web-dev-qa-db-fra.com

Pourquoi faut-il des siècles pour installer Pandas sur Alpine Linux

J'ai remarqué que l'installation de Pandas et de Numpy (sa dépendance) dans un conteneur Docker utilisant le système d'exploitation de base Alpine vs. CentOS ou Debian prend beaucoup plus de temps. J'ai créé un petit test ci-dessous pour démontrer la différence de temps. Mis à part les quelques secondes nécessaires à Alpine pour mettre à jour et télécharger les dépendances de construction pour installer Pandas et Numpy, pourquoi setup.py prend-il environ 70 fois plus de temps que sous Debian?

Existe-t-il un moyen d'accélérer l'installation en utilisant Alpine comme image de base ou existe-t-il une autre image de base de taille comparable à Alpine, qu'il est préférable d'utiliser pour des packages tels que Pandas et Numpy?

Dockerfile.debian

FROM python:3.6.4-slim-jessie

RUN pip install pandas

Construire une image Debian avec Pandas & Numpy:

[PandasDockerTest] time docker build -t debian-pandas -f Dockerfile.debian . --no-cache
    Sending build context to Docker daemon  3.072kB
    Step 1/2 : FROM python:3.6.4-slim-jessie
     ---> 43431c5410f3
    Step 2/2 : RUN pip install pandas
     ---> Running in 2e4c030f8051
    Collecting pandas
      Downloading pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl (26.2MB)
    Collecting numpy>=1.9.0 (from pandas)
      Downloading numpy-1.14.1-cp36-cp36m-manylinux1_x86_64.whl (12.2MB)
    Collecting pytz>=2011k (from pandas)
      Downloading pytz-2018.3-py2.py3-none-any.whl (509kB)
    Collecting python-dateutil>=2 (from pandas)
      Downloading python_dateutil-2.6.1-py2.py3-none-any.whl (194kB)
    Collecting six>=1.5 (from python-dateutil>=2->pandas)
      Downloading six-1.11.0-py2.py3-none-any.whl
    Installing collected packages: numpy, pytz, six, python-dateutil, pandas
    Successfully installed numpy-1.14.1 pandas-0.22.0 python-dateutil-2.6.1 pytz-2018.3 six-1.11.0
    Removing intermediate container 2e4c030f8051
     ---> a71e1c314897
    Successfully built a71e1c314897
    Successfully tagged debian-pandas:latest
    docker build -t debian-pandas -f Dockerfile.debian . --no-cache  0.07s user 0.06s system 0% cpu 13.605 total

Dockerfile.Alpine

FROM python:3.6.4-Alpine3.7

RUN apk --update add --no-cache g++

RUN pip install pandas

Créer une image alpine avec Pandas & Numpy:

[PandasDockerTest] time docker build -t Alpine-pandas -f Dockerfile.Alpine . --no-cache
Sending build context to Docker daemon   16.9kB
Step 1/3 : FROM python:3.6.4-Alpine3.7
 ---> 4b00a94b6f26
Step 2/3 : RUN apk --update add --no-cache g++
 ---> Running in 4b0c32551e3f
fetch http://dl-cdn.alpinelinux.org/Alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/Alpine/v3.7/main/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/Alpine/v3.7/community/x86_64/APKINDEX.tar.gz
fetch http://dl-cdn.alpinelinux.org/Alpine/v3.7/community/x86_64/APKINDEX.tar.gz
(1/17) Upgrading musl (1.1.18-r2 -> 1.1.18-r3)
(2/17) Installing libgcc (6.4.0-r5)
(3/17) Installing libstdc++ (6.4.0-r5)
(4/17) Installing binutils-libs (2.28-r3)
(5/17) Installing binutils (2.28-r3)
(6/17) Installing gmp (6.1.2-r1)
(7/17) Installing isl (0.18-r0)
(8/17) Installing libgomp (6.4.0-r5)
(9/17) Installing libatomic (6.4.0-r5)
(10/17) Installing pkgconf (1.3.10-r0)
(11/17) Installing mpfr3 (3.1.5-r1)
(12/17) Installing mpc1 (1.0.3-r1)
(13/17) Installing gcc (6.4.0-r5)
(14/17) Installing musl-dev (1.1.18-r3)
(15/17) Installing libc-dev (0.7.1-r0)
(16/17) Installing g++ (6.4.0-r5)
(17/17) Upgrading musl-utils (1.1.18-r2 -> 1.1.18-r3)
Executing busybox-1.27.2-r7.trigger
OK: 184 MiB in 50 packages
Removing intermediate container 4b0c32551e3f
 ---> be26c3bf4e42
Step 3/3 : RUN pip install pandas
 ---> Running in 36f6024e5e2d
Collecting pandas
  Downloading pandas-0.22.0.tar.gz (11.3MB)
Collecting python-dateutil>=2 (from pandas)
  Downloading python_dateutil-2.6.1-py2.py3-none-any.whl (194kB)
Collecting pytz>=2011k (from pandas)
  Downloading pytz-2018.3-py2.py3-none-any.whl (509kB)
Collecting numpy>=1.9.0 (from pandas)
  Downloading numpy-1.14.1.Zip (4.9MB)
Collecting six>=1.5 (from python-dateutil>=2->pandas)
  Downloading six-1.11.0-py2.py3-none-any.whl
Building wheels for collected packages: pandas, numpy
  Running setup.py bdist_wheel for pandas: started
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: still running...
  Running setup.py bdist_wheel for pandas: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/e8/ed/46/0596b51014f3cc49259e52dff9824e1c6fe352048a2656fc92
  Running setup.py bdist_wheel for numpy: started
  Running setup.py bdist_wheel for numpy: still running...
  Running setup.py bdist_wheel for numpy: still running...
  Running setup.py bdist_wheel for numpy: still running...
  Running setup.py bdist_wheel for numpy: finished with status 'done'
  Stored in directory: /root/.cache/pip/wheels/9d/cd/e1/4d418b16ea662e512349ef193ed9d9ff473af715110798c984
Successfully built pandas numpy
Installing collected packages: six, python-dateutil, pytz, numpy, pandas
Successfully installed numpy-1.14.1 pandas-0.22.0 python-dateutil-2.6.1 pytz-2018.3 six-1.11.0
Removing intermediate container 36f6024e5e2d
 ---> a93c59e6a106
Successfully built a93c59e6a106
Successfully tagged Alpine-pandas:latest
docker build -t Alpine-pandas -f Dockerfile.Alpine . --no-cache  0.54s user 0.33s system 0% cpu 16:08.47 total
48
moku

Les images basées sur Debian utilisent uniquement python pip pour installer les paquets au format .whl:

  Downloading pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl (26.2MB)
  Downloading numpy-1.14.1-cp36-cp36m-manylinux1_x86_64.whl (12.2MB)

Le format WHL a été développé comme une méthode plus rapide et plus fiable pour installer le logiciel Python que de reconstruire chaque fois à partir du code source. Les fichiers WHL doivent uniquement être déplacés vers le bon emplacement sur le système cible à installer, tandis qu'une distribution source nécessite une étape de compilation avant l'installation.

Les ensembles de roues pandas et numpy ne sont pas pris en charge dans les images basées sur la plate-forme Alpine. C'est pourquoi, lorsque nous les installons à l'aide de python pip pendant le processus de construction, nous les compilons toujours à partir des fichiers source d'Alpine:

  Downloading pandas-0.22.0.tar.gz (11.3MB)
  Downloading numpy-1.14.1.Zip (4.9MB)

et nous pouvons voir les éléments suivants dans le conteneur lors de la création de l'image:

/ # ps aux
PID   USER     TIME   COMMAND
    1 root       0:00 /bin/sh -c pip install pandas
    7 root       0:04 {pip} /usr/local/bin/python /usr/local/bin/pip install pandas
   21 root       0:07 /usr/local/bin/python -c import setuptools, tokenize;__file__='/tmp/pip-build-en29h0ak/pandas/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n
  496 root       0:00 sh
  660 root       0:00 /bin/sh -c gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DTHREAD_STACK_SIZE=0x100000 -fPIC -Ibuild/src.linux-x86_64-3.6/numpy/core/src/pri
  661 root       0:00 gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -DTHREAD_STACK_SIZE=0x100000 -fPIC -Ibuild/src.linux-x86_64-3.6/numpy/core/src/private -Inump
  662 root       0:00 /usr/libexec/gcc/x86_64-Alpine-linux-musl/6.4.0/cc1 -quiet -I build/src.linux-x86_64-3.6/numpy/core/src/private -I numpy/core/include -I build/src.linux-x86_64-3.6/numpy/core/includ
  663 root       0:00 ps aux

Si nous modifions un peu Dockerfile:

FROM python:3.6.4-Alpine3.7
RUN apk add --no-cache g++ wget
RUN wget https://pypi.python.org/packages/da/c6/0936bc5814b429fddb5d6252566fe73a3e40372e6ceaf87de3dec1326f28/pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl
RUN pip install pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl

nous obtenons l'erreur suivante:

Step 4/4 : RUN pip install pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl
 ---> Running in 0faea63e2bda
pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl is not a supported wheel on this platform.
The command '/bin/sh -c pip install pandas-0.22.0-cp36-cp36m-manylinux1_x86_64.whl' returned a non-zero code: 1

Malheureusement, le seul moyen d'installer pandas sur une image alpine est d'attendre la fin de la construction.

Bien sûr, si vous souhaitez utiliser l'image Alpine avec pandas dans CI, par exemple, la meilleure façon de le faire est de la compiler une fois. Transférez-la dans n'importe quel registre et utilisez-la comme image de base pour vos besoins.

EDIT: Si vous voulez utiliser l'image alpine avec pandas, vous pouvez tirer mon nickgryg/Alpine-pandas image de docker. C'est une image python avec pandas pré-compilée sur la plate-forme Alpine. Cela devrait vous faire gagner du temps.

37
Nickolay

[Mise à jour:]

RÉPONSE: CE N'EST PAS!

Dans n'importe quel fichier de docker alpin, vous pouvez simplement faire *

RUN apk add py2-numpy@community py2-scipy@community py-pandas@Edge

En effet, numpy, scipy et maintenant pandas sont tous disponibles prédéfinis sur Alpine:

https://pkgs.alpinelinux.org/packages?name=*numpy

https://pkgs.alpinelinux.org/packages?name=*scipy&branch=Edge

https://pkgs.alpinelinux.org/packages?name=*pandas&branch=Edge

Une façon d'éviter de reconstruire à chaque fois, ou d'utiliser une couche Docker, consiste à utiliser un paquetage natif Alpine Linux/.apk pré-construit, par exemple .

https://github.com/sgerrand/Alpine-pkg-py-pandas

https://github.com/nbgallery/apks

Vous pouvez construire ces .apk une fois et les utiliser n'importe où dans votre fichier Docker :)

Cela vous évite également de devoir tout incorporer dans l'image Docker avant le fait - c'est-à-dire la possibilité de pré-construire n'importe quelle image Docker de votre choix.

Post-scriptum J'ai mis un stub Dockerfile à https://Gist.github.com/jtlz2/b0f4bc07ce2ff04bc193337f2327c13b qui montre approximativement comment construire l'image. Celles-ci incluent les étapes importantes (*):

RUN echo "@community http://dl-cdn.alpinelinux.org/Alpine/Edge/community" >> /etc/apk/repositories
RUN apk update
RUN apk add --update --no-cache libgfortran
17
jtlz2