Docker für Anfänger: Installation, Container und Images verstehen
Docker Schritt für Schritt lernen: Begriffe wie Image und Container, Installation unter Debian und Ubuntu, ersten Webserver starten, Container verwalten und Docker aktualisieren.

Inhalt
Docker 29.9Docker Compose 5.7nginx 1.30Debian 13Ubuntu 26.04Du hast ein Programm auf deinem Rechner zum Laufen gebracht, kopierst es auf einen Server, und dort geht plötzlich nichts mehr. Eine Bibliothek fehlt, die Version stimmt nicht, ein anderes Programm belegt denselben Port. Docker löst dieses Problem, indem es ein Programm samt allem, was es zum Laufen braucht, in ein einziges Paket steckt. Dieses Paket startet auf jedem Rechner mit Docker auf dieselbe Weise.
In diesem Beitrag installieren wir Docker auf einem Linux-Server und starten damit Schritt für Schritt einen Webserver.
Was du brauchst
- Einen Linux-Server, am besten mit Debian oder Ubuntu. Ob Cloud-Server, Raspberry Pi oder Rechner im Heimnetz, spielt für die Docker-Befehle keine Rolle. Ich nutze im Folgenden Server mit Debian 13 und Ubuntu 26.04. Wie du einen Server auswählst und absicherst, steht in meiner Anleitung VPS für Anfänger. Wenn du ihn bei Hetzner anlegst, hilft dir der Cloud-Init-Generator beim Einrichten des Benutzers.
- Eine Verbindung per SSH. Das ist der Weg, auf dem dein Computer Befehle an den Server schickt. Auch dazu findest du alles in der VPS-Anleitung.
- Einen Benutzer, der
sudoverwenden darf. Im Folgenden heißt er deployn. Wenn du alsrootangemeldet bist, lässt du bei allen Befehlen das Wortsudoweg.
Die Befehle in den grauen Kästen kopierst du in das Terminal und bestätigst mit Enter. Zeichen wie $ am Zeilenanfang gehören nicht dazu, ich schreibe sie auch nicht hin. Mit dem Terminal selbst fremdelst du noch? Dann lies vorher die wichtigsten Linux-Befehle.
Verbinde dich jetzt mit deinem Server:
ssh {{username}}@{{server_ip}}Du erkennst, dass es geklappt hat, an der Eingabezeile. Sie beginnt mit deployn@ und dem Namen deines Servers.
Die wichtigsten Begriffe
Bevor wir etwas installieren, klären wir vier Wörter, die in jeder Docker-Anleitung vorkommen. Die Reihenfolge ist: Aus einem Bauplan wird eine laufende Anwendung.
| Begriff | Bedeutung |
|---|---|
| Image | Ein fertiges, unveränderliches Paket aus einem Programm und allem, was es braucht. Das Image ist der Bauplan. |
| Container | Ein laufendes Programm, das aus einem Image gestartet wurde. Aus einem Image kannst du beliebig viele Container starten. |
| Registry | Ein Lager für Images. Die bekannteste ist Docker Hub. Dort holt Docker Images ab, wenn sie noch nicht auf deinem Server liegen. |
| Dockerfile | Eine Textdatei, in der steht, wie ein Image gebaut wird. Du brauchst sie erst, wenn du eigene Images erstellst. Hier kommt sie nicht vor. |
Der Ablauf in einem Satz: Docker holt ein Image aus einer Registry und startet daraus einen Container.
Ist ein Container eine virtuelle Maschine?
Nein. Eine virtuelle Maschine bringt ein komplettes eigenes Betriebssystem mit. Ein Container teilt sich den Kern (Kernel) des Betriebssystems mit deinem Server und ist nur von den anderen Programmen abgeschottet. Stell dir ein Mehrfamilienhaus vor: Jede Wohnung hat eigene Türen und Möbel, aber alle teilen sich Fundament und Heizung. Deshalb starten Container in Sekunden und brauchen weniger Arbeitsspeicher als virtuelle Maschinen.
Docker installieren
Debian bietet Docker im eigenen Paketarchiv an, aber die Version ist dort nicht aktuell. Wir nehmen deshalb die Paketquelle, die Docker selbst pflegt. Sie besteht aus fünf kleinen Schritten.
Schritt 1: Alte Docker-Pakete entfernen
Auf einem frisch angelegten Server hast du nichts zu entfernen. Der Befehl schadet trotzdem nicht. Er entfernt nur Pakete, die mit Docker aus der offiziellen Quelle kollidieren würden:
Debian
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-doc docker-buildx podman-docker containerd runc | cut -f1)Ubuntu
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc docker-buildx podman-docker containerd runc | cut -f1)Meldungen wie dpkg: no packages found matching docker-compose bedeuten nur, dass dieses Paket nicht installiert war. Container und Images, die bereits auf dem Server liegen, bleiben erhalten.
Schritt 2: Den Schlüssel von Docker speichern
Linux prüft installierte Pakete mit einem digitalen Schlüssel, damit niemand dir veränderte Software unterschieben kann. Diesen Schlüssel holen wir uns jetzt. Wähle den Tab zu deinem System:
Debian
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.ascUbuntu
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.ascSchritt 3: Die Paketquelle eintragen
Jetzt sagst du dem System, wo es die Docker-Pakete findet. Kopiere den gesamten Block, auch die letzte Zeile EOF:
Debian
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: $(. /etc/os-release && echo "$VERSION_CODENAME")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOFUbuntu
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOFDer Befehl schreibt eine kleine Textdatei und gibt ihren Inhalt noch einmal aus. In der Zeile Suites: steht der Name deiner Version, auf Debian 13 zum Beispiel trixie, auf Ubuntu 26.04 resolute.
sudo apt updateIn der Ausgabe taucht jetzt eine Zeile mit download.docker.com auf. Dann kennt dein Server die neue Quelle.
Schritt 4: Docker installieren
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginDas sind mehrere Pakete in einem Befehl: die Docker Engine (docker-ce), das Befehlszeilenprogramm (docker-ce-cli), eine Hilfskomponente (containerd.io) und zwei Erweiterungen. Eine davon, docker-compose-plugin, brauchst du später für Docker Compose.
Debian zeigt eine Liste der Pakete und fragt Do you want to continue? [Y/n]. Mit Enter bestätigst du den Vorgang. Das große Y zeigt, dass „Ja” die Voreinstellung ist. Die Installation dauert ein bis zwei Minuten.
Schritt 5: Installation prüfen
sudo docker --version
sudo docker compose versionDocker version 29.9.3, build 5457199
Docker Compose version v5.7.0Bei dir können die Nummern höher sein. Wichtig ist, dass überhaupt Versionen erscheinen. Dass der Docker-Dienst im Hintergrund läuft und beim Start des Servers automatisch hochfährt, kannst du ebenfalls prüfen:
systemctl is-active docker
systemctl is-enabled dockeractive
enabledFalls hier etwas anderes steht, startest du den Dienst mit sudo systemctl start docker und schaltest den Autostart mit sudo systemctl enable docker ein.
Warum steht vor jedem Befehl sudo?
Docker greift tief in das System ein und braucht dafür Administratorrechte. Ohne sudo bekommst du diese Meldung:
permission denied while trying to connect to the docker API at unix:///var/run/docker.sockDu kannst deinen Benutzer in die Gruppe docker aufnehmen, dann entfällt sudo. Ich empfehle das nicht. Ein Benutzer in dieser Gruppe darf einen Container starten, der Ordner des Servers einbindet. Bindet er zum Beispiel den Ordner /etc des Servers ein, kann der Container die Datei /etc/shadow sehen, in der die Passwort-Prüfsummen stehen. Der Benutzer selbst darf sie auf dem Server nicht lesen (cat /etc/shadow meldet Permission denied).
docker run --rm -v /etc:/host alpine ls -l /host/shadow-rw-r----- 1 root shadow 634 Nov 7 06:17 /host/shadowDie Gruppe docker ist also praktisch gleichbedeutend mit Administratorrechten. Ich bleibe hier bei sudo.
Der erste Container: hello-world
Jetzt starten wir den ersten Container. Das Image hello-world ist ein winziger Test, der nur einen Text ausgibt:
sudo docker run hello-worldAuf deinem Server passiert dabei Folgendes:
- Docker sucht das Image
hello-worldauf dem Server und findet es nicht. Du siehst die MeldungUnable to find image 'hello-world:latest' locally. - Docker lädt das Image aus Docker Hub herunter (
PullingundPull complete). - Docker startet daraus einen Container. Er gibt einen Text aus, der mit
Hello from Docker!beginnt. - Der Container hat nichts weiter zu tun und beendet sich selbst.
Wenn du den Text Hello from Docker! siehst, funktioniert deine Installation. Den Container gibt es jetzt noch, nur läuft er nicht mehr. Das siehst du gleich bei der Verwaltung.
Der zweite Container: ein Webserver
Das war ein Test. Jetzt starten wir etwas, das du im Browser sehen kannst. nginx ist ein Webserver, also ein Programm, das Webseiten ausliefert.
sudo docker run nginxDocker lädt das Image nginx und startet den Container. Danach scrollen einige Zeilen durch, und die Eingabezeile kommt nicht zurück:
/docker-entrypoint.sh: Configuration complete; ready for start upDas ist gewollt. Ein Webserver hat keine Aufgabe, die irgendwann endet, er läuft weiter und wartet auf Besucher. Das Terminal zeigt dir seine Ausgabe, deshalb ist es blockiert. Mit Strg + C stoppst du den Container.
Es bleiben drei Probleme. Das Terminal ist blockiert. Du kannst den Webserver nicht im Browser erreichen, weil er von der Außenwelt abgeschottet ist. Und welche nginx-Version läuft, weißt du auch nicht. Den Befehl verbessern wir jetzt Schritt für Schritt.
Der vollständige Befehl
sudo docker run -d -p 8080:80 --name mein-webserver nginx:1.30Das sieht länger aus, besteht aber nur aus fünf Teilen:
| Teil | Bedeutung |
|---|---|
docker run |
Starte einen neuen Container. |
-d |
„Detached”: Der Container läuft im Hintergrund, das Terminal bleibt frei. |
-p 8080:80 |
Leite Anfragen an Port 8080 deines Servers an Port 80 im Container weiter. Mehr dazu gleich. |
--name mein-webserver |
Gib dem Container einen Namen. Ohne Namen vergibt Docker einen zufälligen wie musing_elbakyan. |
nginx:1.30 |
Das Image: links vom Doppelpunkt der Name, rechts der Tag. Der Tag legt die Version fest. |
Die Ausgabe ist beim ersten Mal lang, weil das Image heruntergeladen wird. Am Ende steht eine lange Zeichenfolge, die Kennung des neuen Containers.
Was bedeutet 8080:80?
Ein Rechner hat viele Ports, nummerierte Eingänge, über die Programme Anfragen entgegennehmen. Der Browser sendet Anfragen für normale Webseiten standardmäßig an Port 80 (HTTP) und 443 (HTTPS). Der nginx-Webserver im Container wartet auf Port 80. Dieser Port gilt aber nur innerhalb des Containers, von außen kommt niemand heran.
Mit -p 8080:80 baust du eine Verbindung: Was auf dem Server an Port 8080 ankommt, landet im Container an Port 80. Die Zahl links gehört dem Server, die Zahl rechts dem Container. Die rechte Zahl ist durch nginx vorgegeben. Die linke kannst du frei wählen, solange der Port noch frei ist.
Im Browser ansehen
Öffne in deinem Browser diese Adresse:
http://{{server_ip}}:8080Du siehst die Seite „Welcome to nginx!“. Du hast gerade einen Webserver gestartet, ohne ihn zu installieren.
Zur Kontrolle auf dem Server selbst:
curl -s localhost:8080 | head -n 8<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>Mehrere Webserver nebeneinander
Weil jeder Container abgeschottet ist, kannst du mehrere gleichzeitig laufen lassen, auch in verschiedenen Versionen. Starte zwei weitere:
sudo docker run -d -p 8081:80 --name mein-webserver-2 nginx:1.30
sudo docker run -d -p 8082:80 --name mein-webserver-3 nginx:1.28Jetzt laufen drei Webserver, erreichbar unter den Ports 8080, 8081 und 8082, zwei davon in Version 1.30 und einer in Version 1.28. Ohne Docker müsstest du dafür drei Installationen auseinanderhalten.
Was passiert, wenn du einen Fehler machst? Wiederhole den ersten Befehl mit einem anderen Namen, aber demselben Port:
sudo docker run -d -p 8080:80 --name zweiter nginx:1.30docker: Error response from daemon: ... Bind for 0.0.0.0:8080 failed: port is already allocatedPort 8080 ist schon vergeben. Wähle einen anderen. Und wenn du einen Namen doppelt verwendest:
docker: Error response from daemon: Conflict. The container name "/mein-webserver" is already in use by container "...". You have to remove (or rename) that container to be able to reuse that name.Jeder Name darf nur einmal vorkommen. Beachte außerdem, dass der fehlgeschlagene Start trotzdem einen Container mit dem Status Created hinterlässt. Er taucht in der Liste auf (sudo docker ps -a), und du entfernst ihn mit sudo docker rm zweiter. Wie das geht, zeige ich im nächsten Abschnitt.
Container verwalten
Ein Webserver ist erst nützlich, wenn du ihn auch wieder anhalten, ansehen und löschen kannst. Dafür brauchst du sieben Befehle.
Laufende Container anzeigen
sudo docker psCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8e360e0586c nginx:1.28 "/docker-entrypoint.…" 2 seconds ago Up 2 seconds 0.0.0.0:8082->80/tcp, [::]:8082->80/tcp mein-webserver-3
276fdfb7fef4 nginx:1.30 "/docker-entrypoint.…" 6 seconds ago Up 6 seconds 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp mein-webserver-2
758f8ae64784 nginx:1.30 "/docker-entrypoint.…" 6 seconds ago Up 6 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mein-webserverJede Zeile ist ein Container. Wichtig sind für dich vier Spalten: die ID (CONTAINER ID), das Image, der Status (Up heißt: läuft) und der Name ganz rechts. 0.0.0.0:8080->80/tcp bedeutet, dass Port 8080 des Servers auf Port 80 des Containers zeigt. Die zweite Angabe mit [::] ist dieselbe Weiterleitung für IPv6, die neuere Form der Internetadressen.
Ein Befehl mit gleicher Wirkung ist sudo docker container ls. Er ist ausführlicher, docker ps ist kürzer und verbreiteter.
Nur die IDs, ohne Tabelle, gibt dir das Flag -q („quiet”):
sudo docker ps -qWelche Flags es zu einem Befehl gibt, verrät dir --help, zum Beispiel sudo docker ps --help.
Container anhalten und wieder starten
Einen Container hältst du mit seinem Namen an:
sudo docker stop mein-webserver-3Docker gibt zur Bestätigung den Namen aus. Die Seite auf Port 8082 lädt jetzt nicht mehr. Statt des Namens kannst du auch die ID nehmen, und es genügen die ersten Zeichen, solange sie eindeutig sind, also etwa bf7.
Der Container ist nicht weg. docker ps zeigt nur laufende Container, mit -a („all”) siehst du auch die angehaltenen:
sudo docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e8e360e0586c nginx:1.28 "/docker-entrypoint.…" 2 seconds ago Exited (0) Less than a second ago mein-webserver-3
276fdfb7fef4 nginx:1.30 "/docker-entrypoint.…" 6 seconds ago Up 6 seconds 0.0.0.0:8081->80/tcp, [::]:8081->80/tcp mein-webserver-2
758f8ae64784 nginx:1.30 "/docker-entrypoint.…" 6 seconds ago Up 6 seconds 0.0.0.0:8080->80/tcp, [::]:8080->80/tcp mein-webserverAuf deinem Server stehen in dieser Liste außerdem der hello-world-Container und der erste nginx-Container mit ihren zufälligen Namen, beide mit dem Status Exited. Einen angehaltenen Container startest du wieder mit:
sudo docker start mein-webserver-3Container entfernen
Mit docker rm löschst du einen Container endgültig:
sudo docker rm mein-webserver-3Ein laufender Container lässt sich nicht löschen. Docker meldet dann cannot remove container "mein-webserver-3": container is running: stop the container before removing or force remove. Erst stop, dann rm. Dasselbe in einem Schritt macht sudo docker rm -f mein-webserver-3.
Alle angehaltenen Container entfernst du auf einmal mit:
sudo docker container pruneDocker fragt vorher nach (Are you sure you want to continue? [y/N]). Hier ist N die Voreinstellung. Du musst also y eingeben, ein bloßes Enter bricht ab.
Was beim Löschen mit den Dateien im Container passiert
Das ist die wichtigste Eigenschaft von Containern und ein häufiger Anfängerfehler. Probiere es aus. Erstelle im laufenden Container mein-webserver eine Datei:
sudo docker exec mein-webserver sh -c "echo hallo > /usr/share/nginx/html/test.html"
curl -s localhost:8080/test.htmlhallodocker exec führt einen Befehl in einem laufenden Container aus. Hier legt er eine Datei an, die nginx sofort ausliefert. Anhalten und wieder starten ändert daran nichts. Die Datei ist danach noch da. Jetzt löschen wir den Container und starten einen neuen aus demselben Image:
sudo docker stop mein-webserver
sudo docker rm mein-webserver
sudo docker run -d -p 8080:80 --name mein-webserver nginx:1.30
curl -s -o /dev/null -w "%{http_code}\n" localhost:8080/test.html404Der Statuscode 404 heißt „nicht gefunden”. Die Datei ist weg. Ein Container ist wie ein Wegwerfprodukt, das jederzeit aus dem Image neu entsteht. Alles, was du in ihm veränderst, geht beim Entfernen verloren. Programme, die Daten behalten sollen, wie Datenbanken oder Fotosammlungen, legen diese deshalb außerhalb des Containers ab. Dafür gibt es Volumes und Bind-Mounts, ein eigenes Thema.
Logs ansehen
Wenn etwas nicht funktioniert, schaust du zuerst in die Logs. Das sind die Meldungen, die ein Programm über seine Arbeit schreibt:
sudo docker logs --tail 2 mein-webserver2026/11/07 06:25:27 [error] 30#30: *1 open() "/usr/share/nginx/html/test.html" failed (2: No such file or directory), client: 172.17.0.1, server: localhost, request: "GET /test.html HTTP/1.1", host: "localhost:8080"
172.17.0.1 - - [07/Nov/2026:06:25:27 +0000] "GET /test.html HTTP/1.1" 404 153 "-" "curl/8.14.1" "-"Du siehst, dass der Aufruf von /test.html mit 404 beantwortet wurde, und den Grund dazu: No such file or directory. --tail 2 zeigt nur die letzten zwei Zeilen. Mit -f („follow”) bleibt das Terminal offen und zeigt neue Einträge laufend an. Beenden kannst du das mit Strg + C.
In einen Container hineinschauen
Mit exec und einer Shell öffnest du ein Terminal im Container:
sudo docker exec -it mein-webserver bash-i hält die Eingabe offen, -t sorgt für ein ordentliches Terminal. Die Eingabezeile ändert sich:
root@06fa4833f3b5:/#Du bist jetzt im Container. Der Name nach dem @ ist die Container-ID. Hier kannst du ls /usr/share/nginx/html ausführen und siehst 50x.html und index.html. Mit exit kehrst du zum Server zurück.
Manche Images haben keine Shell namens bash. Dann kommt exec: "bash": executable file not found in $PATH, und du versuchst es mit sh. Das trifft besonders schlanke Images, wie du im nächsten Abschnitt siehst.
Images und Tags
Beim Start hat Docker das Image heruntergeladen und gespeichert. Diese Liste zeigt dir, was auf deinem Server liegt:
sudo docker image lsIMAGE ID DISK USAGE CONTENT SIZE EXTRA
nginx:1.28 fda7399e8104 161MB 0B U
nginx:1.30 53d8f012a1a7 163MB 0B UDer Teil vor dem Doppelpunkt ist der Name, der Teil danach der Tag. Der Tag legt fest, welche Version du bekommst. Das U in der letzten Spalte bedeutet, dass ein Container dieses Image gerade nutzt.
Zwei Images mit demselben Namen, aber unterschiedlichem Tag sind verschiedene Images. Die Image-ID unterscheidet sie. Bei Docker ist gleiche ID gleicher Inhalt: Hätten zwei Tags dieselbe ID, belegen sie den Speicherplatz nur einmal.
Warum du latest vermeiden solltest
Lässt du den Tag weg, ergänzt Docker latest. sudo docker run nginx ist also dasselbe wie sudo docker run nginx:latest. Der Name klingt nach „die neueste Version”, ist aber nur ein Tag wie jeder andere. Der Entwickler des Images entscheidet, worauf er zeigt, und kann ihn jederzeit auf eine neue Version umstellen.
Zum Zeitpunkt dieses Beitrags zeigte nginx:latest auf nginx 1.31.8, während nginx:1.30 genau die Version 1.30 lieferte. Wer latest benutzt und seinen Container neu erstellt, bekommt irgendwann eine andere Version als zuvor, zum Beispiel mit anderen Einstellungen. Deshalb gebe ich bei jedem Projekt einen festen Tag an. Dann weiß ich, was läuft.
Versionsnummern lesen
Die meisten Programme nummerieren ihre Versionen nach dem Muster Haupt.Neben.Patch, also etwa 1.30.2. Das nennt sich semantische Versionierung. Es hilft dir beim Abschätzen, wie riskant ein Update ist:
| Ändert sich | Beispiel | Bedeutung |
|---|---|---|
| Die letzte Zahl | 1.30.1 → 1.30.2 |
Fehlerbehebung. Das Update ist in der Regel unproblematisch. |
| Die mittlere Zahl | 1.30.2 → 1.31.0 |
Neue Funktionen, die alte weiterhin unterstützen sollten. |
| Die erste Zahl | 1.31.0 → 2.0.0 |
Große Änderung. Vorhandene Einstellungen können danach nicht mehr funktionieren. |
Bei Docker-Images kann ein Tag grob oder fein sein. nginx:1.30 hält dich auf der Version 1.30 und lädt Fehlerbehebungen nach. nginx:1 macht innerhalb von Version 1 auch größere Sprünge mit. Zum Zeitpunkt meines Tests lieferte dieser Tag nginx 1.31.8. Welche Tags es gibt und was sie bedeuten, entscheidet jedes Projekt selbst. Eine Übersicht findest du im Reiter „Tags” des Images auf Docker Hub.
Der Tag alpine
Auf Docker Hub gibt es viele Images mit einem Zusatz im Tag, etwa nginx:1.30-alpine. Alpine ist ein Linux, das auf geringe Größe getrimmt ist. Lade das Image herunter und vergleiche:
sudo docker pull nginx:1.30-alpine
sudo docker image ls nginxIMAGE ID DISK USAGE CONTENT SIZE EXTRA
nginx:1.28 fda7399e8104 161MB 0B U
nginx:1.30 53d8f012a1a7 163MB 0B U
nginx:1.30-alpine 1390db6b01a8 62.4MB 0BDie Alpine-Variante belegt nur etwa ein Drittel (62,4 MB gegenüber 163 MB). Kleinere Images sind schneller heruntergeladen, brauchen weniger Platz und enthalten weniger Programme, die Sicherheitslücken haben könnten. Der Preis ist, dass manches fehlt. Starte einen Container aus dem Alpine-Image und versuche, hineinzuschauen:
sudo docker run -d --name alp nginx:1.30-alpine
sudo docker exec alp bashOCI runtime exec failed: exec failed: unable to start container process: exec: "bash": executable file not found in $PATHDas Image hat kein bash. Mit sh klappt es:
sudo docker exec -it alp shEntferne diesen Testcontainer danach mit sudo docker rm -f alp.
Images löschen
Ein Image löschst du mit docker image rm. Solange ein Container es verwendet, verweigert Docker das:
Error response from daemon: conflict: unable to remove repository reference "nginx:1.30-alpine" (must force) - container 6bf29c9edd00 is using its referenced image 1390db6b01a8Entferne zuerst den Container, dann geht es:
sudo docker rm -f alp
sudo docker image rm nginx:1.30-alpineAufräumen
Zum Schluss räumen wir alles weg, was wir in diesem Beitrag gestartet haben. Wie viel Platz Docker auf deinem Server belegt, zeigt dir:
sudo docker system dfTYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 2 2 323.4MB 0B (0%)
Containers 3 3 3.285kB 0B (0%)
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0BEntferne die Container, und danach alle Images, die kein Container mehr benutzt:
sudo docker rm -f mein-webserver mein-webserver-2 mein-webserver-3
sudo docker image prune -aimage prune -a fragt nach (y/N) und löscht dann jedes Image ohne Container. Das ist praktisch zum Aufräumen. Auf einem Server mit laufenden Anwendungen schaust du vorher kurz nach, ob sie alle laufen, sonst werden Images gelöscht, die du später wieder herunterladen musst.
Docker aktualisieren
Du musst Docker für ein Update nicht deinstallieren. Docker kommt aus einer Paketquelle, und die aktualisierst du wie alles andere auf Debian:
sudo apt update
sudo apt install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginAlternativ aktualisiert sudo apt upgrade das ganze System und damit auch Docker.
Aktualisiert Docker sich, startet der Docker-Dienst neu, und die Container werden dabei gestoppt. Container, die du mit --restart unless-stopped gestartet hast, fahren von selbst wieder hoch. Alle anderen bleiben auf Exited stehen, bis du sie mit docker start startest. Nach einem Neustart des Docker-Dienstes (sudo systemctl restart docker) stehen Container ohne diese Einstellung auf Exited. Plane Updates deshalb nicht in einem Moment ein, in dem jemand deinen Dienst nutzt. Die Daten selbst liegen in /var/lib/docker und bleiben unberührt. Wenn dir deine Daten wichtig sind, sicherst du sie vorher trotzdem. Den Ordner /var/lib/docker zeigt dir sudo docker info, er heißt dort „Docker Root Dir”.
Das Docker-Update ersetzt nicht die Images deiner Container. Ein Container läuft weiter mit dem Image, aus dem er gestartet wurde. Für eine neuere Version eines Programms holst du das neue Image (sudo docker pull nginx:1.30 lädt Fehlerbehebungen nach, falls es welche gibt) und erstellst den Container neu. Mit Docker Compose geht das mit zwei Befehlen.
Häufige Fehler
| Meldung | Ursache und Lösung |
|---|---|
docker: command not found |
Docker ist nicht installiert, oder es wurde docker.io installiert. Folge den Schritten oben. |
permission denied while trying to connect to the docker API |
Du hast sudo vergessen. |
port is already allocated |
Der Port links von : wird bereits benutzt. Wähle einen anderen oder entferne den Container, der ihn belegt. |
The container name ... is already in use |
Der Name ist vergeben. Wähle einen anderen oder entferne den alten Container mit docker rm. |
cannot remove container ...: container is running |
Erst docker stop, dann docker rm, oder docker rm -f. |
exec: "bash": executable file not found in $PATH |
Das Image hat kein bash. Verwende sh. |
| Die Seite im Browser lädt nicht | Mit sudo docker ps prüfen, ob der Container läuft und welcher Port eingetragen ist. Dann sudo docker logs. |
Fazit
Mit sechs Befehlen kommst du schon weit: docker run startet einen Container, docker ps zeigt, was läuft, docker logs verrät, was schiefgeht, docker stop und docker rm halten ihn an und entfernen ihn, und docker image ls zeigt die heruntergeladenen Images. Entscheidend sind drei Gedanken: Aus einem Image entstehen Container, Dateien im Container verschwinden mit ihm, und feste Tags statt latest halten deine Installation reproduzierbar.
Langfristig willst du solche Befehle nicht mehr jedes Mal von Hand tippen. Dafür gibt es Docker Compose: Du schreibst alle Einstellungen einmal in eine Datei. Du siehst Compose in meinen Anleitungen zu Uptime Kuma oder Vaultwarden im Einsatz.
Bei welchem Schritt hast du am längsten gebraucht? Schreib es gerne in die Kommentare, dann ergänze ich die Stelle.
FAQ
Häufige Fragen
Was ist der Unterschied zwischen einem Image und einem Container?
Ein Image ist die Vorlage: ein fertiges Paket aus Programm und Zubehör, das sich nicht verändert. Ein Container ist ein laufendes Programm, das aus dem Image gestartet wurde. Aus einem Image lassen sich beliebig viele Container starten.
Ist ein Docker-Container eine virtuelle Maschine?
Nein. Eine virtuelle Maschine bringt ein komplettes Betriebssystem mit. Ein Container teilt sich den Kernel mit dem Server und ist nur von anderen Programmen abgeschottet. Deshalb startet er schneller und braucht weniger Arbeitsspeicher.
Warum installiere ich Docker nicht mit apt install docker.io?
Das Debian-Paket docker.io liegt mehrere Hauptversionen hinter der aktuellen zurück. Auf Debian 13 ist es Version 26.1.5, die offizielle Version ist 29.9.3.
Wie aktualisiere ich Docker, ohne Daten zu verlieren?
Mit sudo apt update und sudo apt install --only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin. Deinstallieren ist nicht nötig. Container und Volumes bleiben erhalten, die Container werden beim Update aber kurz neu gestartet.
Ist Docker Desktop kostenlos?
Für Privatpersonen, Bildung, Open-Source-Projekte und kleine Unternehmen ja. Die Grenze liegt laut Docker bei weniger als 250 Mitarbeitern und weniger als 10 Millionen US-Dollar Jahresumsatz. Die Docker Engine, die du auf einem Linux-Server installierst, ist davon nicht betroffen.
Warum läuft mein Container nicht, obwohl der Befehl keinen Fehler zeigt?
Schau mit sudo docker ps -a nach dem Status und mit sudo docker logs NAME nach der Ursache. Steht der Container auf Exited, ist das Programm im Container beendet. Der Grund steht in den Logs.
Muss ich bei Rückfragen immer y eintippen?
Nicht bei apt. Bei der Rückfrage [Y/n] ist Ja voreingestellt (großes Y), ein Enter genügt. Bei docker container prune oder docker image prune -a steht [y/N]: Dort ist Nein voreingestellt, du musst y eingeben.