Alpine збірае Docker білды пад Python у 50 разоў павольней, а выявы ў 2 разу цяжэй

Alpine збірае Docker білды пад Python у 50 разоў павольней, а выявы ў 2 разу цяжэй

Alpine Linux - часта рэкамендаваны як базавая выява для Docker`а. Вам кажуць, што выкарыстанне Alpine зробіць вашыя білды менш, а працэс зборкі хутчэй.

Але калі вы выкарыстоўваеце Alpine Linux для Python прыкладанняў, то ён:

  • Робіць вашыя білды нашмат павольней
  • Робіць вашыя вобразы больш
  • Марнуе ваш час
  • І ў выніку можа стаць прычынай памылак у рантайме.


Давайце разгледзім чаму ж Alpine рэкамендуюць, але чаму вам усё ж не варта выкарыстоўваць яго ў месцы з Python.

Чаму людзі рэкамендуюць Alpine?

Давайце выкажам здагадку, што нам неабходзен gcc як частка нашай выявы і мы жадаем параўнаць Alpine Linux vs 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. Таму, адзін з варыянтаў узяць афіцыйную выяву на базе Debian, выкарыстаючы такі Dockerfile:

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.
Атрымаецца ў нас лепш з Alpine? Давайце паспрабуем:

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('"'"'rn'"'"', '"'"'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

Што адбываецца?

Alpine не падтрымлівае wheels

Калі вы паглядзіце на білд, які грунтуецца на Debian, тыя вы ўбачыце, што ён спампоўвае matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.віл.

Гэта бінарнік для wheel. Alpine жа спампоўвае зыходнікі `matplotlib-3.1.2.tar.gz`, бо ён не падтрымлівае стандартны колы.

Чаму? Большасць Linux дыстрыбутываў выкарыстоўваюць GNU версію (glibc) стандартнай бібліятэкі C, які па факце неабходзен кожнай праграме напісанай на C, уключаючы Python. Але Alpine выкарыстоўвае `musl`, а бо тыя бінарнікі прызначаны для `glibc`, яны папросту не варыянт.

Таму, калі вы выкарыстоўваеце Alpine, вам неабходна кампіляваць увесь код, напісаны на C, у кожным пакеце Python.

Ах, так, спіс усіх такіх залежнасцяў якія, трэба кампіляваць давядзецца шукаць самім.
У дадзеным выпадку атрымліваем такое:

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 збіраюцца нашмат даўжэй, самі па сабе яны большага памеру і вам яшчэ трэба шукаць усе залежнасці. Можна вядома паменшыць памер зборкі выкарыстоўваючы multi-stage builds але гэта азначае, што трэба прарабіць яшчэ больш працы.

Гэта яшчэ не ўсё!

Alpine можа быць прычынай нечаканых багаў у рантайме.

  • У тэорыі musl сумяшчальны з glibc, але на практыцы адрозненні могуць стаць чыннікам шматлікіх праблем. І калі яны будуць, то, напэўна, непрыемныя. Вось некаторыя праблемы, якія могуць узнікнуць:
  • Alpine па змаўчанні мае меншы памер стэка патоку, што можа прывесці да памылкам у Python
  • Некаторыя карыстальнікі выявілі, што Python прыкладанні працуюць павольней з-за таго як, musl вылучае памяць (адрозніваецца ад glibc).
  • Адзін з карыстальнікаў выявіў памылку пры фарматаванні даты

Напэўна, гэтыя памылкі ўжо выправілі, але хто ведае колькі іх яшчэ.

Не выкарыстоўвайце вобразы Alpine для Python

Калі не жадаеце важдацца з вялікімі і доўгімі білдамі, пошукам залежнасцяў і патэнцыйнымі памылкамі - не выкарыстоўвайце Alpine Linux у якасці базавай выявы. Сhoosing a good base image.

Крыніца: habr.com

Дадаць каментар