python:3.8-slim-buster
Dockerfile lesen
▍Grundbild
Beginnen wir mit einem Basisbild:
FROM debian:buster-slim
Es stellt sich heraus, dass das Basis-Image
python:3.8-slim-busterDebian GNU / Linux 10 ist, die aktuelle stabile Version von Debian, auch bekannt als Buster (Debian-Versionen sind nach Charakteren aus Toy Story benannt). Buster ist, wenn jemand interessiert ist, Andys Hund.
Das Herzstück des Images, an dem wir interessiert sind, ist die Linux-Distribution, die einen stabilen Betrieb garantiert. Für diese Distribution werden regelmäßig Fehlerbehebungen veröffentlicht. In der Variante sind
slimweniger Pakete installiert als in der regulären Variante. Dort gibt es zum Beispiel keine Compiler.
▍Umgebungsvariablen
Schauen wir uns nun die Umgebungsvariablen an. Der erste stellt sicher, dass es
/usr/local/binso früh wie möglich hinzugefügt wird $PATH.
# python, ,
ENV PATH /usr/local/bin:$PATH
Das Image ist so konzipiert, dass Python in installiert ist
/usr/local. Infolgedessen stellt dieses Konstrukt sicher, dass die installierten ausführbaren Dateien standardmäßig verwendet werden.
Schauen wir uns als nächstes die Spracheinstellungen an:
# http://bugs.python.org/issue19846
# > "LANG=C" Linux * Python 3*, .
ENV LANG C.UTF-8
Soweit ich weiß, verwendet modernes Python 3 standardmäßig und ohne diese Einstellung UTF-8. Ich bin mir also nicht sicher, ob diese Zeile heutzutage in der fraglichen Docker-Datei benötigt wird.
Es gibt auch eine Umgebungsvariable, die Informationen zur aktuellen Python-Version enthält:
ENV PYTHON_VERSION 3.8.5
Die Docker-Datei verfügt außerdem über eine Umgebungsvariable mit einem GPG-Schlüssel, mit dem die geladene Python-Quelle überprüft wird.
▍ Laufzeitabhängigkeiten
Python benötigt einige zusätzliche Pakete, um zu funktionieren:
RUN apt-get update && apt-get install -y --no-install-recommends \
ca-certificates \
netbase \
&& rm -rf /var/lib/apt/lists/*
Das erste Paket
ca-certificatesenthält eine Liste der Standard-CA-Zertifikate. Ähnliches wird vom Browser zum Überprüfen von URLs verwendet . Auf diese Weise können Python wgetund andere Tools die von den Servern bereitgestellten Zertifikate überprüfen.
Das zweite Paket,
netbasedas die Installation in /etcmehreren Dateien ausführt , ist erforderlich, um die Zuordnung bestimmter Namen zu bestimmten Ports und Protokollen zu konfigurieren. Beispielsweise ist es /etc/servicesfür die Konfiguration der Entsprechung von Dienstnamen wie httpsPortnummern verantwortlich. In diesem Fall ist es 443/tcp.
▍Installation von Python
Das Kompilierungs-Toolkit wird jetzt installiert. Die Python-Quelle wird nämlich heruntergeladen und kompiliert, wonach unnötige Debian-Pakete deinstalliert werden:
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
Hier ist viel los, aber das Wichtigste ist:
- Python ist in installiert
/usr/local. - Alle .pyc-Dateien werden entfernt.
- Insbesondere Pakete -
gccund andere, die zum Kompilieren von Python benötigt wurden - werden entfernt, nachdem sie nicht mehr benötigt werden.
Aufgrund der Tatsache, dass dies alles in einem einzigen Befehl geschieht
RUN, wird der Compiler in keiner der Ebenen gespeichert, was zur Aufrechterhaltung einer kompakten Bildgröße beiträgt.
Hier können Sie feststellen, dass Python zum Kompilieren eine Bibliothek benötigt
libbluetooth-dev. Das schien mir ungewöhnlich, also beschloss ich, es herauszufinden. Wie sich herausstellt, kann Python Bluetooth-Sockets erstellen, jedoch nur, wenn diese mit dieser Bibliothek kompiliert werden.
▍Symbolic Link Setup
Der nächste Schritt
/usr/local/bin/python3besteht darin, eine symbolische Verknüpfung zuzuweisen /usr/local/bin/python, über die Python auf verschiedene Arten aufgerufen werden kann:
# ,
RUN cd /usr/local/bin \
&& ln -s idle3 idle \
&& ln -s pydoc3 pydoc \
&& ln -s python3 python \
&& ln -s python3-config python-config
PipInstallieren Sie pip
Der Paketmanager
pipverfügt über einen eigenen Release-Zeitplan, der sich vom Python-Release-Zeitplan unterscheidet. In diesem Dockerfile wird beispielsweise Python 3.8.5 installiert, das im Juli 2020 veröffentlicht wurde. Pip 20.2.2 wurde im August veröffentlicht, nachdem Python veröffentlicht wurde. In Dockerfile ist jedoch eine neue Version installiert 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
Nach Abschluss dieser Vorgänge werden nach wie vor alle .pyc-Dateien gelöscht.
▍Bildeinstiegspunkt
Infolgedessen wird der Einstiegspunkt in das Bild in der Docker-Datei angegeben:
CMD ["python3"]
Wenn Sie
CMDstattdessen ENTRYPOINTdas Image starten, erhalten Sie standardmäßig Zugriff auf 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.
>>>
Bei Bedarf können Sie beim Starten des Images jedoch andere ausführbare Dateien angeben:
$ docker run -it python:3.8-slim-buster bash
root@280c9b73e8f9:/#
Ergebnis
Folgendes haben wir gelernt, indem wir die Docker-Datei des offiziellen Python-Images analysiert haben
slim-buster.
▍Das Bild enthält Python
Dies mag offensichtlich erscheinen, es lohnt sich jedoch, genau darauf zu achten, wie Python im Bild enthalten ist. Dies geschieht nämlich durch Installation in
/usr/local.
Programmierer, die dieses Image verwenden, machen manchmal den gleichen Fehler, nämlich die Debian-Version von Python neu zu installieren:
FROM python:3.8-slim-buster
# :
RUN apt-get update && apt-get install python3-dev
Wenn Sie diesen Befehl ausführen, wird
RUNPython erneut installiert, jedoch /usrnicht in /usr/local. Und dies ist normalerweise nicht die Version von Python, in der installiert ist /usr/local. Und der Programmierer, der die obige Docker-Datei verwendet hat, benötigt wahrscheinlich nicht zwei verschiedene Versionen von Python im selben Image. Dies ist hauptsächlich der Grund für die Verwirrung.
Und wenn jemand wirklich eine Debian-Version von Python benötigt, ist es besser, sie als Basis-Image zu verwenden
debian:buster-slim.
▍ Das Bild enthält die neueste Version von pip
Die neueste Version von Python 3.5 war beispielsweise im November 2019, aber das Docker-Image
python:3.5-slim-busterenthält das Image pip, das im August 2020 veröffentlicht wurde. Dies ist (normalerweise) gut, da wir die neuesten Fehlerkorrekturen und Leistungsverbesserungen haben. Dies bedeutet auch, dass wir von der Unterstützung neuerer Radoptionen profitieren können.
▍ Alle .pyc-Dateien werden aus dem Image entfernt
Wenn Sie den Systemstart etwas beschleunigen möchten, können Sie den Quellcode der Standardbibliothek unabhängig im .pyc-Format kompilieren. Dies erfolgt über das Compileall- Modul .
▍Image installiert keine Debian-Sicherheitsupdates
Obwohl die Basisbilder
debian:buster-slimund pythonzwischen der Veröffentlichung der Debian - Sicherheitsaktualisierungen und wandeln sie in Bilder werden häufig aktualisiert, gibt es eine gewisse Lücke. Daher müssen Sie Sicherheitsupdates für die Linux-Basisdistribution unabhängig installieren.
Welche Docker-Images verwenden Sie zum Ausführen von Python-Code?
