
Alpine Linux es a menudo recomendado como imagen base para Docker. Se dice que usar Alpine hará que tus compilaciones sean más pequeñas y el proceso de compilación más rápido.
Pero si usas Alpine Linux para aplicaciones de Python, entonces:
- Hace que tus compilaciones sean mucho más lentas.
- Hace que tus imágenes sean más grandes.
- Te cuesta tiempo.
- Y, al final, puede ser la causa de errores en tiempo de ejecución.
Veamos por qué se recomienda Alpine, pero por qué aún así no deberías usarlo junto con Python.
¿Por qué la gente recomienda Alpine?
Supongamos que necesitamos gcc como parte de nuestra imagen y queremos comparar Alpine Linux con Ubuntu 18.04 en términos de velocidad de compilación y tamaño final de la imagen.
Primero, descarguemos ambas imágenes y comparemos su tamaño:
$ 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 puedes ver, la imagen base para Alpine es mucho más pequeña. Ahora intentemos instalar gcc y comenzaremos 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 un Dockerfile perfecto está más allá del alcance de este artículo.
Mediremos la velocidad de compilación:
$ 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 lo mismo para Alpine (Dockerfile):
FROM alpine
RUN apk add --update gcc
Compilamos, observamos el tiempo y el tamaño de la compilación:
$ 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 se prometió, las imágenes basadas en Alpine se compilan más rápido y son más pequeñas: 15 segundos en lugar de 30 y un tamaño de imagen de 105MB frente a 150MB. ¡Eso es bastante bueno!
Pero si cambiamos a la compilación de una aplicación de Python, las cosas no son tan brillantes.
Imagen de Python
Las aplicaciones de Python a menudo utilizan pandas y matplotlib. Por lo tanto, una de las opciones es tomar la imagen oficial basada en Debian, utilizando un Dockerfile como este:
FROM python:3.8-slim
RUN pip install --no-cache-dir matplotlib pandas
La compilamos:
$ docker build -f Dockerfile.slim -t python-matpan.
Enviando contexto de construcción al demonio de Docker 3.072kB
Paso 1/2 : FROM python:3.8-slim
---> 036ea1506a85
Paso 2/2 : RUN pip install --no-cache-dir matplotlib pandas
---> Ejecutando en 13739b2a0917
Recolección de matplotlib
Descargando matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl (13.1 MB)
Recolección de pandas
Descargando pandas-0.25.3-cp38-cp38-manylinux1_x86_64.whl (10.4 MB)
...
Construcción exitosa b98b5dc06690
Etiquetado exitosamente python-matpan:latest
real 0m30.297s
user 0m0.043s
sys 0m0.020s
Estamos obteniendo una imagen de 363MB.
¿Lo haremos mejor con Alpine? Vamos a intentarlo:
FROM python:3.8-alpine
RUN pip install --no-cache-dir matplotlib pandas
$ docker build -t python-matpan-alpine -f Dockerfile.alpine .
Enviando contexto de construcción al demonio de Docker 3.072kB
Paso 1/2 : FROM python:3.8-alpine
---> a0ee0c90a0db
Paso 2/2 : RUN pip install --no-cache-dir matplotlib pandas
---> Ejecutando en 6740adad3729
Recolección de matplotlib
Descargando matplotlib-3.1.2.tar.gz (40.9 MB)
ERROR: El comando terminó con el estado 1:
comando: /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: El comando terminó con estado 1: python setup.py egg_info Verifique los registros para la salida completa del comando.
El comando '/bin/sh -c pip install matplotlib pandas' devolvió un código distinto de cero: 1
¿Qué está pasando?
Alpine no admite wheels
Si miras la construcción que se basa en Debian, verás que descarga matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl.
Es un binario para wheels. Alpine, en cambio, descarga los fuentes `matplotlib-3.1.2.tar.gz`, ya que no admite los estándar .
¿Por qué? La mayoría de las distribuciones de Linux utilizan la versión GNU (glibc) de la biblioteca estándar C, que en realidad es necesaria para cada programa escrito en C, incluyendo Python. Pero Alpine utiliza `musl`, y dado que esos binarios están destinados a `glibc`, simplemente no son una opción.
Por lo tanto, si estás usando Alpine, necesitarás compilar todo el código escrito en C en cada paquete de Python.
Ah, sí, tendrás que buscar tú mismo la lista de todas esas dependencias que necesitas compilar.
En este caso, obtenemos lo siguiente:
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
Y el tiempo de construcción toma…
… 25 minutos 57 segundos! Y el tamaño de la imagen es 851MB.
Las imágenes basadas en Alpine se construyen mucho más lentamente, son más grandes y además necesitas buscar todas las dependencias. Claro, se puede reducir el tamaño de la construcción utilizando , pero eso significa que hay que hacer mucho más trabajo.
¡Eso no es todo!
Alpine puede ser la causa de errores inesperados en tiempo de ejecución.
- En teoría, musl es compatible con glibc, pero en la práctica, las diferencias pueden causar muchos problemas. Y si los hay, seguramente serán desagradables. Aquí hay algunos problemas que pueden surgir:
- Alpine por defecto tiene un tamaño de pila de hilo más pequeño, lo que puede llevar a
- Algunos usuarios han descubierto que debido a la forma en que musl asigna memoria (diferente de glibc).
- Uno de los usuarios
Seguramente esos errores ya se han corregido, pero quién sabe cuántos más hay.
No utilices imágenes de Alpine para Python.
Si no quieres lidiar con construcciones grandes y largas, buscar dependencias y errores potenciales, no uses Alpine Linux como imagen base. .
Fuente: habr.com
