Das erste Docker-Image bauen
Das erste Docker-Image zu bauen wirkt am Anfang vielleicht einschüchternd, ist aber eine Grundfähigkeit, wenn man aus containerisierten Umgebungen etwas herausholen will. Diese Anleitung geht die Grundlagen durch, ein Image über ein Dockerfile zu erzeugen.
Voraussetzungen
Bevor du anfängst, stelle sicher, dass Folgendes vorhanden ist:
- Docker: Docker installieren, falls es noch nicht auf deinem System liegt.
- Ein grundlegendes Verständnis von Containern und Images (fang hier an).
Schritt für Schritt: das erste Docker-Image
Wir bauen eine einfache Python-Anwendung und containerisieren sie.
-
Projektverzeichnis anlegen
Lege ein Verzeichnis für die Anwendung an:
mkdir my-docker-appcd my-docker-appErstelle darin die folgenden Dateien:
app.py# A simple Python applicationprint("Hello, Docker!")requirements.txt# No dependencies for this simple example -
Dockerfile schreiben
Ein
Dockerfileist eine Textdatei mit den Anweisungen, aus denen ein Image zusammengesetzt wird. Ein einfaches Beispiel:Dockerfile# Use an official Python runtime as the base imageFROM python:3.9-slim# Set the working directory inside the containerWORKDIR /app# Copy the requirements file and install dependenciesCOPY requirements.txt ./RUN pip install --no-cache-dir -r requirements.txt# Copy the application code into the containerCOPY app.py ./# Define the command to run the applicationCMD ["python", "app.py"] -
Image bauen
Führe im Projektverzeichnis aus:
docker build -t my-docker-app .Was dabei passiert:
-t my-docker-app: taggt das Image mit dem Namen my-docker-app..: bestimmt das aktuelle Verzeichnis als Build-Kontext.
-
Container starten
Sobald das Image gebaut ist, erzeugst und startest du einen Container mit:
docker run my-docker-appDie Ausgabe sollte lauten:
Hello, Docker! -
Image prüfen
Um deine Images aufzulisten:
docker imagesDu siehst dann etwas wie:
REPOSITORY TAG IMAGE ID CREATED SIZEmy-docker-app latest abc12345defg 1 minute ago 29MB
Sicherheitsverbesserungen für Docker-Images
Minimale Base-Images verwenden: Ersetze allgemeine Base-Images durch minimale Varianten, um die Angriffsfläche zu verkleinern:
# Instead of python:3.9
FROM python:3.9-slim
# Or even better, use Alpine
FROM python:3.9-alpine
# For production, consider distroless
FROM gcr.io/distroless/python3
Als Non-Root-Nutzer laufen: Lege einen eigenen Nutzer an und verwende ihn, statt als root zu laufen:
FROM python:3.9-slim
WORKDIR /app
# Create non-root user
RUN addgroup --system appgroup && \
adduser --system --ingroup appgroup appuser
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py ./
# Switch to non-root user
USER appuser
CMD ["python", "app.py"]
Multi-Stage-Builds: Trenne Build-Abhängigkeiten von der Laufzeit, um das Endimage klein zu halten:
# Build stage
FROM python:3.9 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt
# Runtime stage
FROM python:3.9-slim
WORKDIR /app
# Copy only necessary files from builder
COPY /root/.local /root/.local
COPY app.py .
ENV PATH=/root/.local/bin:$PATH
CMD ["python", "app.py"]
Auf Schwachstellen scannen: Bau das Security-Scanning in den Build-Prozess ein:
# Build image
docker build -t my-docker-app .
# Scan for vulnerabilities
trivy image my-docker-app
# Block deployment if critical vulnerabilities found
trivy image --severity CRITICAL --exit-code 1 my-docker-app
Abhängigkeiten pinnen: Nenne exakte Versionen in requirements.txt, damit Builds reproduzierbar sind:
flask==2.3.2
psycopg2==2.9.6
.dockerignore nutzen: Halte unnötige Dateien aus dem Build-Kontext heraus:
.git
.gitignore
.env
.env.local
*.md
__pycache__
*.pyc
tests/
.vscode/
.idea/
Health Checks ergänzen: Damit Docker den Zustand des Containers überwachen kann:
FROM python:3.9-slim
WORKDIR /app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py ./
HEALTHCHECK \
CMD python -c "import requests; requests.get('http://localhost:5000/health')"
CMD ["python", "app.py"]
Sinnvolle Labels setzen: Metadaten für Nachvollziehbarkeit und Verwaltung:
LABEL maintainer="your.email@example.com"
LABEL version="1.0.0"
LABEL description="Python application"
LABEL org.opencontainers.image.source="https://github.com/user/repo"
Layer-Caching ausnutzen: Ordne Anweisungen von selten zu häufig wechselnd:
FROM python:3.9-slim
WORKDIR /app
# These change rarely, cache them
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Application code changes frequently, copy last
COPY . .
CMD ["python", "app.py"]
Zusammenfassung
Security-Checkliste:
- Minimale, konkrete Base-Images mit Versions-Tag verwenden
- Container als Non-Root-Nutzer laufen lassen
- Images vor dem Ausrollen auf Schwachstellen scannen
- Nie Secrets in Images legen
- Multi-Stage-Builds nutzen, um die Angriffsfläche zu verkleinern
- Health Checks für Verlässlichkeit einbauen
- Abhängigkeiten aktuell halten und pinnen
- .dockerignore nutzen, um sensible Dateien auszuschließen
Image-Verwaltung:
- Images mit semantischen Versionen taggen, nicht nur mit latest
- Images in private Registries mit Zugriffskontrolle pushen
- Signieren und Prüfen von Images aktivieren
- Images regelmäßig neu bauen, damit Sicherheitspatches einfließen
- Unbenutzte Images entfernen, das spart Platz und vermeidet Verwechslungen
Testen:
- Images vor Produktion in isolierten Umgebungen testen
- Ergebnisse der Security-Scans prüfen
- Funktion der Health Checks nachweisen
- Ressourcengrenzen und Beschränkungen testen
- Korrekte Nutzerrechte bestätigen