
python:3.8-slim-buster
Ler o Dockerfile
▍Imagem básica
Vamos começar com uma imagem de base:
FROM debian:buster-slim
Acontece que a imagem base
python:3.8-slim-buster
é Debian GNU / Linux 10, a versão estável atual do Debian, também conhecido como Buster (as versões do Debian têm o nome de personagens do Toy Story). Buster é, se alguém estiver interessado, o cachorro de Andy.
Portanto, no centro da imagem que nos interessa está a distribuição Linux, que garante seu funcionamento estável. Correções de bugs são lançadas periodicamente para esta distribuição. A variante tem
slim
menos pacotes instalados do que a variante regular. Lá, por exemplo, não existem compiladores.
▍ Variáveis de ambiente
Agora vamos dar uma olhada nas variáveis de ambiente. O primeiro garante que ele seja adicionado o
/usr/local/bin
mais cedo possível $PATH
.
# python, ,
ENV PATH /usr/local/bin:$PATH
A imagem foi projetada para que o Python seja instalado
/usr/local
. Como resultado, essa construção garante que os executáveis instalados serão usados por padrão.
A seguir, vamos dar uma olhada nas configurações de idioma:
# http://bugs.python.org/issue19846
# > "LANG=C" Linux * Python 3*, .
ENV LANG C.UTF-8
Pelo que eu sei, o Python 3 moderno, por padrão, e sem essa configuração, usa UTF-8. Portanto, não tenho certeza se essa linha é necessária no Dockerfile em questão atualmente.
Também existe uma variável de ambiente que contém informações sobre a versão atual do Python:
ENV PYTHON_VERSION 3.8.5
Há também uma variável de ambiente com chave GPG no Dockerfile, que é usada para verificar o código-fonte Python carregado.
▍ Dependências de tempo de execução
O Python precisa de alguns pacotes adicionais para funcionar:
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
netbase \
&& rm -rf /var/lib/apt/lists/*
O primeiro pacote ,,
ca-certificates
contém uma lista de certificados CA padrão. Algo semelhante é usado pelo navegador para validar -addresses . Isso permite que o Python wget
e outras ferramentas validem os certificados fornecidos pelos servidores.
O segundo pacote,
netbase
que realiza a instalação em /etc
vários arquivos, é necessário para configurar o mapeamento de determinados nomes para determinadas portas e protocolos. Por exemplo, /etc/services
é responsável por configurar a correspondência de nomes de serviços, como https
, com números de portas. Nesse caso, é 443/tcp
.
▍ Instalar Python
O kit de ferramentas de compilação agora está sendo instalado. Ou seja, o código-fonte Python é baixado e compilado e, em seguida, pacotes Debian desnecessários são desinstalados:
RUN set -ex \
\
&& savedAptMark="$(apt-mark showmanual)" \
&& apt-get update && apt-get install -y --no-install-recommends \
dpkg-dev \
gcc \
libbluetooth-dev \
libbz2-dev \
libc6-dev \
libexpat1-dev \
libffi-dev \
libgdbm-dev \
liblzma-dev \
libncursesw5-dev \
libreadline-dev \
libsqlite3-dev \
libssl-dev \
make \
tk-dev \
uuid-dev \
wget \
xz-utils \
zlib1g-dev \
# Stretch "gpg"
$(command -v gpg > /dev/null || echo 'gnupg dirmngr') \
\
&& wget -O python.tar.xz "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz" \
&& wget -O python.tar.xz.asc "https://www.python.org/ftp/python/${PYTHON_VERSION%%[a-z]*}/Python-$PYTHON_VERSION.tar.xz.asc" \
&& export GNUPGHOME="$(mktemp -d)" \
&& gpg --batch --keyserver ha.pool.sks-keyservers.net --recv-keys "$GPG_KEY" \
&& gpg --batch --verify python.tar.xz.asc python.tar.xz \
&& { command -v gpgconf > /dev/null && gpgconf --kill all || :; } \
&& rm -rf "$GNUPGHOME" python.tar.xz.asc \
&& mkdir -p /usr/src/python \
&& tar -xJC /usr/src/python --strip-components=1 -f python.tar.xz \
&& rm python.tar.xz \
\
&& cd /usr/src/python \
&& gnuArch="$(dpkg-architecture --query DEB_BUILD_GNU_TYPE)" \
&& ./configure \
--build="$gnuArch" \
--enable-loadable-sqlite-extensions \
--enable-optimizations \
--enable-option-checking=fatal \
--enable-shared \
--with-system-expat \
--with-system-ffi \
--without-ensurepip \
&& make -j "$(nproc)" \
LDFLAGS="-Wl,--strip-all" \
&& make install \
&& rm -rf /usr/src/python \
\
&& find /usr/local -depth \
\( \
\( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \
-o \( -type f -a \( -name '*.pyc' -o -name '*.pyo' -o -name '*.a' \) \) \
-o \( -type f -a -name 'wininst-*.exe' \) \
\) -exec rm -rf '{}' + \
\
&& ldconfig \
\
&& apt-mark auto '.*' > /dev/null \
&& apt-mark manual $savedAptMark \
&& find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec ldd '{}' ';' \
| awk '/=>/ { print $(NF-1) }' \
| sort -u \
| xargs -r dpkg-query --search \
| cut -d: -f1 \
| sort -u \
| xargs -r apt-mark manual \
&& apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false \
&& rm -rf /var/lib/apt/lists/* \
\
&& python3 --version
Há muita coisa acontecendo aqui, mas o mais importante é o seguinte:
- Python está instalado em
/usr/local
. - Todos os arquivos .pyc são removidos.
- Pacotes, em particular -
gcc
e outros do tipo que eram necessários para compilar o Python, são removidos depois que não são mais necessários.
Pelo fato de tudo isso acontecer em um único comando
RUN
, o resultado é que o compilador não fica armazenado em nenhuma das camadas, o que ajuda a manter o tamanho compacto da imagem.
Aqui você pode notar que o Python precisa de uma biblioteca para compilar
libbluetooth-dev
. Isso parecia incomum para mim, então decidi descobrir. Acontece que o Python pode criar soquetes Bluetooth, mas apenas se compilado usando esta biblioteca.
▍ Configuração de link simbólico
A próxima etapa
/usr/local/bin/python3
é atribuir um link simbólico /usr/local/bin/python
, que permite que o Python seja chamado de diferentes maneiras:
# ,
RUN cd /usr/local/bin \
&& ln -s idle3 idle \
&& ln -s pydoc3 pydoc \
&& ln -s python3 python \
&& ln -s python3-config python-config
▍Instalar pip
O gerenciador de pacotes
pip
tem sua própria programação de lançamento, que difere da programação de lançamento do Python. Por exemplo, este Dockerfile instala o Python 3.8.5, lançado em julho de 2020. E o pip 20.2.2 foi lançado em agosto, depois que o Python foi lançado, mas o Dockerfile foi projetado para ter uma nova versão instalada pip
:
# "PIP_VERSION", pip : "ValueError: invalid truth value '<VERSION>'"
ENV PYTHON_PIP_VERSION 20.2.2
# https://github.com/pypa/get-pip
ENV PYTHON_GET_PIP_URL https://github.com/pypa/get-pip/raw/5578af97f8b2b466f4cdbebe18a3ba2d48ad1434/get-pip.py
ENV PYTHON_GET_PIP_SHA256 d4d62a0850fe0c2e6325b2cc20d818c580563de5a2038f917e3cb0e25280b4d1
RUN set -ex; \
\
savedAptMark="$(apt-mark showmanual)"; \
apt-get update; \
apt-get install -y --no-install-recommends wget; \
\
wget -O get-pip.py "$PYTHON_GET_PIP_URL"; \
echo "$PYTHON_GET_PIP_SHA256 *get-pip.py" | sha256sum --check --strict -; \
\
apt-mark auto '.*' > /dev/null; \
[ -z "$savedAptMark" ] || apt-mark manual $savedAptMark; \
apt-get purge -y --auto-remove -o APT::AutoRemove::RecommendsImportant=false; \
rm -rf /var/lib/apt/lists/*; \
\
python get-pip.py \
--disable-pip-version-check \
--no-cache-dir \
"pip==$PYTHON_PIP_VERSION" \
; \
pip --version; \
\
find /usr/local -depth \
\( \
\( -type d -a \( -name test -o -name tests -o -name idle_test \) \) \
-o \
\( -type f -a \( -name '*.pyc' -o -name '*.pyo' \) \) \
\) -exec rm -rf '{}' +; \
rm -f get-pip.py
Depois de concluir essas operações, como antes, todos os arquivos .pyc são excluídos.
▍ Ponto de entrada da imagem
Como resultado, o ponto de entrada para a imagem é especificado no Dockerfile:
CMD ["python3"]
Usando
CMD
, em vez disso, ENTRYPOINT
lançamos a imagem, por padrão temos acesso ao python:
$ docker run -it python:3.8-slim-buster
Python 3.8.5 (default, Aug 4 2020, 16:24:08)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>>
Mas, se necessário, você pode especificar outros arquivos executáveis ao iniciar a imagem:
$ docker run -it python:3.8-slim-buster bash
root@280c9b73e8f9:/#
Resultado
Aqui está o que aprendemos ao analisar o Dockerfile de imagem oficial do Python
slim-buster
.
▍A imagem inclui Python
Embora isso possa parecer óbvio, vale a pena prestar atenção em exatamente como o Python está incluído na imagem. Ou seja, isso é feito instalando-o em
/usr/local
.
Os programadores que usam essa imagem às vezes cometem o mesmo erro, que é reinstalar a versão Debian do Python:
FROM python:3.8-slim-buster
# :
RUN apt-get update && apt-get install python3-dev
Ao executar este comando, o
RUN
Python será instalado novamente, mas em /usr
, não em /usr/local
. E esta geralmente não será a versão do Python que está instalada /usr/local
. E o programador que usou o arquivo Docker acima provavelmente não precisa de duas versões diferentes do Python na mesma imagem. Este é principalmente o motivo da confusão.
E se alguém realmente precisa de uma versão Debian do Python, então seria melhor usá-la como imagem base
debian:buster-slim
.
▍ A imagem inclui a última versão do pip
Por exemplo, a versão mais recente do Python 3.5 foi em novembro de 2019, mas a imagem do Docker
python:3.5-slim-buster
inclui pip
aquela que foi lançada em agosto de 2020. Isso é (geralmente) bom, pois significa que temos as últimas correções de bugs e melhorias de desempenho. Isso também significa que podemos nos beneficiar do suporte para opções de rodas mais recentes.
▍ Todos os arquivos .pyc são removidos da imagem
Se quiser acelerar um pouco a inicialização do sistema, você pode compilar independentemente o código-fonte da biblioteca padrão no formato .pyc. Isso é feito usando o módulo compileall .
▍O Image não instala atualizações de segurança do Debian
Embora as imagens de base
debian:buster-slim
, e python
são atualizados com freqüência, há um certo desfasamento entre o lançamento das atualizações de segurança do Debian e transformando-os em imagens. Portanto, você precisa instalar independentemente as atualizações de segurança para a distribuição básica do Linux.
Quais imagens Docker você usa para executar o código Python?
