Dockerfile schreiben und optimieren
Was dieser Artikel über Dockerfiles behandelt
- Aufbau eines Dockerfile.
- Wichtige Anweisungen und ihre Reihenfolge.
- Layer, Caching und Image-Grösse.
- Sicherheit und Clean Builds.
- Typische Fehler und Lösungen.
Einleitung: Dockerfile schreiben und optimieren
Ein Dockerfile ist das Rezept für ein Docker-Image. Es legt fest, welches Basis-Image verwendet wird, welche Dateien kopiert werden, welche Befehle ausgeführt werden und wie der Container startet. Ein gut geschriebenes Dockerfile sorgt für kleine, sichere und schnell bauende Images. Ein schlechtes Dockerfile führt zu langen Build-Zeiten, grossen Images und Sicherheitslücken.
Dieser Artikel erklärt die Grundlagen, wichtige Anweisungen und Best Practices für saubere Dockerfiles.
Wichtige Begriffe
- FROM: Basis-Image.
- RUN: Befehl ausführen.
- COPY: Dateien kopieren.
- ADD: Dateien kopieren und entpacken.
- CMD: Standardbefehl beim Start.
- ENTRYPOINT: Festes Startkommando.
- WORKDIR: Arbeitsverzeichnis.
- ENV: Umgebungsvariable.
- EXPOSE: Port deklarieren.
- USER: Benutzer wechseln.
- Layer: Schicht im Image.
- Cache: Zwischenspeicher für Builds.
Grundaufbau
FROM node:20-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
USER node
EXPOSE 3000
CMD ["node", "server.js"]
FROM wählen
| Image | Grösse | Einsatz |
|---|---|---|
ubuntu | gross | Kompatibilität |
debian:slim | mittel | Vielseitig |
alpine | klein | Klein, aber musl |
distroless | sehr klein | Minimal, keine Shell |
Empfehlung: Offizielle Slim-Images oder Distroless für produktive Container.
Reihenfolge beachten
Docker cached Layer. Dateien, die sich selten ändern, zuerst kopieren:
- Basis-Image.
- Abhängigkeitsdateien.
- Abhängigkeiten installieren.
- Quellcode kopieren.
- Build-Schritte.
- Laufzeitbefehl.
Falsch:
COPY . .
RUN npm ci
Richtig:
COPY package*.json ./
RUN npm ci
COPY . .
COPY vs ADD
COPYkopiert einfach Dateien.ADDkann URLs und Tar-Archive verarbeiten.- In den meisten Fällen ist
COPYsicherer und vorhersehbarer.
Layer minimieren
Jede RUN, COPY und ADD-Anweisung erzeugt einen Layer. Weniger Layer bedeuten kleinere Images:
RUN apt-get update && \
apt-get install -y --no-install-recommends curl ca-certificates && \
rm -rf /var/lib/apt/lists/*
Image-Grösse reduzieren
.dockerignorenutzen.- Nur Produktionsabhängigkeiten installieren.
- Build-Tools entfernen.
- Multistage-Builds einsetzen.
- Keine unnötigen Dateien kopieren.
Beispiel .dockerignore:
node_modules
.git
.env
Dockerfile
README.md
tests
Sicherheit
- Non-root User nutzen:
RUN useradd -m appuser
USER appuser
- Keine Secrets im Dockerfile.
- Keine Passwörter in Umgebungsvariablen hinterlegen.
- Rechte minimal halten.
- Read-only-Dateisystem nutzen, wenn möglich.
CMD und ENTRYPOINT
CMD ist der Standardbefehl, ENTRYPOINT ist das fixe Kommando. Kombination:
ENTRYPOINT ["node"]
CMD ["server.js"]
Healthchecks
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
Build-Befehl
docker build -t mein-image:1.0 .
Build-Caching erzwingen
docker build --no-cache -t mein-image:1.0 .
Logs und Umgebung
- Logs nach
stdout/stderrausgeben. - Konfiguration über Umgebungsvariablen.
- Keine festen Pfade in Images hinterlegen.
Typische Stolpersteine
- Alles in einem Layer: grosse Images.
- Build-Tools im Runtime-Image: Sicherheitsrisiken.
- Secrets in Umgebungsvariablen: bei Images oder Logs sichtbar.
- Falsche FROM-Version:
latestanstelle fester Tags. - Dockerignore fehlt: unnötige Dateien landen im Image.
- Rechte falsch: Container läuft als root.
- CMD als Shell-Form: Signale werden nicht korrekt weitergegeben.
Weiterführende Links und Infos
- BotServ.de Docker Multistage-Builds
- BotServ.de Docker Befehle
- BotServ.de Docker Image-Optimierung
- BotServ.de Docker Sicherheit
FAQ: Dockerfile
Was ist ein Dockerfile? Eine Textdatei mit Anweisungen zum Bau eines Docker-Images.
Soll ich COPY . . verwenden?
Nur mit .dockerignore, sonst landen unnötige Dateien im Image.
Was ist besser: Alpine oder Debian Slim? Debian Slim ist einfacher kompatibel, Alpine ist kleiner, aber musl-basiert.
Wie reduziere ich die Build-Zeit?
Reihenfolge der Layer beachten, Cache nutzen, .dockerignore setzen.
Warum einen Non-Root-User nutzen? Es reduziert das Risiko, falls ein Container kompromittiert wird.
Quellen und weiterführende Literatur
- Dockerfile Referenz: https://docs.docker.com/reference/dockerfile/
- Docker Best Practices: https://docs.docker.com/develop/dev-best-practices/
- BuildKit: https://docs.docker.com/build/buildkit/
Zusammenfassung: Dockerfile schreiben und optimieren
Ein gutes Dockerfile ist der Schlüssel zu schnellen Builds, kleinen Images und sicheren Containern. Wichtig sind die richtige Reihenfolge der Anweisungen, effektives Caching, Multistage-Builds, .dockerignore, Non-Root-Benutzer und feste Image-Tags. Wer diese Prinzipien beachtet, vermeidert typische Probleme und baut Docker-Images, die sich sowohl im Homelab als auch produktiv gut betreiben lassen.


