Alpine在Python下收集Docker构建的速度慢了50倍,而镜像则重了2倍



通常建议将Alpine Linux作为Docker的基础映像。有人告诉您使用Alpine将使您的构建更小,构建过程更快。

但是,如果您将Alpine Linux用于Python应用程序,那么它将:

  • 使您的构建速度变慢
  • 使您看起来更大
  • 浪费你的时间
  • 最后,它可能导致运行时错误

让我们看一下Alpine为什么推荐它,但是为什么不应该在Python地方使用它。

人们为什么推荐阿尔卑斯山?


假设我们需要gcc作为映像的一部分,并且要在构建速度和最终映像大小方面比较Alpine Linux与Ubuntu 18.04。

首先,下载两个图像并比较它们的大小:

$ docker pull --quiet ubuntu:18.04
docker.io/library/ubuntu:18.04
$ docker pull --quiet alpine
docker.io/library/alpine:latest
$ docker image ls ubuntu:18.04
REPOSITORY          TAG        IMAGE ID         SIZE
ubuntu              18.04      ccc6e87d482b     64.2MB
$ docker image ls alpine
REPOSITORY          TAG        IMAGE ID         SIZE
alpine              latest     e7d92cdc71fe     5.59MB

如您所见,Alpine的基本图像要小得多。现在让我们尝试安装gcc并从Ubuntu开始:

FROM ubuntu:18.04
RUN apt-get update && \
    apt-get install --no-install-recommends -y gcc && \
    apt-get clean && rm -rf /var/lib/apt/lists/*

编写完美的Dockerfile超出了本文的范围。

让我们测量构建速度:

$ time docker build -t ubuntu-gcc -f Dockerfile.ubuntu --quiet .
sha256:b6a3ee33acb83148cd273b0098f4c7eed01a82f47eeb8f5bec775c26d4fe4aae

real    0m29.251s
user    0m0.032s
sys     0m0.026s
$ docker image ls ubuntu-gcc
REPOSITORY   TAG      IMAGE ID      CREATED         SIZE
ubuntu-gcc   latest   b6a3ee33acb8  9 seconds ago   150MB

对Alpine(Dockerfile)重复相同的操作:

FROM alpine
RUN apk add --update gcc

我们组装,看看组装的时间和大小:

$ time docker build -t alpine-gcc -f Dockerfile.alpine --quiet .
sha256:efd626923c1478ccde67db28911ef90799710e5b8125cf4ebb2b2ca200ae1ac3

real    0m15.461s
user    0m0.026s
sys     0m0.024s
$ docker image ls alpine-gcc
REPOSITORY   TAG      IMAGE ID       CREATED         SIZE
alpine-gcc   latest   efd626923c14   7 seconds ago   105MB

如所承诺的那样,基于Alpine的图像组装起来更快,更少:15秒(而不是30秒),图像大小为105MB与150MB。这很好!

但是,如果我们切换到构建Python应用程序,那么一切都不会那么乐观。

Python图像


Python应用程序经常使用pandas和matplotlib。因此,一种选择是使用此Dockerfile拍摄基于Debian的官方映像:

FROM python:3.8-slim
RUN pip install --no-cache-dir matplotlib pandas

我们收集它:

$ docker build -f Dockerfile.slim -t python-matpan.
Sending build context to Docker daemon  3.072kB
Step 1/2 : FROM python:3.8-slim
 ---> 036ea1506a85
Step 2/2 : RUN pip install --no-cache-dir matplotlib pandas
 ---> Running in 13739b2a0917
Collecting matplotlib
  Downloading matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl (13.1 MB)
Collecting pandas
  Downloading pandas-0.25.3-cp38-cp38-manylinux1_x86_64.whl (10.4 MB)
...
Successfully built b98b5dc06690
Successfully tagged python-matpan:latest

real    0m30.297s
user    0m0.043s
sys     0m0.020s

我们得到的图像大小为363MB。
阿尔卑斯山会让我们变得更好吗?我们试试吧:

FROM python:3.8-alpine
RUN pip install --no-cache-dir matplotlib pandas

$ docker build -t python-matpan-alpine -f Dockerfile.alpine .                                 
Sending build context to Docker daemon  3.072kB                                               
Step 1/2 : FROM python:3.8-alpine                                                             
 ---> a0ee0c90a0db                                                                            
Step 2/2 : RUN pip install --no-cache-dir matplotlib pandas                                                  
 ---> Running in 6740adad3729                                                                 
Collecting matplotlib                                                                         
  Downloading matplotlib-3.1.2.tar.gz (40.9 MB)                                               
    ERROR: Command errored out with exit status 1:                                            
     command: /usr/local/bin/python -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/
tmp/pip-install-a3olrixa/matplotlib/setup.py'"'"'; __file__='"'"'/tmp/pip-install-a3olrixa/matplotlib/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' egg_info --egg-base /tmp/pip-install-a3olrixa/matplotlib/pip-egg-info                              

...
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.
The command '/bin/sh -c pip install matplotlib pandas' returned a non-zero code: 1

发生了什么?

高山不支持车轮


如果您查看基于Debian的构建,您会看到它下载了matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64。WHL

这是车轮的二进制文件。 Alpine下载了`matplotlib-3.1.2.tar的资源。gz`,因为它不支持标准车轮

为什么?大多数Linux发行版都使用C标准库的GNU版本(glibc),实际上每个C程序(包括Python)都需要它。但是Alpine使用“ musl”,并且由于这些二进制文件是针对“ glibc”的,因此它们根本不是一种选择。

因此,如果使用Alpine,则需要编译每个Python包中用C编写的所有代码。

嗯,是的,必须自己搜索所有需要编译的依赖项列表。
在这种情况下,我们得到以下信息:

FROM python:3.8-alpine
RUN apk --update add gcc build-base freetype-dev libpng-dev openblas-dev
RUN pip install --no-cache-dir matplotlib pandas

构建时间需要

……25分钟57秒!图像大小为851MB。

基于高山的图像花费的时间更长,它们本身更大,您仍然需要查找所有依赖项。您当然可以使用多阶段构建来减小构建大小但这意味着需要做更多的工作。

那不是全部!

高山可能会导致意外的运行时错误



这些错误肯定已经得到修复,但是谁知道又多少错误。

不要将Alpine图片用于Python


如果您不想打扰大型和冗长的构建,依赖项搜索和潜在的错误-请勿将Alpine Linux用作基础映像。选择一个好的基础形象

Source: https://habr.com/ru/post/undefined/


All Articles