Alpine compila as compilacións de Docker para Python 50 veces máis lenta e as imaxes son dúas veces máis pesadas

Alpine compila as compilacións de Docker para Python 50 veces máis lenta e as imaxes son dúas veces máis pesadas

Alpine Linux adoita recomendarse como imaxe base para Docker. Díxenche que usar Alpine fará que as túas construcións sexan máis pequenas e que o teu proceso de construción sexa máis rápido.

Pero se usa Alpine Linux para aplicacións Python, entón:

  • Fai que as túas construcións sexan moito máis lentas
  • Fai as túas imaxes máis grandes
  • Perder o tempo
  • E ao final pode causar erros no tempo de execución


Vexamos por que se recomenda Alpine, pero por que aínda non deberías usalo con Python.

Por que a xente recomenda Alpine?

Supoñamos que necesitamos gcc como parte da nosa imaxe e queremos comparar Alpine Linux con Ubuntu 18.04 en termos de velocidade de compilación e tamaño da imaxe final.

En primeiro lugar, descarguemos dúas imaxes e comparemos os seus tamaños:

$ 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

Como podes ver, a imaxe base de Alpine é moito máis pequena. Imos agora tentar instalar gcc e comezar con 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/*

Escribir o Dockerfile perfecto está fóra do alcance deste artigo.

Imos medir a velocidade de montaxe:

$ 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

Repetimos o mesmo para Alpine (Dockerfile):

FROM alpine
RUN apk add --update gcc

Montamos, miramos a hora e o tamaño da montaxe:

$ 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

Como prometeu, as imaxes baseadas en Alpine recóllense máis rápido e son máis pequenas: 15 segundos en lugar de 30 e o tamaño da imaxe é de 105 MB fronte a 150 MB. Está moi ben!

Pero se cambiamos a construír unha aplicación Python, entón todo non é tan bo.

Imaxe de Python

As aplicacións de Python adoitan usar pandas e matplotlib. Polo tanto, unha opción é tomar a imaxe oficial baseada en Debian usando este Dockerfile:

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

Imos recollelo:

$ 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

Temos unha imaxe de 363 MB de tamaño.
Farémolo mellor con Alpine? Imos probar:

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

Que pasa?

Alpine non admite rodas

Se miras a compilación, que está baseada en Debian, verás que descarga matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl.

Este é un binario para roda. Alpine descarga as fontes `matplotlib-3.1.2.tar.gz` xa que non admite estándar rodas.

Por que? A maioría das distribucións de Linux usan a versión GNU (glibc) da biblioteca estándar C, que de feito é requirida por todos os programas escritos en C, incluído Python. Pero Alpine usa `musl`, e dado que eses binarios están deseñados para `glibc`, simplemente non son unha opción.

Polo tanto, se usas Alpine, necesitas compilar todo o código escrito en C en cada paquete de Python.

Ah, si, terás que buscar a lista de todas esas dependencias que hai que compilar vostede mesmo.
Neste caso obtemos isto:

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

E o tempo de construción leva...

... 25 minutos 57 segundos! E o tamaño da imaxe é de 851 MB.

As imaxes baseadas no alpino tardan moito máis en construírse, son de maior tamaño e aínda debes buscar todas as dependencias. Por suposto, pode reducir o tamaño da montaxe usando construcións en varias etapas pero iso significa que aínda hai que traballar máis.

Isto non é todo!

Alpine pode causar erros inesperados no tempo de execución

  • En teoría, musl é compatible con glibc, pero na práctica as diferenzas poden causar moitos problemas. E se o son, probablemente serán desagradables. Aquí tes algúns problemas que poden ocorrer:
  • Alpine ten un tamaño de pila de fíos menor por defecto, o que pode provocar erros en Python
  • Algúns usuarios descubriron iso As aplicacións de Python son máis lentas pola forma en que musl asigna a memoria (diferente da glibc).
  • Un dos usuarios atopou un erro ao formatar a data

Seguro que estes erros xa foron corrixidos, pero quen sabe cantos máis haberá.

Non use imaxes alpinas para Python

Se non queres molestarte con compilacións grandes e longas, buscando dependencias e posibles erros, non uses Alpine Linux como imaxe base. Elixir unha boa imaxe base.

Fonte: www.habr.com

Engadir un comentario