Memahami fitur gambar resmi Python Docker

Image resmi Python Docker cukup populer. Ngomong-ngomong, saya sendiri sudah merekomendasikan salah satu variasinya sebagai gambar dasar. Tetapi banyak programmer tidak begitu mengerti cara kerjanya. Hal ini dapat menimbulkan kebingungan dan berbagai masalah. Dalam posting ini, saya akan berbicara tentang bagaimana gambar ini dibuat, bagaimana bisa berguna, tentang penggunaan yang benar dan batasannya. Secara khusus, saya akan memecahnya di sini (dalam keadaan yang diwakili oleh Dockerfile tertanggal 19 Agustus 2020 ) dan memikirkan detail terpenting di sepanjang jalan.







python:3.8-slim-buster



Membaca Dockerfile



▍Gambar dasar



Mari kita mulai dengan gambar dasar:



FROM debian:buster-slim


Ternyata gambar dasarnya python:3.8-slim-busteradalah Debian GNU / Linux 10, rilis stabil Debian saat ini, juga dikenal sebagai Buster (rilis Debian dinamai karakter dari Toy Story). Buster adalah, jika ada yang tertarik, anjing Andy.



Jadi, inti dari gambar yang kami minati adalah distribusi Linux, yang menjamin operasi yang stabil. Perbaikan bug dirilis secara berkala untuk distribusi ini. Varian memiliki slimlebih sedikit paket yang dipasang daripada varian biasa. Di sana, misalnya, tidak ada kompiler.



▍ Variabel Lingkungan



Sekarang mari kita lihat variabel lingkungan. Memastikan pertama bahwa itu ditambahkan /usr/local/binsebagai sedini mungkin $PATH.



#     python,   ,    
ENV PATH /usr/local/bin:$PATH


Gambar dirancang sedemikian rupa sehingga penginstalan Python selesai di /usr/local. Akibatnya, konstruksi ini memastikan bahwa executable yang diinstal akan digunakan secara default.



Selanjutnya, mari kita lihat pengaturan bahasa:



# http://bugs.python.org/issue19846
# >     "LANG=C"  Linux *    Python 3*,   .
ENV LANG C.UTF-8


Sejauh yang saya tahu, Python 3 modern, secara default, dan tanpa pengaturan ini, menggunakan UTF-8. Jadi saya tidak yakin apakah baris ini diperlukan di Dockerfile yang dimaksud belakangan ini.



Ada juga variabel lingkungan yang berisi informasi tentang versi Python saat ini:



ENV PYTHON_VERSION 3.8.5


Dockerfile juga memiliki variabel lingkungan dengan kunci GPG yang digunakan untuk memverifikasi sumber Python yang sedang dimuat.



▍Ketergantungan runtime



Python membutuhkan beberapa paket tambahan untuk bekerja:



RUN apt-get update && apt-get install -y --no-install-recommends \
    ca-certificates \
    netbase \
  && rm -rf /var/lib/apt/lists/*


Paket pertama ,, ca-certificatesberisi daftar sertifikat CA standar. Hal serupa digunakan oleh browser untuk memvalidasi -alamat . Ini memungkinkan Python wgetdan alat lain untuk memvalidasi sertifikat yang disediakan oleh server.



Paket kedua, netbaseyang melakukan penginstalan di /etcbeberapa file, diperlukan untuk mengkonfigurasi pemetaan nama tertentu ke port dan protokol tertentu. Misalnya, /etc/servicesbertanggung jawab untuk mengkonfigurasi korespondensi nama layanan, seperti https, dengan nomor port. Dalam hal ini, memang demikian 443/tcp.



▍ Instal Python



Toolkit kompilasi sekarang sedang diinstal. Yakni, sumber Python diunduh dan dikompilasi, dan kemudian paket Debian yang tidak perlu dihapus:



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


Ada banyak hal yang terjadi di sini, tetapi yang terpenting adalah ini:



  1. Python dipasang di /usr/local.
  2. Semua file .pyc dihapus.
  3. Paket, khususnya - gccdan jenis lain yang diperlukan untuk mengkompilasi Python, dihapus setelah tidak lagi diperlukan.


Karena fakta bahwa semua ini terjadi dalam satu perintah RUN, sebagai akibatnya, kompilator tidak disimpan di salah satu lapisan, yang membantu menjaga ukuran gambar yang ringkas.



Di sini Anda dapat mencatat bahwa Python membutuhkan perpustakaan untuk dikompilasi libbluetooth-dev. Ini tampak tidak biasa bagi saya, jadi saya memutuskan untuk mencari tahu. Ternyata, Python dapat membuat soket Bluetooth, tetapi hanya jika dikompilasi menggunakan pustaka ini.



▍Penyiapan tautan simbolik



Langkah selanjutnya /usr/local/bin/python3adalah menetapkan tautan simbolik /usr/local/bin/python, yang memungkinkan Python dipanggil dengan berbagai cara:



#     ,     
RUN cd /usr/local/bin \
  && ln -s idle3 idle \
  && ln -s pydoc3 pydoc \
  && ln -s python3 python \
  && ln -s python3-config python-config


▍ Instal pip



Manajer paket pipmemiliki jadwal rilisnya sendiri yang berbeda dari jadwal rilis Python. Misalnya, Dockerfile ini menginstal Python 3.8.5, dirilis pada Juli 2020. Dan pip 20.2.2 dirilis pada Agustus, setelah Python dirilis, tetapi Dockerfile dirancang untuk menginstal versi baru 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


Setelah menyelesaikan operasi ini, seperti sebelumnya, semua file .pyc akan dihapus.



▍Titik masuk gambar



Akibatnya, titik masuk ke image ditentukan di Dockerfile:



CMD ["python3"]


Menggunakan CMDsebaliknya, ENTRYPOINTkami meluncurkan gambar, secara default kita mendapatkan akses ke 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.
>>>


Namun, jika perlu, Anda dapat menentukan file lain yang dapat dijalankan saat memulai gambar:



$ docker run -it python:3.8-slim-buster bash
root@280c9b73e8f9:/#


Hasil



Inilah yang kami pelajari dengan mengurai image resmi Python Dockerfile slim-buster.



▍Gambar tersebut menyertakan Python



Meskipun ini mungkin tampak jelas, perlu diperhatikan bagaimana Python disertakan dalam gambar. Yakni, ini dilakukan dengan menginstalnya di /usr/local.



Pemrogram yang menggunakan gambar ini terkadang membuat kesalahan yang sama, yaitu menginstal ulang Python versi Debian:



FROM python:3.8-slim-buster

#    :
RUN apt-get update && apt-get install python3-dev


Saat Anda menjalankan perintah ini, RUNPython akan diinstal lagi, tetapi di /usr, bukan di /usr/local. Dan ini biasanya bukan versi Python yang diinstal /usr/local. Dan programmer yang menggunakan file Docker di atas mungkin tidak membutuhkan dua versi Python yang berbeda dalam gambar yang sama. Ini terutama alasan kebingungan.



Dan jika seseorang benar-benar membutuhkan versi Debian dari Python, maka akan lebih baik jika menggunakannya sebagai gambar dasar debian:buster-slim.



▍ Gambar menyertakan versi pip terbaru



Misalnya, Python 3.5 rilis terbaru pada November 2019, tetapi image Docker python:3.5-slim-bustermenyertakan pipyang keluar pada Agustus 2020. Ini (biasanya) bagus, karena itu berarti kami memiliki perbaikan bug terbaru dan peningkatan kinerja. Ini juga berarti bahwa kami dapat memanfaatkan dukungan untuk opsi roda yang lebih baru.



▍ Semua file .pyc dihapus dari gambar



Jika Anda ingin sedikit mempercepat boot sistem, Anda dapat mengompilasi sendiri kode sumber pustaka standar ke dalam format .pyc. Ini dilakukan dengan menggunakan modul compileall .



▍Gambar tidak menginstal pembaruan keamanan Debian



Meskipun gambar dasar debian:buster-slim, dan pythonsering diperbarui, ada celah tertentu antara rilis pembaruan keamanan Debian dan mengubahnya menjadi gambar. Oleh karena itu, Anda perlu menginstal pembaruan keamanan secara mandiri untuk distribusi Linux dasar.



Gambar Docker apa yang Anda gunakan untuk menjalankan kode Python?






All Articles