为什么在 Alpine Linux 上安装 Pandas 需要很长时间
Why does it take ages to install Pandas on Alpine Linux
我注意到使用基础 OS 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
使用 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
Dockerfile.alpine
FROM python:3.6.4-alpine3.7
RUN apk --update add --no-cache g++
RUN pip install pandas
使用 Pandas & Numpy 构建 Alpine 镜像:
[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
基于 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)
WHL 格式被开发为比每次从源代码 re-building 安装 Python 软件更快、更可靠的方法。 WHL 文件只需移动到要安装的目标系统上的正确位置,而源代码分发需要在安装前执行构建步骤。
轮子包 pandas
和 numpy
在基于 Alpine 平台的图像中不受支持。这就是为什么我们在构建过程中使用 python pip
安装它们时,我们总是从 alpine 中的源文件编译它们:
Downloading pandas-0.22.0.tar.gz (11.3MB)
Downloading numpy-1.14.1.zip (4.9MB)
在镜像构建过程中我们可以看到容器内部如下:
/ # 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
如果我们稍微修改一下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
我们得到以下错误:
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
不幸的是,在 Alpine 映像上安装 pandas
的唯一方法是等待构建完成。
当然如果你想在CI中使用pandas
的Alpine镜像,最好的方法是编译一次,推送到任何注册表并使用它作为满足您需求的基础图像。
编辑:
如果您想将 Alpine 图像与 pandas
一起使用,您可以拉取我的 nickgryg/alpine-pandas docker 图像。它是在 Alpine 平台上带有 pre-compiled pandas
的 python 图像。它应该可以节省您的时间。
答案:截至 2020 年 3 月 9 日,对于 PYTHON 3,它仍然没有!
这是一个完整的工作Docker文件:
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
构建对确切的 python 和 alpine 版本号非常敏感 - 弄错这些似乎会引发 Max Levy 的错误 so:libpython3.7m.so.1.0 (missing)
- 但上面的内容现在对我有用。
我更新的 Docker 文件可在 https://gist.github.com/jtlz2/b0f4bc07ce2ff04bc193337f2327c13b
[较早更新:]
答案:不是!
在任何 Alpine Docker文件中你可以简单地做*
RUN apk add py2-numpy@community py2-scipy@community py-pandas@edge
这是因为 numpy
、scipy
和现在的 pandas
都可以在 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
避免每次重建或使用 Docker 层的一种方法是使用预构建的原生 Alpine Linux/.apk
包,例如
https://github.com/sgerrand/alpine-pkg-py-pandas
https://github.com/nbgallery/apks
您可以构建这些 .apk
一次,然后在您喜欢的 Docker 文件中的任何地方使用它们:)
这也使您不必在事前将其他所有内容都烘焙到 Docker 图像中 - 即可以灵活地预先构建您喜欢的任何 Docker 图像。
PS 我已经在 https://gist.github.com/jtlz2/b0f4bc07ce2ff04bc193337f2327c13b 处放置了一个 Docker 文件存根,它大致显示了如何构建图像。其中包括重要步骤 (*):
RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
RUN apk update
RUN apk add --update --no-cache libgfortran
注意
查看@jtlz2 的回答最新更新
已过时
因此,py3-pandas 和 py3-numpy 包已移至测试 alpine 存储库,因此,您可以通过将这些行添加到您的 Dockerfile 来下载它:
RUN echo "http://dl-8.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
&& apk update \
&& apk add py3-numpy py3-pandas
Hope it helps someone!
Alpine packages links:
- py3-pandas
- py3-numpy
Alpine repositories docks info.
只是将这些答案中的一些放在一个答案中,并添加一个我认为遗漏的细节。某些 python 库,特别是优化的数学和数据库,在 alpine 上构建需要这么长时间的原因是因为这些库的 pip wheels 包括从 c/c++ 预编译并链接到 gnu-libc (glibc)
,一组通用的c标准库。 Debian、Fedora、CentOS 都(通常)使用 glibc
,但 alpine 为了保持轻量级,改为使用 musl-libc
。 c/c++ 在 glibc
系统上构建的二进制文件将无法在没有 glibc
的系统上运行,musl
.
也是如此
Pip 首先查找带有正确二进制文件的轮子,如果找不到,它会尝试从 c/c++ 源代码编译二进制文件并将它们链接到 musl。在许多情况下,除非您拥有来自 python3-dev
的 python headers 或 make
.
之类的构建工具,否则这甚至都行不通
现在的一线希望,正如其他人所提到的,社区提供了 apk
包含适当二进制文件的软件包,使用这些软件包将为您节省构建二进制文件的过程(有时很漫长)。
事实上,您可以在 alpine 上从纯 python .whl
安装,但是,在撰写本文时,manylinux 不支持 alpine 的二进制发行版,因为musl/gnu
问题。
真正诚实的建议,切换到基于 Debian 的映像,然后您所有的问题都会消失。
python 应用程序的 Alpine 运行不佳。
这是我的 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
python:3.7.6-buster
在这种情况下更合适,此外,您不需要任何额外的依赖OS。
关注一篇有用的最新文章:https://pythonspeed.com/articles/alpine-docker-python/:
Don’t use Alpine Linux for Python images
Unless you want massively slower build times, larger images, more work, and the potential for obscure bugs, you’ll want to avoid Alpine Linux as a base image. For some recommendations on what you should use, see my article on choosing a good base image.
这对我有用:
FROM python:3.8-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
ENV PYTHONPATH=/usr/lib/python3.8/site-packages
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5003
ENTRYPOINT [ "python" ]
CMD [ "app.py" ]
这里的大部分代码来自另一个线程 from this same thread and 的回答。
原来 pandas 的较轻版本可以在 Alpine 存储库 py3-numpy
中找到,但它没有安装在 Python 读取导入的同一文件路径中默认。因此您需要添加 ENV
。还要注意高山版本。
alpine 需要很多时间来安装 pandas 而且图像也很大。我尝试了 python:3.8-slim-buster 版本的 python 基本图像。与 alpine python docker image
相比,图像构建速度非常快,图像大小不到一半
https://github.com/dguyhasnoname/k8s-cluster-checker/blob/master/Dockerfile
pandas
被认为是社区支持的包,因此指向 edge/testing
的答案不会起作用,因为 Alpine 没有正式支持 pandas 作为核心包(它仍然有效,只是核心 Alpine 开发人员不支持它。
试试这个 Dockerfile:
FROM python:3.8-alpine
RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
&& apk add py3-pandas@community
ENV PYTHONPATH="/usr/lib/python3.8/site-packages"
这也适用于原版 Alpine 图片,使用 FROM alpine:3.12
。
更新:感谢@cegprakash 提出了当您还有一个必须在容器内满足的 requirements.txt
文件时如何使用此设置的问题。
我在 Dockerfile 片段中添加了一行以将 PYTHONPATH
变量导出到容器运行时。如果这样做,pandas
或 numpy
是否包含在需求文件中并不重要(前提是它们与通过 apk
安装的版本相同)。
需要这样做的原因是 apk
在 /usr/lib
下安装了 py3-pands@community
包,但该位置不在 [=23= 的默认 PYTHONPATH
上] 在安装新包之前进行检查。如果我们不包含此步骤来添加它,pip
和 python
将找不到该软件包,并且 pip
将尝试在 /usr/local
下下载并安装它,这就是我们正在努力避免。
鉴于我们确实想要确保pip
不会尝试安装pandas
,我建议not 在 requirements.txt
文件中包含 pandas
或 numpy
如果您已经使用上述方法通过 apk
安装了它们。这只是一些额外的保险,确保事情会按预期进行。
在这种情况下,alpine 不是最好的解决方案,将 alpine 更改为苗条:
来自 python:3.8.3-高山
更改为:
FROM python:3.8.3-slim
在我的情况下,这个小改动就解决了。
我注意到使用基础 OS 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
使用 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
Dockerfile.alpine
FROM python:3.6.4-alpine3.7
RUN apk --update add --no-cache g++
RUN pip install pandas
使用 Pandas & Numpy 构建 Alpine 镜像:
[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
基于 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)
WHL 格式被开发为比每次从源代码 re-building 安装 Python 软件更快、更可靠的方法。 WHL 文件只需移动到要安装的目标系统上的正确位置,而源代码分发需要在安装前执行构建步骤。
轮子包 pandas
和 numpy
在基于 Alpine 平台的图像中不受支持。这就是为什么我们在构建过程中使用 python pip
安装它们时,我们总是从 alpine 中的源文件编译它们:
Downloading pandas-0.22.0.tar.gz (11.3MB)
Downloading numpy-1.14.1.zip (4.9MB)
在镜像构建过程中我们可以看到容器内部如下:
/ # 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
如果我们稍微修改一下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
我们得到以下错误:
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
不幸的是,在 Alpine 映像上安装 pandas
的唯一方法是等待构建完成。
当然如果你想在CI中使用pandas
的Alpine镜像,最好的方法是编译一次,推送到任何注册表并使用它作为满足您需求的基础图像。
编辑:
如果您想将 Alpine 图像与 pandas
一起使用,您可以拉取我的 nickgryg/alpine-pandas docker 图像。它是在 Alpine 平台上带有 pre-compiled pandas
的 python 图像。它应该可以节省您的时间。
答案:截至 2020 年 3 月 9 日,对于 PYTHON 3,它仍然没有!
这是一个完整的工作Docker文件:
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
构建对确切的 python 和 alpine 版本号非常敏感 - 弄错这些似乎会引发 Max Levy 的错误 so:libpython3.7m.so.1.0 (missing)
- 但上面的内容现在对我有用。
我更新的 Docker 文件可在 https://gist.github.com/jtlz2/b0f4bc07ce2ff04bc193337f2327c13b
[较早更新:]
答案:不是!
在任何 Alpine Docker文件中你可以简单地做*
RUN apk add py2-numpy@community py2-scipy@community py-pandas@edge
这是因为 numpy
、scipy
和现在的 pandas
都可以在 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
避免每次重建或使用 Docker 层的一种方法是使用预构建的原生 Alpine Linux/.apk
包,例如
https://github.com/sgerrand/alpine-pkg-py-pandas
https://github.com/nbgallery/apks
您可以构建这些 .apk
一次,然后在您喜欢的 Docker 文件中的任何地方使用它们:)
这也使您不必在事前将其他所有内容都烘焙到 Docker 图像中 - 即可以灵活地预先构建您喜欢的任何 Docker 图像。
PS 我已经在 https://gist.github.com/jtlz2/b0f4bc07ce2ff04bc193337f2327c13b 处放置了一个 Docker 文件存根,它大致显示了如何构建图像。其中包括重要步骤 (*):
RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories
RUN apk update
RUN apk add --update --no-cache libgfortran
注意
查看@jtlz2 的回答最新更新
已过时
因此,py3-pandas 和 py3-numpy 包已移至测试 alpine 存储库,因此,您可以通过将这些行添加到您的 Dockerfile 来下载它:
RUN echo "http://dl-8.alpinelinux.org/alpine/edge/testing" >> /etc/apk/repositories \
&& apk update \
&& apk add py3-numpy py3-pandas
Hope it helps someone!
Alpine packages links:
- py3-pandas
- py3-numpyAlpine repositories docks info.
只是将这些答案中的一些放在一个答案中,并添加一个我认为遗漏的细节。某些 python 库,特别是优化的数学和数据库,在 alpine 上构建需要这么长时间的原因是因为这些库的 pip wheels 包括从 c/c++ 预编译并链接到 gnu-libc (glibc)
,一组通用的c标准库。 Debian、Fedora、CentOS 都(通常)使用 glibc
,但 alpine 为了保持轻量级,改为使用 musl-libc
。 c/c++ 在 glibc
系统上构建的二进制文件将无法在没有 glibc
的系统上运行,musl
.
Pip 首先查找带有正确二进制文件的轮子,如果找不到,它会尝试从 c/c++ 源代码编译二进制文件并将它们链接到 musl。在许多情况下,除非您拥有来自 python3-dev
的 python headers 或 make
.
现在的一线希望,正如其他人所提到的,社区提供了 apk
包含适当二进制文件的软件包,使用这些软件包将为您节省构建二进制文件的过程(有时很漫长)。
事实上,您可以在 alpine 上从纯 python .whl
安装,但是,在撰写本文时,manylinux 不支持 alpine 的二进制发行版,因为musl/gnu
问题。
真正诚实的建议,切换到基于 Debian 的映像,然后您所有的问题都会消失。
python 应用程序的 Alpine 运行不佳。
这是我的 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
python:3.7.6-buster
在这种情况下更合适,此外,您不需要任何额外的依赖OS。
关注一篇有用的最新文章:https://pythonspeed.com/articles/alpine-docker-python/:
Don’t use Alpine Linux for Python images Unless you want massively slower build times, larger images, more work, and the potential for obscure bugs, you’ll want to avoid Alpine Linux as a base image. For some recommendations on what you should use, see my article on choosing a good base image.
这对我有用:
FROM python:3.8-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
ENV PYTHONPATH=/usr/lib/python3.8/site-packages
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
EXPOSE 5003
ENTRYPOINT [ "python" ]
CMD [ "app.py" ]
这里的大部分代码来自另一个线程
原来 pandas 的较轻版本可以在 Alpine 存储库 py3-numpy
中找到,但它没有安装在 Python 读取导入的同一文件路径中默认。因此您需要添加 ENV
。还要注意高山版本。
alpine 需要很多时间来安装 pandas 而且图像也很大。我尝试了 python:3.8-slim-buster 版本的 python 基本图像。与 alpine python docker image
相比,图像构建速度非常快,图像大小不到一半https://github.com/dguyhasnoname/k8s-cluster-checker/blob/master/Dockerfile
pandas
被认为是社区支持的包,因此指向 edge/testing
的答案不会起作用,因为 Alpine 没有正式支持 pandas 作为核心包(它仍然有效,只是核心 Alpine 开发人员不支持它。
试试这个 Dockerfile:
FROM python:3.8-alpine
RUN echo "@community http://dl-cdn.alpinelinux.org/alpine/edge/community" >> /etc/apk/repositories \
&& apk add py3-pandas@community
ENV PYTHONPATH="/usr/lib/python3.8/site-packages"
这也适用于原版 Alpine 图片,使用 FROM alpine:3.12
。
更新:感谢@cegprakash 提出了当您还有一个必须在容器内满足的 requirements.txt
文件时如何使用此设置的问题。
我在 Dockerfile 片段中添加了一行以将 PYTHONPATH
变量导出到容器运行时。如果这样做,pandas
或 numpy
是否包含在需求文件中并不重要(前提是它们与通过 apk
安装的版本相同)。
需要这样做的原因是 apk
在 /usr/lib
下安装了 py3-pands@community
包,但该位置不在 [=23= 的默认 PYTHONPATH
上] 在安装新包之前进行检查。如果我们不包含此步骤来添加它,pip
和 python
将找不到该软件包,并且 pip
将尝试在 /usr/local
下下载并安装它,这就是我们正在努力避免。
鉴于我们确实想要确保pip
不会尝试安装pandas
,我建议not 在 requirements.txt
文件中包含 pandas
或 numpy
如果您已经使用上述方法通过 apk
安装了它们。这只是一些额外的保险,确保事情会按预期进行。
在这种情况下,alpine 不是最好的解决方案,将 alpine 更改为苗条:
来自 python:3.8.3-高山
更改为:
FROM python:3.8.3-slim
在我的情况下,这个小改动就解决了。