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.whl.

Π­Ρ‚ΠΎ Π±ΠΈΠ½Π°Ρ€Π½ΠΈΠΊ для wheel. Alpine ΠΆΠ΅ скачиваСт исходники `matplotlib-3.1.2.tar.gz`, Ρ‚Π°ΠΊ ΠΊΠ°ΠΊ ΠΎΠ½ Π½Π΅ ΠΏΠΎΠ΄Π΄Π΅Ρ€ΠΆΠΈΠ²Π°Π΅Ρ‚ стандартный wheels.

ΠŸΠΎΡ‡Π΅ΠΌΡƒ? Π‘ΠΎΠ»ΡŒΡˆΠΈΠ½ΡΡ‚Π²ΠΎ 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