Ein Docker-Image ist eine unveränderliche, schreibgeschützte Vorlage mit einem Dateisystem, das alles enthält, was zum Ausführen einer Anwendung nötig ist (Code, Abhängigkeiten, Konfiguration). Ein Container ist eine laufende Instanz dieses Images mit einer eigenen beschreibbaren Schicht. Die nützlichste Analogie stammt aus der objektorientierten Programmierung: Das Image ist die Klasse, der Container das Objekt. Aus einem Image kannst du beliebig viele Container starten, jeder isoliert von den anderen.
Wenn du gerade mit Docker anfängst, ist genau diese Unterscheidung die, die die meisten Verwirrungen vermeidet: Was wird heruntergeladen, was läuft, was belegt Speicher und was geht beim Löschen verloren.
Was ein Image ist
Ein Image wird in Schichten aufgebaut. Jede Anweisung eines Dockerfile (FROM, RUN, COPY…) erzeugt eine Schicht, und die Schichten stapeln sich: Unten liegt meist ein Basissystem (Debian, Alpine, Ubuntu), darüber die Abhängigkeiten und ganz oben der Code deiner Anwendung. Schichten sind schreibgeschützt und werden zwischen Images geteilt: Gehen zehn Images von derselben Basis aus, belegt diese Basis nur einmal Speicherplatz.
Images werden über Name und Tag identifiziert (node:22-alpine, nginx:1.27) und über Registries wie Docker Hub verteilt.
# Ein Image herunterladen
docker pull nginx:1.27
# Lokale Images auflisten
docker images
# Ein Image aus dem Dockerfile im aktuellen Verzeichnis bauen
docker build -t meine-app:1.0 .
# Ein Image löschen (nur wenn kein Container es nutzt)
docker rmi meine-app:1.0
Was ein Container ist
Ein Container ist ein Prozess (oder eine Prozessgruppe), der isoliert vom Rest des Systems läuft, das Image als Basisdateisystem nutzt und darüber eine beschreibbare Schicht legt. Alles, was die Anwendung zur Laufzeit schreibt (Logs, temporäre Dateien, Daten), landet in dieser Schicht. Wird der Container gelöscht, verschwindet die beschreibbare Schicht mit ihm; das Image bleibt unberührt.
# Container aus einem Image erstellen und starten
docker run -d --name web -p 8080:80 nginx:1.27
# Laufende Container auflisten (-a schließt gestoppte ein)
docker ps
docker ps -a
# Logs ansehen und in den Container wechseln
docker logs web
docker exec -it web sh
# Stoppen, erneut starten und löschen
docker stop web
docker start web
docker rm web
docker run tut zwei Dinge auf einmal: Es erstellt den Container (docker create) und startet ihn (docker start). Führst du docker run dreimal mit demselben Image aus, erhältst du deshalb drei verschiedene Container, nicht einen.
Die Beziehung der beiden in einer Tabelle
| Image | Container | |
|---|---|---|
| Was es ist | Schreibgeschützte Vorlage | Laufende (oder gestoppte) Instanz eines Images |
| Erstellt mit | docker build, docker pull |
docker run, docker create |
| Aufgelistet mit | docker images |
docker ps -a |
| Gelöscht mit | docker rmi |
docker rm |
| Ändert sich zur Laufzeit? | Nein | Ja, in seiner beschreibbaren Schicht |
| Wie viele kann es geben? | Eines pro Name:Tag | Beliebig viele pro Image |
Wo Daten liegen: Volumes
Da die beschreibbare Schicht mit dem Container stirbt, müssen Daten, die überleben sollen (eine Datenbank, von Nutzern hochgeladene Dateien), außerhalb liegen, in einem Volume oder einem in den Container eingebundenen Host-Verzeichnis:
# Von Docker verwaltetes Volume
docker run -d --name db -v db-daten:/var/lib/postgresql/data postgres:16
# Host-Verzeichnis (Bind Mount), praktisch in der Entwicklung
docker run -d --name web -v "$(pwd)/html:/usr/share/nginx/html:ro" -p 8080:80 nginx:1.27
So kannst du den Container löschen und neu erstellen, ohne Daten zu verlieren. Die Dokumentation zu Volumes beschreibt die Unterschiede zwischen beiden Optionen.
Häufige Fehler
- Glauben,
docker stopgebe Speicher frei. Ein gestoppter Container existiert weiter mit seiner beschreibbaren Schicht. Speicher gibt erstdocker rmfrei (oderdocker run --rm, damit er sich nach dem Ende selbst löscht). - Daten im Container speichern. Funktioniert, bis du ihn neu erstellst. Nutze von Anfang an Volumes.
- Einen Container ändern und erwarten, dass sich das Image ändert. Passiert nicht. Soll eine Änderung Teil des Images werden, nimm sie im
Dockerfilevor und baue neu.docker commitexistiert, erzeugt aber nicht reproduzierbare Images und sollte vermieden werden. - Verwaiste Images und Container ansammeln.
docker system dfzeigt, wie viel sie belegen;docker system pruneentfernt gestoppte Container, ungenutzte Netzwerke und hängende Images (mit Rückfrage). - Den Tag
latestin Produktion verwenden.lateständert sich mit der Zeit; fixiere eine konkrete Version (node:22.12-alpine), damit das Deployment reproduzierbar ist.
Fazit
Das Image ist die Vorlage, der Container die Ausführung. Images werden gebaut und heruntergeladen, Container gestartet, gestoppt und gelöscht, und dauerhafte Daten gehören in Volumes. Sind diese drei Konzepte klar, versteht sich der Rest von Docker (Netzwerke, Compose, Registries) als Kombination derselben Ideen.