Dockerfile bevált gyakorlatok: tippek profi image-ekhez
Réteg-sorrend a cache-ért, .dockerignore, konkrét tagek, nem-root felhasználó, kis alapképek. A legfontosabb Dockerfile bevált gyakorlatok egy helyen.
Egy Dockerfile megírása viszonylag könnyű, de egy jó Dockerfile megírása már igazi szakma. A különbség gyorsabb buildekben, kisebb image-ekben, jobb cache-kihasználásban és biztonságosabb konténerekben mutatkozik meg. Ebben a cikkben összegyűjtöttem a legfontosabb bevált gyakorlatokat, amelyeket érdemes minden projektnél alkalmazni. Mindegyikhez kapsz konkrét, copy-paste-elhető példát, hogy ne csak elméletben értsd, hanem rögtön használni is tudd.
1. Rendezd az utasításokat a cache miatt
A Docker rétegekben (layer) építi az image-et, és minden utasítás egy réteget hoz létre. A build során a Docker addig használja a cache-elt rétegeket, amíg egy utasítás vagy annak bemenete nem változik. Amint egy réteg megváltozik, az összes utána következő réteg újraépül.
A gyakorlati következmény: a ritkán változó dolgokat tedd előre, a gyakran változókat hátra. A függőségek telepítését válaszd külön a forráskód másolásától:
FROM node:22-slim
WORKDIR /app
# Ritkán változik -> jó cache-kihasználás
COPY package.json package-lock.json ./
RUN npm ci
# Gyakran változik -> csak ez épül újra kódmódosításkor
COPY . .
CMD ["node", "server.js"]
Ha a COPY . . előbb lenne, akkor minden kódmódosításkor újra lefutna az npm ci, ami feleslegesen lassítaná a buildet.
2. Vond össze a RUN utasításokat és takaríts utánuk
Minden RUN egy külön réteget hoz létre. Ha külön rétegben telepítesz csomagot és külön rétegben törlöd a cache-t, a törölt fájlok továbbra is ott maradnak egy korábbi rétegben — az image nem lesz kisebb. A megoldás: egyetlen RUN utasításban, &&-del láncolva telepíts és takaríts:
RUN apt-get update && \
apt-get install -y --no-install-recommends \
curl \
ca-certificates && \
rm -rf /var/lib/apt/lists/*
A --no-install-recommends elhagyja a felesleges ajánlott csomagokat, a rm -rf /var/lib/apt/lists/* pedig még ugyanabban a rétegben takarítja el az apt cache-t.
3. Használj .dockerignore fájlt
A .dockerignore fájl megakadályozza, hogy felesleges fájlok kerüljenek a build kontextusba (és ezzel az image-be). Ez gyorsítja a buildet és csökkenti a véletlen titokszivárgás kockázatát:
node_modules
.git
.env
*.log
dist
Dockerfile
.dockerignore
README.md
💡 Tipp: A
.gitmappa és a.envfájlok kihagyása nem csak méret-, hanem biztonsági kérdés is — ezekben gyakran lapulnak titkok vagy érzékeny adatok.
4. Rögzíts konkrét tageket, kerüld a latest-et
A FROM node:latest ma még működhet, de holnap egy teljesen más verzióra mutathat, és kiszámíthatatlanná teszi a buildjeidet. Mindig rögzíts konkrét verziót:
# Rossz: kiszámíthatatlan
FROM python:latest
# Jó: konkrét, reprodukálható
FROM python:3.12-slim
A maximális reprodukálhatóság kedvéért akár a digest-hez (SHA256) is kötheted az image-et, például FROM python:3.12-slim@sha256:.... Így garantáltan ugyanazt az alapképet kapod minden buildnél.
5. Válassz kis alapképet
Az alapkép mérete drámaian befolyásolja a végeredményt. Általában három szintet érdemes ismerni:
| Alapkép | Jellemző méret | Mikor? |
|---|---|---|
debian / teljes | 100+ MB | ha sok rendszereszköz kell |
*-slim | 30-80 MB | általános, kompatibilis választás |
*-alpine | 5-15 MB | minimális, de musl libc |
distroless | néhány MB | csak a futtatáshoz, shell nélkül |
Az alpine kicsi, de a glibc helyett musl libc-t használ, ami egyes csomagoknál kompatibilitási problémát okozhat. A -slim változatok jó kompromisszumot kínálnak. Ha pedig a lehető legkisebb és legbiztonságosabb image-et akarod, a distroless a befutó.
6. Ne futtasd root felhasználóként
Alapból a konténerek root felhasználóként futnak, ami felesleges kockázat. Hozz létre és válts egy nem-root felhasználóra:
FROM node:22-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
COPY . .
# Nem-root felhasználó létrehozása és váltás
RUN useradd --create-home --shell /bin/bash appuser
USER appuser
CMD ["node", "server.js"]
Sok hivatalos image már tartalmaz egy beépített nem-root felhasználót (például a node image-ben a node felhasználó), így gyakran elég egy USER node sor.
⚠️ Figyelem: A
USERváltás után aCOPYáltal írt fájlok tulajdonjogára is figyelj. Használhatod aCOPY --chown=appuser:appuser . .formát, hogy a fájlok rögtön a megfelelő felhasználóé legyenek.
7. Egy konténer, egy folyamat
A konténerek filozófiája szerint egy konténer ideális esetben egyetlen fő folyamatot futtat. Ne pakold ugyanabba a konténerbe a webszervert, az adatbázist és a cache-t. Bontsd külön őket, és kösd össze a szolgáltatásokat. Ehhez a Docker Compose bevezető ad jó kiindulópontot. Így könnyebb skálázni, frissíteni és hibát keresni.
8. COPY-t használj ADD helyett
Az ADD utasítás többet tud (URL-ek letöltése, tömörített fájlok automatikus kicsomagolása), de pont emiatt kevésbé kiszámítható és kockázatosabb. A bevett szabály: használj COPY-t, hacsak nincs konkrét szükséged az ADD extra funkcióira:
# Egyszerű, kiszámítható
COPY app.jar /app/app.jar
9. Aknázd ki a multi-stage buildet
A build eszközöknek nincs helyük a végső image-ben. A multi-stage build segítségével a fordítást egy “buildelő” fázisban végzed, majd csak a kész artefaktumot viszed át a minimális futtató image-be. Ez gyakran tört részére csökkenti a méretet. Erről részletesen írtam a Multi-stage build cikkben — érdemes elolvasni, mert szinte minden komolyabb projektben hasznos.
10. Adj hozzá HEALTHCHECK-et
A HEALTHCHECK segít az orchestrátornak (vagy a Compose-nak) eldönteni, hogy a konténer valóban egészséges-e, nem csak fut:
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
Az --interval az ellenőrzések gyakorisága, a --timeout a megengedett válaszidő, a --retries pedig hány sikertelen próba után minősül a konténer beteggé. Ezután a docker ps kimenetében látszik az állapot (healthy/unhealthy).
Egy összerakott példa
Lássuk, hogyan néz ki sok tipp együtt, egy tipikus Node.js alkalmazásnál:
FROM node:22-slim
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev && npm cache clean --force
COPY --chown=node:node . .
USER node
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s CMD node healthcheck.js || exit 1
CMD ["node", "server.js"]
Összefoglalás
A jó Dockerfile néhány következetesen alkalmazott szabályon múlik: rendezd az utasításokat a cache miatt, vond össze és takaríts a RUN-okban, használj .dockerignore-t, rögzíts konkrét tageket, válassz kis alapképet, futtass nem-root felhasználóként, tarts egy folyamatot konténerenként, használj COPY-t, aknázd ki a multi-stage buildet, és adj hozzá HEALTHCHECK-et. Ezekkel az image-eid gyorsabbak, kisebbek és biztonságosabbak lesznek.
Most pedig nyisd meg a saját Dockerfile-odat, és nézd át pontról pontra! Ha még az alapokat csiszolnád, kezdd a Kezdő lépések útmutatóval, vagy ha még nem telepítetted a Dockert, a Telepítés oldal segít elindulni.