Installieren Sie das C-sprachabhängige Modul von Python im Wheel-Format mit mehrstufigem Build

Hintergrund

Die Pip-Installation eines C-sprachabhängigen Moduls mit Alpine macht es schwer

Verfahren

  1. Erstellen Sie die erforderlichen Module auf dem Alpenbild
  2. Sammeln Sie die Produkte (Radfeilen) zur einfachen Wiederverwendung an einem Ort
  3. Drücken Sie als erstelltes Image auf den Docker-Hub
  4. Holen Sie sich nur das Wheel-Verzeichnis mit mehrstufigem Build in Alpine für die Ausführungsumgebung und installieren Sie es
  5. Bestätigung und Reinigung

Implementierung

Holen Sie sich zunächst die erforderlichen Modul-Counties Dieses Mal werde ich die folgenden Module vorstellen

requirements.txt


cycler==0.10.0
Cython==0.29.17
h5py==2.10.0
joblib==0.14.1
kiwisolver==1.2.0
matplotlib==3.2.1
numpy==1.18.4
pandas==1.0.3
Pillow==7.1.2
pyparsing==2.4.7
python-dateutil==2.8.1
pytz==2020.1
scikit-learn==0.22.2.post1
scipy==1.3.3
six==1.14.0

Sammeln Sie die erforderlichen Module an einem Ort

Im Falle von Alpine fällt das Komprimierungsformat wie tar und zip für c-sprachabhängige Module ab. Diese müssen in das whl-Format konvertiert werden.

Vorbereitung

Für die Konvertierung in whl sollte eine Bibliothek erforderlich sein. Installieren Sie sie daher über apk

apk update \
  && apk add --virtual .build --no-cache openblas-dev lapack-dev freetype-dev 
...
  && apk add --virtual .community_build --no-cache -X http://dl-cdn.alpinelinux.org/alpine/edge/community hdf5-dev

Bereiten Sie die erforderliche whl-Datei vor

Sie können das Modul auch mit "pip download" herunterladen. Verwenden Sie den Befehl pip Wheel, da er die tar / zip-Datei herunterlädt, automatisch extrahiert und erstellt. Da "Pip Wheel" auch die Option "-r" verwenden kann, geben Sie die Versionsdatei mit "Pip Freeze> Requirements.txt" an.

pip wheel --no-cache --wheel-dir=./whl -r requirements.txt

Ergänzung bei Verwendung von Pip Wheel

Leider scheitert es in diesem Fall ** unterwegs ** Ich verwende require.txt, das in einer anderen alpinen Umgebung gebaut und pip eingefroren wurde. scikit-learn fällt während des Builds, weil numpy und scipy nicht verfügbar sind.

Mit pip install -r require.txt wird die Pip-Seite es gut installieren, aber [^ 1] [^ 1]: Da die Installationsreihenfolge von pip auf einmal ausgeführt wird, ohne abhängige Bibliotheken und Prioritäten zu berücksichtigen, tritt das gleiche Phänomen bei "pip install" auf. Stattdessen werden Module, die aufgrund "zirkulärer Abhängigkeit" in der Mitte ausfallen, vermieden, indem der Build erneut ausgeführt wird, sobald alle anderen Module installiert wurden. Nur dieses Mal bleibt keine andere Wahl, als die abhängigen Module an die erste Stelle zu setzen. [^ 2]

[^ 2]: Wenn scipy ~ = 1.4 in der vorliegenden Umgebung ist, tritt ein Fehler auf und er schlägt fehl. Geben Sie daher die 1.3-Reihe an, die gehorsam eingegeben wurde

pip install cython numpy==1.18.4 scipy==1.3.3
pip wheel --no-cache --wheel-dir=./whl -r requirements.txt

Ich habe versucht, ein separates Bild zu erstellen, um zu vermeiden, dass es numpy und scipy wird Ich habe das Gefühl, etwas Sinnloses zu tun ...?

Nach Abschluss des Builds auf "Docker Hub" drücken

Richtig markieren und drücken

docker tag 123456789a hoge/builder-image:latest
docker push hoge/builder-image:latest

Bringen Sie das Produkt für die Ausführungsumgebung

Von hier aus werden wir an der Docker-Datei für die Ausführungsumgebung arbeiten.

Installieren Sie das Rad im lokalen Verzeichnis

Um mehrere Module mit pip install anzugeben, schreiben Sie solide oder geben Sie eine Textdatei mit --requirement an. Es gibt keine Spezifikation, mit der Sie whl in einem geeigneten Verzeichnis sammeln und vollständig installieren können.

Installieren Sie dieses Mal vom lokalen Rad aus das Verzeichnis COPY, das das Rad im mehrstufigen Build enthält, und führen Sie den folgenden Befehl aus.

pip install --no-index --no-deps --no-cache-dir -f ./whl -r requirement.txt

Entsprechendes Modul mit --upgrade

Module, die Sie mit der Option "--upgrade" installieren möchten, z. B. pip und setuptools, werden separat in der Upgrade-Textdatei installiert. Die Textdatei, auf die mit der Option -r verwiesen wird, kann ohne Angabe der Version installiert werden.

upgrade.txt


pip
setuptools
wheel

Aktualisieren Sie die in einem bestimmten Verzeichnis gruppierten Module mit dem folgenden Befehl

pip install -U --no-index --no-deps --no-cache-dir -f ./upgrade  -r upgrade.txt

Da sich jedoch die Anzahl der zu verwaltenden Dateien erhöht, ist es besser, direkt in die Docker-Datei zu schreiben, es sei denn, Sie befinden sich in einer Offline-Umgebung.

Ausführungsbestätigung

Überprüfen Sie, ob es importiert werden kann. Erstellen Sie eine Shell-Datei und drücken Sie direkt den Befehl RUN.

import_test.sh


#!/bin/sh
python -c "import numpy"
python -c "import scipy"
python -c "import h5py"
python -c "import pandas"
python -c "import matplotlib"
python -c "import sklearn"

Aufräumen

Entfernen Sie zusätzliche Dateien, um das Gewicht des Docker-Images zu verringern Das Image, das zum Erstellen von whl verwendet wird, muss nur ein Produkt enthalten. Löschen Sie also alles andere.

builder-image


apk del --purge .build .testing_build
pip freeze | xargs pip uninstall -y
pip cache purge

Überprüfen Sie, wie hell das erstellte Image ist, indem Sie die zusätzlichen Dateien löschen. ** 360MB ** scheint beim Abnehmen erfolgreich gewesen zu sein

# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
naka345/wheel_build     latest              b6c9df898334        9 minutes ago       1.04GB 
naka345/wheel_build     latest              3236cf2f87de        2 days ago          639MB

Als nächstes folgt die Anordnung auf der Seite der Ausführungsumgebung. Offizieller Python Docker ist sehr intelligent, daher werde ich die Datei entsprechend löschen. [^ 3]

[^ 3]: In der Ausführungsumgebung, in der -no-cache-dir installiert ist, wird bei Ausführung von pip cache purge die Cache-Datei nicht gefunden und ein Fehlercode zurückgegeben. Es ist nüchtern und schwer zu bedienen.

execution-image


#Sammeln Sie nur die für das Modul erforderlichen Dateien als neues virtuelles Paket.
find /usr/local -type f -executable -not \( -name '*tkinter*' \) -exec scanelf --needed --nobanner --format '%n#p' '{}' ';' \
    | tr ',' '\n' \
    | sort -u \
    | awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
    | xargs -rt apk add --no-cache --virtual .module-rundeps && \
  #Löschen Sie alle zur Erstellungszeit verwendeten Pakete
  apk del --purge .build .community_build
#Löschen Sie zusätzliche Dateien und Müll auf der Python-Seite
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 '{}' + 

#Staubreinigung für diesen Ausführungsbereich
rm -rf /tmp/whl

Vergleichen wir es mit der Zeit, als es auf der Seite der Ausführungsumgebung nicht gelöscht wurde.

# docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
naka345/wheel_install   latest              f0df8a9887de        3 hours ago         1.29GB
↓
naka345/wheel_install   latest              27b4805053f2        3 hours ago         968MB

Ich habe es geschafft, es unter 1 GB zu halten.

Versuchen Sie, daraus eine Docker-Datei zu machen

Schreiben Sie es auf der Grundlage des oben Gesagten in die Docker-Datei. Da es lange dauern wird, habe ich den [Github-Link] eingefügt (https://github.com/naka345/qiita_product/tree/master/docker/wheel_build).

Zusammenfassung

Wir haben es möglich gemacht, zeitaufwändige Module sicher und relativ schnell per Pip einzubringen. Das Docker-Bild war auch etwas heller.

Der Teil, der mehrere Bilder enthalten muss, wird jedoch zurückgestellt. Da die Konsistenz von require.txt erforderlich ist, Wäre es einfacher, wenn es einen Mechanismus gäbe, mit dem beide Bilder bei der Aktualisierung auf den Docker-Hub übertragen werden könnten?

Verweise

Recommended Posts

Installieren Sie das C-sprachabhängige Modul von Python im Wheel-Format mit mehrstufigem Build
Modultest mit mehreren Instanzen in C-Sprache
Segfo mit 16 Zeichen in C-Sprache
Ich habe die Zeit gemessen, als ich das C-sprachabhängige Modul mit alpine installiert habe
Erstellen Sie eine Entwicklungsumgebung für die C-Sprache mit einem Container
Versuchen Sie, ein Python-Modul in C-Sprache zu erstellen