为什么在Alpine Linux上安装Pandas需要很长时间

mok*_*oku 66 numpy pandas docker alpine-linux

我注意到使用基本操作系统Alpine与CentOS或Debian在Docker容器中安装Pandas和Numpy(它的依赖关系)需要更长的时间.我在下面创建了一个小测试来演示时差.除了Alpine更新和下载构建依赖项以安装Pandas和Numpy的几秒钟之外,为什么setup.py需要比Debian安装多70倍的时间?

有没有办法加速使用Alpine作为基本图像的安装,或者是否有另一个与Alpine相当的基本图像,最好用于像Pandas和Numpy这样的软件包?

Dockerfile.debian

FROM python:3.6.4-slim-jessie

RUN pip install pandas
Run Code Online (Sandbox Code Playgroud)

使用Pandas&Numpy构建Debian映像:

[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
Run Code Online (Sandbox Code Playgroud)

Dockerfile.alpine

FROM python:3.6.4-alpine3.7

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

RUN pip install pandas
Run Code Online (Sandbox Code Playgroud)

用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
Run Code Online (Sandbox Code Playgroud)

Nic*_*lay 43

基于Debian的映像仅python pip用于安装.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)
Run Code Online (Sandbox Code Playgroud)

WHL格式是作为一种安装Python软件的更快,更可靠的方法而开发的,而不是每次从源代码重建.只需将WHL文件移动到要安装的目标系统上的正确位置,而源分发需要在安装之前进行构建步骤.

轮包pandasnumpy基于高山平台,图像不支持.这就是为什么当我们python pip在构建过程中使用它们时,我们总是从alpine的源文件中编译它们:

  Downloading pandas-0.22.0.tar.gz (11.3MB)
  Downloading numpy-1.14.1.zip (4.9MB)
Run Code Online (Sandbox Code Playgroud)

我们可以在图像构建过程中看到以下内部容器:

/ # 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
Run Code Online (Sandbox Code Playgroud)

如果我们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
Run Code Online (Sandbox Code Playgroud)

我们收到以下错误:

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
Run Code Online (Sandbox Code Playgroud)

不幸的是,安装pandas在Alpine图像上的唯一方法是等到构建完成.

当然,如果您想pandas在CI中使用Alpine图像,最好的方法是编译一次,将其推送到任何注册表并将其用作满足您需求的基本图像.

编辑: 如果你想使用阿尔卑斯山图像,pandas你可以拉我的nickgryg/alpine-pandas docker图像.这是一个pandas在Alpine平台上预编译的python图像.它应该节省你的时间.

  • 嗯,那太糟糕了.但是,看起来六,pytz和python-dateutil正在下载Alpine上的.whl包.这是否意味着它可以为大熊猫制造轮子,为阿尔卑斯山制造numpy,但它目前还没有发生? (3认同)
  • @ jtlz2在答案中添加了一些信息 (2认同)
  • 之所以会出现这种情况,是因为这些wheel包含从c/c++构建并与glibc链接的二进制文件,但alpine没有glibc,而是使用musl,这意味着新的二进制文件必须针对musl进行编译和链接。 (2认同)

jtl*_*lz2 20

[更新:]

答案:它没有!

在任何Alpine Dockerfile中你都可以做到

FROM python:3.7-alpine
RUN echo "@testing http://dl-cdn.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories
RUN apk add --update --no-cache py3-numpy py3-pandas@testing
Run Code Online (Sandbox Code Playgroud)

这是因为so:libpython3.7m.so.1.0 (missing),numpy现在scipy都预先建立在pandas:

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

每次避免重建或使用Docker层的一种方法是使用预构建的原生Alpine Linux/alpine软件包,例如

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

https://github.com/nbgallery/apks

你可以构建这些.apk一次并在你喜欢的Dockerfile中的任何地方使用它们:)

这也节省了你必须在事实之前将其他所有内容都烘焙到Docker镜像中 - 即可以灵活地预构建你喜欢的任何Docker镜像.

  • 好像最近被删了?https://pkgs.alpinelinux.org/package/edge/testing/x86/py-pandas (2认同)
  • @jtlz2我切换到3.7-slim-buster,一切都很顺利https://pythonspeed.com/articles/base-image-python-docker-images/ (2认同)

小智 12

真正诚实的建议,切换到基于 Debian 的镜像,然后你所有的问题都会消失。

Alpine for python 应用程序运行不佳。

这是我的一个例子dockerfile

FROM python:3.7.6-buster

RUN pip install pandas==1.0.0
RUN pip install sklearn
RUN pip install Django==3.0.2
RUN pip install cx_Oracle==7.3.0
RUN pip install excel
RUN pip install djangorestframework==3.11.0
Run Code Online (Sandbox Code Playgroud)

python:3.7.6-buster是在这种情况下更合适,此外,您不需要在OS任何额外的依赖。

关注一篇有用的最新文章:https : //pythonspeed.com/articles/alpine-docker-python/ :

不要将 Alpine Linux 用于 Python 镜像除非您想要大幅减慢构建时间、更大的镜像、更多的工作以及潜在的隐蔽错误,否则您将希望避免将 Alpine Linux 作为基础镜像。有关您应该使用什么的一些建议,请参阅我关于选择良好基础映像的文章。

  • 您可以减少映像中的层数,即 RUN pip install <packegeA> && pip install <packageB> 等,而不是使用 RUN 命令块。它会影响您的构建性能:) (4认同)
  • 您还可以使用“pip --no-cache”来减少更多的占用空间。你真正应该做的就是将它们逐行放入“requirements.txt”文件中,然后“pip install --no-cache -rrequirements.txt” (3认同)

Thi*_*ven 7

只是将这些答案中的一些汇总到一个答案中,并添加我认为遗漏的细节。某些 python 库,特别是优化的数学和数据库,在 alpine 上构建需要这么长时间的原因是因为这些库的 pip 轮包括从 c/c++ 预编译并链接到gnu-libc (glibc)一组通用 c 标准库的二进制文件 。Debian、Fedora、CentOS 都(通常)使用glibc,但 alpine 为了保持轻量级,musl-libc改为使用。C / C ++二进制文件上构建glibc系统没有一个系统上运行glibc和同样的musl

Pip 首先查找具有正确二进制文件的轮子,如果找不到,它会尝试从 c/c++ 源代码编译二进制文件并将它们链接到 musl。在许多情况下,这甚至不会工作,除非你有从蟒蛇头python3-dev或这样的构建工具make

现在的一线希望,正如其他人所提到的,apk社区提供了带有适当二进制文件的软件包,使用这些可以为您节省构建二进制文件的(有时是冗长的)过程。

实际上,您可以.whl在 alpine 上从纯 python 安装,但是,在撰写本文时,由于该问题,manylinux不支持 alpine 的二进制musl/gnu发行版。


小智 6

在这种情况下,alpine 不是最好的解决方案,将 alpine 更改为 slim:

来自 python:3.8.3-alpine

改为:

FROM python:3.8.3-slim

就我而言,这个小改动就解决了这个问题。


ste*_*sky 5

注意
查看@ jtlz2的最新更新

2019年9月17日最新更新

因此,py3-pandas和py3-numpy软件包已移至测试高山存储库,因此,您可以通过将以下几行添加到Dockerfile中来下载它:

RUN echo "http://dl-8.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
  && apk update \
  && apk add py3-numpy py3-pandas
Run Code Online (Sandbox Code Playgroud)

希望它能对某人有所帮助!

高山套餐链接:
- PY3 -大熊猫
- PY3-numpy的

高山仓库停靠info

  • 已在我的回答中修复 (2认同)