Dockerfile Best Practices - was wirklich zählt
Dockerfile Best Practices - was wirklich zählt
Es gibt viele Ratschläge für Dockerfiles — dieser Artikel fokussiert auf die Punkte, die in der Praxis tatsächlich einen Unterschied machen.
1. Spezifische Basis-Image-Tags pinnen
# Schlecht
FROM node:latest
# Gut
FROM node:20.11.0-slim
latest ist kein Version — bei einem docker pull kann Breaking Change kommen. Exakte Tags machen Builds reproduzierbar.
2. Einen Prozess pro Container
Container sollten genau einen Hauptprozess haben. Nicht nginx + PHP-FPM + cron in einen Container — das ist das Konzept klassischer VMs, nicht Container.
Mehrere Dienste: Docker Compose oder Kubernetes, jeder Dienst sein eigener Container.
3. Non-Root-User verwenden
Standardmäßig laufen Container als root. Das ist ein unnötiges Risiko.
FROM node:20-slim
WORKDIR /app
COPY --chown=node:node . .
RUN npm ci --omit=dev
USER node
CMD ["node", "index.js"]
Bei Debian-basierten Images ist node-User bereits vorhanden. Alternativ:
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
USER appuser
4. RUN-Befehle zusammenfassen und bereinigen
# Schlecht: drei Layer, Cache bleibt in Layer 1
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
# Gut: ein Layer, Bereinigung im selben Schritt
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl \
&& rm -rf /var/lib/apt/lists/*
5. HEALTHCHECK definieren
Docker und Container-Orchestratoren können Container auf Gesundheit prüfen — aber nur wenn ein Healthcheck definiert ist.
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
Ohne Healthcheck gilt ein Container mit dem Status running als gesund — auch wenn die Anwendung intern hängt.
6. Exec Form für CMD und ENTRYPOINT
# Shell Form: PID 1 ist /bin/sh, Signale kommen nicht an
CMD node index.js
# Exec Form: PID 1 ist node, SIGTERM wird korrekt empfangen
CMD ["node", "index.js"]
7. Instructions nach Änderungshäufigkeit sortieren
Was sich selten ändert, gehört nach oben (Basis-Image, System-Pakete, Dependencies). Was sich oft ändert (Quellcode), ans Ende. So bleibt der Layer-Cache so lange wie möglich gültig.
8. Images labeln
LABEL maintainer="team@example.com"
LABEL version="2.1.4"
LABEL description="API server for product service"
Labels sind über docker inspect abrufbar und helfen bei der Verwaltung von Images in Registries.
9. .dockerignore pflegen
Kein .git, kein node_modules, keine .env-Dateien im Build-Kontext. Weniger Kontext = schnellerer Build und keine versehentlichen Secrets im Image.