- 1 Section
- 10 Lessons
- unbegrenzt
- Docker & Container10
- 1.1Container vs. VM
- 1.2Docker-Architektur: Client, Daemon, Registry
- 1.3Images und Container: pull, run, stop, rm
- 1.4Dockerfile – eigene Images bauen
- 1.5Volumes: persistente Daten
- 1.6Netzwerke in Docker: bridge, host, overlay
- 1.7Docker Compose: Multi-Container-Anwendungen
- 1.8Docker in der CI/CD-Pipeline
- 1.9Sicherheit in Docker-Umgebungen
- 1.10Aufgaben Docker
Dockerfile – eigene Images bauen
Ein Container-Image aus dem öffentlichen Docker Hub zu pullen ist einfach – aber meistens reicht das nicht. Du willst eigene Anwendungen, eigene Konfigurationen, eigene Versionsstände paketieren. Genau dafür gibt es das Dockerfile: eine Textdatei mit Anweisungen, wie ein Image gebaut werden soll. Sie ist gleichzeitig Bauplan, Dokumentation und Versionsstand der Anwendung. Wer Dockerfiles richtig schreibt, baut kleine, schnelle, sichere Images. Wer sie schlecht schreibt, baut 2-GB-Klötze, die jede CI-Pipeline lähmen und Sicherheitslücken einschleppen. Genau das macht diese Lektion zum Kern der praktischen Docker-Beherrschung.
Ein Dockerfile ist wie ein Rezept. Es listet Zutaten (Base-Image, Pakete, Quellcode) und Arbeitsschritte (kopieren, installieren, konfigurieren). Wenn das Rezept klar ist, kann jeder dieselbe Mahlzeit nachkochen – egal in welcher Küche.
1) Ein erstes Dockerfile zerlegt
Hier ist ein typisches Dockerfile für eine kleine Node.js-Anwendung. Klick jede Zeile, um die Anweisung zu verstehen – und sieh, welcher Layer dabei entsteht:
2) Die wichtigsten Dockerfile-Anweisungen
Ein Dockerfile kennt rund ein Dutzend Anweisungen – jede mit klarer Aufgabe. Hier die wichtigsten kompakt:
FROM
Basis-Image. Erste Anweisung Pflicht. Bsp.: FROM debian:12-slim
RUN
Befehl im Image ausführen, Ergebnis = Layer. Bsp.: RUN apt-get update && apt-get install -y curl
COPY
Dateien vom Build-Kontext ins Image kopieren. COPY src/ /app/src/
ADD
Wie COPY, kann zusätzlich URLs laden und tar entpacken. Best Practice: COPY bevorzugen (klarer).
WORKDIR
Arbeitsverzeichnis setzen. WORKDIR /app
ENV
Umgebungsvariable im Image. ENV NODE_ENV=production
ARG
Build-Zeit-Variable (nicht zur Laufzeit). ARG VERSION=1.0
EXPOSE
Doku: welcher Port wird benutzt. Öffnet ihn NICHT – das macht -p.
USER
Wechselt den Benutzer (Sicherheit!). Standard: root. USER nobody
VOLUME
Mountpoint für ein Volume deklarieren.
CMD
Standardbefehl beim Container-Start. Genau einer pro Dockerfile. Kann beim Run überschrieben werden.
ENTRYPOINT
Wie CMD, aber NICHT überschreibbar – Argumente werden angehängt. Für „Wrapper"-Container.
HEALTHCHECK
Befehl, der periodisch prüft, ob der Container „gesund" ist.
LABEL
Metadaten anhängen. LABEL version="2.1" maintainer="ops@firma.de"
docker run image bash startet bash statt CMD). ENTRYPOINT ist fest, alle Argumente werden angehängt. Für Tools wie docker run my-cli --help nutzt man oft ENTRYPOINT für das eigentliche Programm und CMD für die Default-Argumente.3) Layer-Cache – das wichtigste Performance-Konzept
Jede RUN, COPY und ADD-Anweisung erzeugt einen neuen Layer. Docker cached diese Layer: Wenn sich eine Anweisung (und alle darüberliegenden) nicht ändert, wird der Layer aus dem Cache genommen, statt neu gebaut. Das macht einen riesigen Unterschied: Ein erster Build dauert vielleicht 3 Minuten, ein zweiter mit gleichem Stand 5 Sekunden.
Die Reihenfolge der Anweisungen entscheidet, wie effektiv der Cache ist. Die goldene Regel: Was sich selten ändert, kommt nach oben. Was sich oft ändert, kommt nach unten.
COPY package*.json → RUN npm ci → COPY . .). Das npm ci ist der langsamste Schritt; durch die Trennung wird er nur neu ausgeführt, wenn sich die Abhängigkeiten ändern – nicht bei jeder Code-Änderung.4) Multi-Stage Builds – kleine Images mit großem Build-Toolset
Bei kompilierten Sprachen wie Go, Java oder C++ hat man ein Problem: Zum Bauen braucht man Compiler, Build-Tools, Test-Frameworks. Im Produktions-Image will man die alle nicht haben – sie machen das Image groß und erhöhen die Angriffsfläche. Die Lösung: Multi-Stage Builds. Du baust in einem ersten Stage mit vollem Toolset, kopierst nur das fertige Binary in einen schlanken zweiten Stage. Beispiel:
5) .dockerignore – was NICHT ins Image gehört
Beim docker build wird der gesamte Verzeichnisinhalt (der „Build-Kontext") an den Daemon geschickt. Das ist langsam, wenn der Ordner groß ist – z. B. mit lokalen node_modules, Git-History oder Build-Artefakten. Außerdem landen Dateien, die du nicht im Image willst (Secrets!), möglicherweise im Image.
Die Lösung: eine .dockerignore-Datei. Sie funktioniert wie .gitignore und schließt Pfade vom Kontext aus:
COPY package.json . nur eine Datei kopierst, sendet Docker erst den GESAMTEN Kontext an den Daemon. Eine fehlende .dockerignore bedeutet: 500 MB node_modules reisen sinnlos durch den Build. Außerdem: Wer .env nicht ignoriert, hat möglicherweise Passwörter und API-Keys in seinem Image – die später in der Registry landen.6) Best Practices für produktionsreife Dockerfiles
Die folgenden Regeln machen den Unterschied zwischen einem Quick-Hack und einem Image, das tausendfach in Produktion läuft:
- Schlanke Base-Images nutzen:
alpine(~5 MB) oderdistroless(~2-10 MB) statt voller Distributionen (~70-400 MB). Bei Sprachen wie Go reicht oftFROM scratch(leeres Image). - Versionen pinnen: Nicht
FROM node, sondernFROM node:20.11.0-alpine3.19. Reproduzierbarkeit! - RUN-Anweisungen zusammenfassen:
RUN apt-get update && apt-get install -y curlin einer Zeile statt zwei – das vermeidet veraltete Update-Caches und spart einen Layer. - Aufräumen im selben RUN:
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*. Sonst landet der Paket-Cache im Layer. - Niemals als Root laufen: Mit
USEReinen unprivilegierten Nutzer setzen. Mehr in Docker-Sicherheit. - Multi-Stage nutzen für kompilierte Sprachen.
- HEALTHCHECK definieren für Produktions-Container, damit Docker / Kubernetes weiß, wann ein Container „wirklich" bereit ist.
- LABEL für Metadaten:
LABEL org.opencontainers.image.source="https://github.com/firma/repo"– wird von Registries gelesen. - Secrets niemals ins Image: Keine API-Keys, Passwörter, Zertifikate. Stattdessen zur Laufzeit per Umgebungsvariable, Volume oder Secret-Management (Kubernetes Secrets, HashiCorp Vault).
- Reihenfolge cache-freundlich: Was sich oft ändert (Quellcode) kommt unten, was sich selten ändert (Dependencies) oben.
7) Image bauen und veröffentlichen
Wenn das Dockerfile fertig ist, baut man das Image und kann es in eine Registry pushen:
Zusammenfassung
Ein Dockerfile ist eine Textdatei mit Anweisungen, wie ein Image gebaut wird. Wichtige Anweisungen: FROM (Basis-Image), RUN (Befehl ausführen, erzeugt Layer), COPY (Dateien rein), WORKDIR (Arbeitsverzeichnis), ENV (Umgebungsvariable), USER (Sicherheit!), EXPOSE (Port-Doku), CMD/ENTRYPOINT (Standardbefehl). Jede Anweisung erzeugt einen Layer, der gecached wird – Reihenfolge ist Performance-entscheidend: erst COPY package.json, dann RUN npm install, dann COPY . .. Multi-Stage Builds trennen Build-Toolset vom finalen Image – aus 700 MB werden 20 MB. .dockerignore hält unerwünschte Dateien (node_modules, .git, .env) aus dem Build-Kontext. Best Practices: schlanke Base-Images (alpine, distroless), Versionen pinnen, nicht als root laufen, Multi-Stage, HEALTHCHECK, keine Secrets im Image. Ablauf: docker build → docker tag → docker push, automatisierbar in jeder CI/CD-Pipeline.
Verwandte Lektionen: Docker Images & Container · Docker-Architektur · Docker-Sicherheit · und mehrWeitere relevante LektionenDocker VolumesDocker-NetzwerkeDocker ComposeDocker in CI/CDCI/CD-Pipeline-AufbauGit-WorkflowsDependency Management
