Multi-stage Docker build
Tato sekce popisuje architekturu multi-stage Docker buildů pro aplikaci WebAMČR. Aplikace využívá dvě varianty Dockerfile:
Dockerfile - produkční obraz s maximální optimalizací velikosti a bezpečnosti
Dockerfile-DEV - vývojový obraz s ladícími nástroji
Oba obrazy používají multi-stage build techniku pro optimalizaci velikosti a bezpečnosti.
Architektura multi-stage buildů
Multi-stage build je technika, která umožňuje rozdělit proces vytváření Docker obrazu do více fází (stages). Každá fáze může používat jiný základní obraz a slouží k určitému účelu. Výsledný obraz obsahuje pouze finální fázi, což snižuje velikost obrazu a zvyšuje bezpečnost.
Produkční Dockerfile (3 fáze)
┌──────────────────────────────────┐
│ Stage 1: python-builder │
│ • Instalace build nástrojů │
│ • Kompilace Python wheels │
│ • BuildKit cache mount │
└────────────┬─────────────────────┘
│
├──────────────┐
│ │
v v
┌────────────────────┐ ┌──────────────────┐
│ Stage 2: │ │ Python wheels │
│ app-builder │ │ (artefakt) │
│ • Instalace balíků │ └──────────────────┘
│ • Kopie kódu │
│ • Kompilace │
│ bytecode (.pyc) │
└────────┬───────────┘
│
v
┌─────────────────────────────────┐
│ Stage 3: runtime │
│ • Čistý základní obraz │
│ • Pouze runtime závislosti │
│ • Instalace wheels │
│ • Kopie zkompilovaného kódu │
│ • BEZ build nástrojů │
│ • Minimální velikost │
└─────────────────────────────────┘
Vývojový Dockerfile-DEV (2 fáze)
┌──────────────────────────────────┐
│ Stage 1: python-builder │
│ • Instalace build nástrojů │
│ • Kompilace Python wheels │
│ • BuildKit cache mount │
└────────────┬─────────────────────┘
│
v
┌─────────────────────────────────┐
│ Stage 2: runtime │
│ • Čistý základní obraz │
│ • Runtime + dev nástroje (nano)│
│ • Instalace wheels │
│ • Kopie zdrojového kódu │
│ • Python aliasy │
│ • BEZ kompilace bytecode │
└─────────────────────────────────┘
Detailní popis Dockerfile (produkce)
Stage 1: python-builder
Účel: Příprava prostředí pro kompilaci Python závislostí
FROM ghcr.io/osgeo/gdal:ubuntu-small-3.12.1 AS python-builder
ENV DEBIAN_FRONTEND=noninteractive \
TZ="Europe/Prague"
Instalované balíčky
- Build závislosti (nutné pro kompilaci):
python3-pip- správce balíčků Pythonpython3-dev- hlavičkové soubory pro kompilacibuild-essential- základní kompilátor GCC a Makegcc- kompilátor Clibpq-dev- PostgreSQL hlavičkové soubory
- Runtime závislosti:
tzdata- časová pásmacron- plánovač úlohsudo- správa oprávněnílibgdal-dev- GDAL knihovna pro GISlocales- lokalizacegettext- překladypoppler-utils- PDF nástroje (vyžadováno propdf2image- konverze PDF na obrázky)unrar- rozbalování RAR archivů (vyžadováno prorarfile- zpracování RAR archivů)jq- JSON procesor (parsování JSON v bash skriptechentrypoint.sh,prod_deploy.sh,run-healthcheck.sh)postgresql-client- PostgreSQL klientcurl- HTTP klientlibmagic1- detekce typu souborůredis-tools- Redis nástroje
Kompilace Python wheels
COPY ./webclient/requirements.txt /tmp/requirements.txt
RUN --mount=type=cache,target=/root/.cache/pip \
pip3 wheel --wheel-dir /wheels -r /tmp/requirements.txt
BuildKit cache mount
--mount=type=cache,target=/root/.cache/pip
Cachuje stažené Python balíčky mezi buildy
Zrychluje opakované buildy
Pouze změněné balíčky se stahují znovu
Vyžaduje
DOCKER_BUILDKIT=1
Aktivace BuildKit
Poznámka
Od Docker 23.0 je BuildKit výchozí build engine a není potřeba jej explicitně aktivovat.
BuildKit lze aktivovat několika způsoby:
Globálně v Docker daemonu (doporučeno) - nastavení v
/etc/docker/daemon.jsonnebo~/.docker/daemon.json:{ "features": { "buildkit": true } }
Po restartu Docker daemonu se BuildKit použije automaticky pro všechny buildy včetně
docker-compose build.Pomocí proměnné prostředí:
export DOCKER_BUILDKIT=1 docker-compose build
Přímo v příkazu:
DOCKER_BUILDKIT=1 docker-compose build
Výhody wheels
Pre-kompilované binární balíčky
Rychlejší instalace než ze zdrojových kódů
Konzistentní napříč prostředími
Menší velikost než zdrojové balíčky
Stage 2: app-builder
Účel: Příprava aplikace a kompilace bytecode
FROM python-builder AS app-builder
COPY --from=python-builder /wheels /wheels
RUN pip3 install --no-cache-dir --no-index \
--find-links=/wheels /wheels/* \
--break-system-packages --ignore-installed && \
rm -rf /wheels ~/.cache/pip
Instalace Python balíčků v app-builder
Balíčky musí být nainstalovány, protože kompilace bytecode vyžaduje importování modulů:
# python3 -m compileall importuje moduly
import django # vyžaduje nainstalované Django
import psycopg2 # vyžaduje nainstalované psycopg2
# ... kompiluje každý modul na .pyc
Kompilace zdrojového kódu
COPY ./webclient /code
WORKDIR /code
RUN python3 -m compileall -b /code
Co dělá kompilace bytecode
Příkaz python3 -m compileall -b /code předkompiluje Python zdrojové soubory (.py) na bytecode (.pyc):
Před: Po:
myapp/ myapp/
├── views.py ├── views.py
├── models.py ├── views.pyc ← přidáno
└── utils.py ├── models.py
├── models.pyc ← přidáno
├── utils.py
└── utils.pyc ← přidáno
Výhody kompilace bytecode
Rychlejší start aplikace -
.pycsoubory se načítají přímo bez kompilaceKonzistentní výkon - kompilace probíhá v build time
Optimalizace - bytecode je optimalizovaný s menší paměťovou stopou
Stage 3: runtime
Účel: Minimální produkční obraz
FROM ghcr.io/osgeo/gdal:ubuntu-small-3.12.1 AS runtime
Proč čistý základní obraz
Žádné build artefakty
Žádné build nástroje (
gcc,python3-dev)Minimální bezpečnostní riziko
Menší velikost obrazu
Instalace pouze runtime balíčků
Instalují se POUZE runtime závislosti, BEZ build nástrojů.
Instalace wheels a aplikace
COPY --from=python-builder /wheels /wheels
RUN pip3 install --no-cache-dir --no-index \
--find-links=/wheels /wheels/* \
--break-system-packages --ignore-installed && \
rm -rf /wheels ~/.cache/pip
COPY --from=app-builder /code /code
Proč instalovat wheels znovu
app-buildermá balíčky v „build“ prostředí (s build nástroji)runtimemusí mít čistou instalaci bez build artefaktůGarantuje čisté produkční prostředí
Nastavení uživatele a oprávnění
RUN mkdir -p /vol/web/media /vol/web/static \
/vol/web/locale/cs/LC_MESSAGES \
/vol/web/locale/en/LC_MESSAGES && \
userdel ubuntu && \
adduser --disabled-password --gecos "" user && \
passwd -d user && \
usermod -aG sudo user
WORKDIR /code
COPY --chown=user:user ./scripts /scripts
COPY --chown=user:user ./proxy/custom_html /custom_html
COPY –chown optimalizace
Místo samostatného RUN chown, používáme COPY --chown:
Efektivnější (jedna operace místo dvou)
Menší počet vrstev
Soubory mají správného vlastníka od začátku
Health check
HEALTHCHECK --interval=30s --timeout=10s \
--start-period=40s --retries=3 \
CMD curl -f http://localhost:8000/ || exit 1
Automatická kontrola zdraví kontejneru
Orchestrační nástroje (Kubernetes, Docker Swarm) mohou restartovat nefunkční kontejnery
Rozdíly: Dockerfile vs Dockerfile-DEV
Vlastnost |
Dockerfile (PROD) |
Dockerfile-DEV |
|---|---|---|
Počet fází |
3 ( |
2 ( |
Kompilace bytecode |
Ano |
Ne |
Velikost obrazu |
Menší |
Větší (obsahuje dev nástroje) |
Health check |
Ano |
Ne |
DEV_CONTAINER proměnná |
Ne |
Ano (DEV_CONTAINER=1) |
Proč DEV NEMÁ app-builder fázi?
Vývojový obraz nepotřebuje app-builder fázi, protože:
- Nekompiluje bytecode
Vývojáři potřebují zdrojové
.pysoubory pro laděníHot-reload vývojových serverů pracuje se zdrojovými soubory
Změny kódu musí být okamžitě viditelné
- Volume mounts
Ve vývoji se mountuje
./webclient:/codeZkompilovaný bytecode by byl zastaralý
Zdrojové soubory se mění za běhu
- Jednoduchost
Méně fází = rychlejší build
Není potřeba instalovat balíčky dvakrát
Přímočařejší architektura pro vývojáře
Optimalizační techniky
BuildKit cache mounts
Použití
RUN --mount=type=cache,target=/root/.cache/pip \
pip3 wheel --wheel-dir /wheels -r /tmp/requirements.txt
Výhody
Pip cache přetrvává mezi buildy
Balíčky se stahují pouze jednou
Zrychluje opakované buildy při změně
requirements.txtNulový download při nezměněných závislostech
Aktivace
DOCKER_BUILDKIT=1 docker build -f Dockerfile .
.dockerignore soubor
Vylučuje nepotřebné soubory z build contextu:
**/__pycache__
**/*.pyc
**/*.pyo
.git/
.pytest_cache/
.coverage
*.log
node_modules/
.env
Výhody
Menší build context
Rychlejší přenos do Docker daemonu
Zabránění vložení citlivých dat (
.env)