Linuxguide

Dockerfile Best Practices – Production-ready Images bauen 2025

Layer-Cache, minimale Images und sichere Defaults

S
SeeColors IT
11. Juni 20264 Min. Lesezeit131 Aufrufe

Das optimale Dockerfile

# 1. Spezifisches Base-Image (kein 'latest')
FROM node:20.11-alpine3.19

# 2. OCI-Labels für Metadaten
LABEL org.opencontainers.image.title="MeineApp" \
      org.opencontainers.image.version="1.0.0" \
      org.opencontainers.image.authors="[email protected]"

# 3. Sicherheit: Kein root
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# 4. Arbeitsverzeichnis setzen
WORKDIR /app

# 5. Dependencies ZUERST (für Cache-Optimierung)
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force

# 6. Quellcode danach
COPY --chown=appuser:appgroup . .

# 7. Benutzer wechseln
USER appuser

# 8. Port dokumentieren
EXPOSE 3000

# 9. Healthcheck
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
  CMD node healthcheck.js || exit 1

# 10. Klarer Entrypoint
CMD ["node", "server.js"]

Die wichtigsten Regeln

1. Spezifische Tags statt latest

# Schlecht – nicht reproduzierbar
FROM node:latest

# Gut – deterministisch
FROM node:20.11.0-alpine3.19

2. Layer-Cache optimal nutzen

# Richtige Reihenfolge: was sich selten ändert kommt zuerst
RUN apt-get update && apt-get install -y --no-install-recommends \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Dependencies vor Source-Code
COPY package.json package-lock.json ./
RUN npm ci

# Source-Code zuletzt (invalidiert Cache am häufigsten)
COPY . .

3. .dockerignore

# .dockerignore
node_modules
.git
.env
*.log
dist
coverage
.DS_Store
Dockerfile*
docker-compose*
README.md

4. RUN-Befehle zusammenfassen

# Schlecht – jedes RUN erstellt einen Layer
RUN apt-get update
RUN apt-get install -y curl
RUN apt-get clean

# Gut – ein Layer
RUN apt-get update \
    && apt-get install -y --no-install-recommends curl \
    && rm -rf /var/lib/apt/lists/*

5. Alpine für kleine Images

FROM node:20-alpine    # ~50 MB
# statt
FROM node:20           # ~900 MB

6. Healthcheck

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
  CMD curl -f http://localhost:3000/health || exit 1

Ohne Healthcheck weiß Docker nicht ob Ihr Container wirklich funktioniert (nur ob er läuft).

7. ENTRYPOINT vs CMD

# ENTRYPOINT: feste Basis-Kommando
# CMD: Standard-Argumente (überschreibbar)
ENTRYPOINT ["node"]
CMD ["server.js"]

# docker run myapp               → node server.js
# docker run myapp worker.js     → node worker.js

8. ARG für Build-Zeit Variablen

ARG NODE_ENV=production
ARG APP_VERSION=1.0.0
ENV NODE_ENV=${NODE_ENV}
LABEL version=${APP_VERSION}
docker build --build-arg NODE_ENV=staging --build-arg APP_VERSION=1.2.3 .

Image-Größe analysieren

# Dive – interaktiver Layer-Inspektor
docker run --rm -it \
  -v /var/run/docker.sock:/var/run/docker.sock \
  wagoodman/dive:latest myapp:latest

# Einzel-Layer-Größen
docker history myapp:latest

FAQ

Soll ich COPY oder ADD nutzen?
COPY für einfaches Kopieren. ADD nur wenn Sie tar-Archive entpacken oder URLs laden müssen (verwirrend und fehleranfällig).

Wann nutze ich SHELL statt RUN?
SHELL ["/bin/bash", "-o", "pipefail", "-c"] vor RUN wenn Sie Pipes nutzen und Fehler korrekt abfangen wollen.

Fazit

Ein gutes Dockerfile kostet 10 Minuten Mehraufwand und spart Stunden bei Debugging, Deployment-Problemen und Security-Incidents.

Container-Optimierungen für Entwicklungsteams in Heidelberg und der Rhein-Neckar-Region. Anfragen.

Artikel teilen

War dieser Artikel hilfreich?

Dein Feedback hilft uns, bessere Inhalte zu erstellen.

Kommentar hinterlassen

Verwandte Artikel