
Alpine Linux — często zalecany jako podstawowy obraz dla Dockera. Mówi się, że użycie Alpine sprawi, że twoje obrazy będą mniejsze, a proces budowy szybszy.
Jednak jeśli używasz Alpine Linux do aplikacji Python, to on:
- Znacznie spowalnia budowę twoich obrazów
- Powoduje, że twoje obrazy stają się większe
- Marnuje twój czas
- I w efekcie może prowadzić do błędów w czasie działania
Zobaczmy, dlaczego zaleca się Alpine, ale dlaczego nie warto go używać w połączeniu z Pythonem.
Dlaczego ludzie polecają Alpine?
Załóżmy, że potrzebujemy gcc jako część naszego obrazu i chcemy porównać Alpine Linux z Ubuntu 18.04, pod względem prędkości budowy i ostatecznego rozmiaru obrazu.
Na początek, pobierzmy dwa obrazy i porównajmy ich rozmiar:
$ 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
Jak widać, podstawowy obraz dla Alpine jest znacznie mniejszy. Teraz spróbujmy zainstalować gcc, zaczynając od 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/*
Pisanie idealnych Dockerfile wykracza poza zakres tego artykułu
Mierzmy prędkość budowy:
$ 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
Powtarzamy to samo dla Alpine (Dockerfile):
FROM alpine
RUN apk add --update gcc
Budujemy, sprawdzamy czas i rozmiar budowy:
$ 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
Jak obiecano, obrazy oparte na Alpine budują się szybciej i same w sobie są mniejsze: 15 sekund zamiast 30 i rozmiar obrazu 105MB w porównaniu do 150MB. To całkiem dobrze!
Jednak jeśli przełączymy się na budowę aplikacji Python, sytuacja nie wygląda tak różowo.
Obraz Python
Aplikacje Python często wykorzystują pandas i matplotlib. Dlatego jednym z wariantów jest użycie oficjalnego obrazu opartego na Debianie, używając takiego Dockerfile:
FROM python:3.8-slim
RUN pip install --no-cache-dir matplotlib pandas
Budujemy go:
$ docker build -f Dockerfile.slim -t python-matpan.
Wysyłanie kontekstu budowy do demona Docker 3.072kB
Krok 1/2 : FROM python:3.8-slim
---> 036ea1506a85
Krok 2/2 : RUN pip install --no-cache-dir matplotlib pandas
---> Uruchamianie w 13739b2a0917
Zbieranie matplotlib
Pobieranie matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl (13.1 MB)
Zbieranie pandas
Pobieranie pandas-0.25.3-cp38-cp38-manylinux1_x86_64.whl (10.4 MB)
...
Pomyślnie zbudowano b98b5dc06690
Pomyślnie otagowano python-matpan:latest
czas rzeczywisty 0m30.297s
czas użytkownika 0m0.043s
czas systemowy 0m0.020s
Otrzymujemy obraz o rozmiarze 363MB.
Czy uzyskamy lepsze rezultaty z Alpine? Spróbujmy:
FROM python:3.8-alpine
RUN pip install --no-cache-dir matplotlib pandas
$ docker build -t python-matpan-alpine -f Dockerfile.alpine .
Wysyłanie kontekstu budowy do demona Docker 3.072kB
Krok 1/2 : FROM python:3.8-alpine
---> a0ee0c90a0db
Krok 2/2 : RUN pip install --no-cache-dir matplotlib pandas
---> Uruchamianie w 6740adad3729
Zbieranie matplotlib
Pobieranie matplotlib-3.1.2.tar.gz (40.9 MB)
BŁĄD: Komenda zakończyła się błędem z kodem wyjścia 1:
komenda: /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
...
BŁĄD: Komenda zakończyła się błędem z kodem wyjścia 1: python setup.py egg_info Sprawdź logi, aby zobaczyć pełne wyjście komendy.
Komenda '/bin/sh -c pip install matplotlib pandas' zwróciła kod inny niż zero: 1
Co się dzieje?
Alpine nie wspiera wheels
Jeśli spojrzysz na budowę, która opiera się na Debianie, zobaczysz, że pobiera matplotlib-3.1.2-cp38-cp38-manylinux1_x86_64.whl.
To jest binarka dla wheel. Alpine pobiera źródła `matplotlib-3.1.2.tar.gz`, ponieważ nie wspiera standardowego .
Dlaczego? Większość dystrybucji Linuksa używa wersji GNU (glibc) standardowej biblioteki C, która jest w rzeczywistości niezbędna każdemu programowi napisanym w C, w tym Pythonowi. Ale Alpine używa `musl`, a ponieważ te binarki są przeznaczone dla `glibc`, po prostu nie są opcją.
Dlatego, jeśli używasz Alpine, musisz kompilować cały kod napisany w C w każdym pakiecie Pythona.
Ach, tak, lista wszystkich takich zależności, które trzeba skompilować, będzie musiała być wyszukana przez siebie.
W tym przypadku otrzymujemy coś takiego:
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
A czas budowy trwa...
… 25 minut 57 sekund! A rozmiar obrazu wynosi 851MB.
Obrazy oparte na Alpine są znacznie dłużej budowane, same w sobie są większe, a dodatkowo musisz szukać wszystkich zależności. Oczywiście można zmniejszyć rozmiar budowy, korzystając z , ale oznacza to, że trzeba wykonać jeszcze więcej pracy.
To jeszcze nie wszystko!
Alpine może być przyczyną niespodziewanych błędów w czasie działania
- Teoretycznie musl jest zgodny z glibc, ale w praktyce różnice mogą prowadzić do wielu problemów. A jeśli się pojawią, to na pewno będą nieprzyjemne. Oto niektóre problemy, które mogą wystąpić:
- Alpine domyślnie ma mniejszy rozmiar stosu wątku, co może prowadzić do
- Niektórzy użytkownicy odkryli, że z powodu tego, jak musl przydziela pamięć (różni się od glibc).
- Jeden z użytkowników
Na pewno te błędy już zostały naprawione, ale kto wie, ile ich jeszcze jest.
Nie używaj obrazów Alpine do Pythona
Jeśli nie chcesz bawić się w długie i skomplikowane budowy, poszukiwanie zależności oraz potencjalne błędy — nie używaj Alpine Linux jako bazowego obrazu. .
Źródło: habr.com
