Docker unter Linux installieren und nutzen – Schritt für Schritt (2026)
Docker hat die Art, wie Software entwickelt, getestet und betrieben wird, grundlegend verändert. Statt Software direkt auf dem Host-System zu installieren, läuft sie in isolierten Containern – reproduzierbar, portierbar und sauber.
Dieser Guide führt dich von der Installation bis zum ersten funktionierenden Container und zeigt dir die wichtigsten Konzepte und Befehle.
Was ist Docker? – Die Kernkonzepte
Bevor wir Befehle eingeben, kurz die wichtigsten Begriffe – einmal verstanden, macht Docker Sinn:
Container vs. Virtuelle Maschine
| Virtuelle Maschine | Docker Container | |
|---|---|---|
| Isolierung | vollständiges OS | Prozess-Isolierung |
| Startzeit | Minuten | Sekunden/Millisekunden |
| Ressourcen | GB RAM/Speicher | MB |
| Portierbarkeit | mittel | sehr hoch |
| Overhead | hoch | gering |
Container teilen sich den Kernel des Host-Systems, sind aber voneinander isoliert. Das macht sie leichtgewichtiger als VMs.
Die vier Kernkonzepte
Image
Ein Image ist eine unveränderliche Vorlage – der Bauplan für einen Container. Images sind schreibgeschützt und können mit docker pull aus Registries (z.B. Docker Hub) heruntergeladen werden.
nginx:alpine → nginx Webserver auf Alpine Linux
postgres:16 → PostgreSQL Datenbank Version 16
python:3.12-slim → Python 3.12, minimale Variante
Container Ein Container ist eine laufende Instanz eines Images. Du kannst viele Container aus demselben Image starten.
Volume Volumes sind persistente Datenspeicher. Container sind von Natur aus vergänglich – stirbt ein Container, gehen seine Daten verloren. Volumes überleben das.
Network Docker-Netzwerke ermöglichen die Kommunikation zwischen Containern. Im Custom-Bridge-Netzwerk können Container sich per Name ansprechen.
Docker CE installieren – Ubuntu & Debian
Hinweis: Installiere Docker nie aus dem Standard-Repository deiner Distro (
apt install docker.io). Die Pakete sind oft veraltet. Nutze das offizielle Docker-Repository.
Ubuntu 24.04 LTS
# 1. Abhängigkeiten und GPG-Key
sudo apt update
sudo apt install -y ca-certificates curl gnupg
# 2. Docker GPG-Schlüssel hinzufügen
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# 3. Docker-Repository hinzufügen
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 4. Docker CE installieren
sudo apt update
sudo apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
Debian 13 Trixie
# 1. Abhängigkeiten
sudo apt update
sudo apt install -y ca-certificates curl gnupg
# 2. GPG-Schlüssel
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg
# 3. Repository
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 4. Installation
sudo apt update
sudo apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
Docker testen und einrichten
Dienst starten und aktivieren
# Docker-Dienst starten und beim Systemstart automatisch starten
sudo systemctl enable --now docker
# Status prüfen
sudo systemctl status docker
# Version überprüfen
sudo docker version
Hello World – erster Test
sudo docker run hello-world
Wenn du Hello from Docker! siehst, funktioniert Docker korrekt.
Docker ohne sudo nutzen (optional, aber empfohlen)
Standardmäßig benötigt Docker sudo. Du kannst deinen Benutzer zur docker-Gruppe hinzufügen:
sudo usermod -aG docker "$USER"
Sicherheitshinweis: Mitglieder der
docker-Gruppe haben faktisch Root-ähnliche Rechte. Füge nur vertrauenswürdige Nutzer hinzu.
Damit die Änderung wirksam wird:
# Option 1: Neue Gruppe für aktuelle Session aktivieren
newgrp docker
# Option 2: Aus- und wieder einloggen
Test ohne sudo:
docker ps
Erste Schritte: Container starten
docker run – der wichtigste Befehl
# Basis-Syntax
docker run [Optionen] Image [Befehl]
# Nginx-Webserver starten
docker run -d --name web -p 8080:80 nginx:alpine
Optionen erklärt:
-d– Detached: Container läuft im Hintergrund--name web– gibt dem Container den Namen "web"-p 8080:80– Port-Mapping: Port 8080 am Host → Port 80 im Containernginx:alpine– Image: nginx, Tag: alpine (klein und leicht)
Teste es im Browser: http://localhost:8080
Container verwalten
# Laufende Container anzeigen
docker ps
# Alle Container (auch gestoppte)
docker ps -a
# Container stoppen
docker stop web
# Container wieder starten
docker start web
# Container (und alle Ausgaben) permanent löschen
docker rm web
# Stoppen und direkt löschen (praktisch in einem Schritt)
docker rm -f web
# Logs anzeigen
docker logs web
# Logs live verfolgen
docker logs -f web
# In einen laufenden Container „einsteigen"
docker exec -it web sh # Alpine/BusyBox: sh
docker exec -it web bash # Debian-basiert: bash
Interaktiver Container (mit --rm)
Für schnelle Experimente, die nach dem Beenden des Containers automatisch gelöscht werden:
# Alpine-Container interaktiv starten, beim Beenden löschen
docker run -it --rm alpine sh
# Debian-Container mit aktuellen Dateien aus dem Host-Verzeichnis
docker run -it --rm -v "$PWD":/work -w /work debian:12 bash
Ressourcen begrenzen
# Maximaler RAM: 512 MB, maximale CPUs: 1
docker run -d \
--name web \
--memory 512m \
--cpus 1 \
-p 8080:80 \
nginx:alpine
Images verwalten
# Image herunterladen (ohne Container zu starten)
docker pull nginx:alpine
docker pull postgres:16
docker pull python:3.12-slim
# Alle lokalen Images anzeigen
docker images
# Image-Details
docker inspect nginx:alpine
# Image löschen
docker rmi nginx:alpine
# Nicht verwendete (dangling) Images löschen
docker image prune
# Alle nicht genutzten Images löschen
docker image prune -a
Tags verstehen
Images haben Tags, die Versionen bezeichnen:
nginx → entspricht nginx:latest (nicht empfohlen für Produktion!)
nginx:alpine → nginx auf Alpine Linux (klein)
nginx:1.27 → spezifische nginx-Version (empfohlen für Reproduzierbarkeit)
postgres:16 → PostgreSQL 16
postgres:16-alpine → PostgreSQL 16 auf Alpine
Best Practice: Nutze in Produktion immer konkrete Tags wie
nginx:1.27-alpinestatt:latest. So vermeidest du ungewollte Updates.
Eigenes Image bauen (Dockerfile)
# Dockerfile Beispiel für eine Python-App
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
# Nicht als root laufen
RUN useradd -m appuser
USER appuser
EXPOSE 8000
CMD ["python", "app.py"]
# Image bauen
docker build -t meine-app:1.0 .
# Mit anderem Dockerfile
docker build -f Dockerfile.prod -t meine-app:prod .
Volumes: Daten persistent speichern
Ohne Volumes gehen alle Daten eines Containers beim Löschen verloren.
Named Volumes (empfohlen für Produktion)
# Volume erstellen
docker volume create dbdata
# Volume auflisten
docker volume ls
# Volume Details
docker volume inspect dbdata
# Container mit Volume starten
docker run -d \
--name db \
-v dbdata:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=sicherespasswort \
postgres:16
# Volume löschen (nur wenn kein Container es nutzt)
docker volume rm dbdata
# Alle ungenutzten Volumes löschen (VORSICHT: Datenverlust möglich!)
docker volume prune
Bind Mounts (für Entwicklung)
Bind Mounts verbinden ein Verzeichnis auf dem Host direkt mit einem Container:
# Aktuelles Verzeichnis im Container einbinden
docker run -d \
--name web \
-v "$PWD/html":/usr/share/nginx/html:ro \
-p 8080:80 \
nginx:alpine
# :ro = read-only – Container kann nicht schreiben
Wann welche Methode?
| Named Volume | Bind Mount | |
|---|---|---|
| Produktion | ✅ | ⚠️ |
| Entwicklung | ⚠️ | ✅ |
| Performance | gut | variiert |
| Portierbarkeit | hoch | niedrig |
Daten kopieren
# Datei vom Container auf den Host kopieren
docker cp web:/etc/nginx/nginx.conf ./nginx.conf
# Datei vom Host in den Container kopieren
docker cp ./nginx.conf web:/etc/nginx/nginx.conf
Netzwerke: Container kommunizieren lassen
Das Default-Netzwerk und warum Custom besser ist
Neu gestartete Container landen im bridge-Netzwerk – dort können sie sich aber nicht per Namen ansprechen, nur per IP. Das ist unpraktisch.
Custom Bridge Network: Hier löst Docker automatisch Container-Namen zu IPs auf.
# Eigenes Netzwerk erstellen
docker network create appnet
# Netzwerke anzeigen
docker network ls
# Container im Netzwerk starten
docker run -d --name api --network appnet meine-api:latest
docker run -d --name web --network appnet -p 8080:80 nginx:alpine
# Jetzt kann "web" den Container "api" direkt per Name ansprechen:
# http://api:PORT
# Netzwerk inspizieren (zeigt verbundene Container)
docker network inspect appnet
# Container nachträglich mit Netzwerk verbinden
docker network connect appnet mein-container
# Verbindung trennen
docker network disconnect appnet mein-container
Docker Compose: Multi-Container-Setups
Für Anwendungen mit mehreren Services (z.B. Web-App + Datenbank + Cache) ist Docker Compose unerlässlich.
Hinweis: Seit Docker Desktop und neueren Docker CE Versionen ist Compose als Plugin integriert. Statt
docker-compose(alt, v1) nutzt dudocker compose(neu, v2).
# Prüfen ob Compose v2 verfügbar ist
docker compose version
# Docker Compose version v2.x.x
Beispiel: WordPress mit MySQL
Erstelle eine Datei compose.yaml (empfohlener Dateiname, docker-compose.yml wird noch unterstützt):
services:
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: rootpasswort
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: wppasswort
volumes:
- dbdata:/var/lib/mysql
networks:
- wpnet
wordpress:
image: wordpress:latest
restart: unless-stopped
depends_on:
- db
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: wppasswort
WORDPRESS_DB_NAME: wordpress
volumes:
- wpdata:/var/www/html
networks:
- wpnet
volumes:
dbdata:
wpdata:
networks:
wpnet:
# Alle Services starten (im Hintergrund)
docker compose up -d
# Status prüfen
docker compose ps
# Logs anzeigen
docker compose logs -f
# Nur WordPress-Logs
docker compose logs -f wordpress
# In einen Service einsteigen
docker compose exec wordpress bash
# Neustart eines Services
docker compose restart wordpress
# Alle Services stoppen (Volumes bleiben erhalten)
docker compose down
# Alles stoppen UND Volumes löschen (VORSICHT: Datenverlust!)
docker compose down -v
Compose mit Build (eigenes Image)
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- "3000:3000"
volumes:
- .:/app # Code live einbinden (Entwicklung)
environment:
- NODE_ENV=development
# Image bauen und starten
docker compose up -d --build
# Nur neu bauen ohne zu starten
docker compose build
Häufige Probleme und Lösungen
Permission denied beim Docker-Befehl
permission denied while trying to connect to the Docker daemon socket
Ursache: Dein Benutzer ist nicht in der docker-Gruppe.
sudo usermod -aG docker "$USER"
newgrp docker
# oder: aus- und wieder einloggen
Prüfen:
groups $USER # Zeigt alle Gruppen des Benutzers
ls -l /var/run/docker.sock
Port bereits belegt
Error: Bind for 0.0.0.0:8080 failed: port is already allocated
Ursache: Ein anderer Prozess oder Container nutzt Port 8080.
# Welcher Prozess nutzt den Port?
sudo ss -ltnp | grep ':8080'
# Anderen Port wählen
docker run -d -p 8081:80 nginx:alpine
Container startet und stoppt sofort
# Logs ansehen – hier steht der Grund
docker logs <container-name>
# Exit-Code prüfen
docker inspect -f '{{.State.ExitCode}}' <container-name>
# Interaktiv debuggen (Entrypoint überschreiben)
docker run -it --rm --entrypoint sh <image>
Häufige Exit-Codes:
1– Allgemeiner Fehler (falsche Konfiguration, fehlende Datei)125– Docker-Fehler selbst126– Befehl nicht ausführbar127– Befehl nicht gefunden137– Container per SIGKILL beendet (OOM-Kill = zu wenig RAM)
Kein Speicherplatz mehr
no space left on device
# Docker-Speicherverbrauch anzeigen
docker system df
# Aufräumen (nicht genutzte Container, Netzwerke, Images)
docker system prune
# Auch Build-Cache löschen
docker system prune --all
# Inkl. Volumes (VORSICHT: Datenverlust!)
docker system prune --volumes
DNS-Probleme im Container
# DNS-Konfiguration im Container prüfen
docker exec -it <container> cat /etc/resolv.conf
# Netzwerkverbindung im Container testen
docker exec -it <container> sh -c "ping -c 1 1.1.1.1"
# Custom DNS beim Start angeben
docker run --dns 1.1.1.1 ...
Rollback: Docker komplett entfernen
Falls du Docker wieder entfernen möchtest:
Pakete deinstallieren
sudo apt purge -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
sudo apt autoremove -y
Docker-Daten entfernen (optional – VORSICHT: löscht alle Images, Container, Volumes!)
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
Repository-Konfiguration entfernen
sudo rm -f /etc/apt/sources.list.d/docker.list
sudo rm -f /etc/apt/keyrings/docker.gpg
sudo apt update
Fazit
Docker verändert, wie du mit Software arbeitest. Statt stundenlanger Installationsprozesse hast du in Sekunden eine PostgreSQL-Datenbank, einen Nginx-Server oder eine komplette Web-Applikation am Laufen – sauber isoliert vom Rest des Systems.
Deine nächsten Schritte:
- Starte ein paar Container aus dem Hub (
nginx,postgres,redis) - Probiere Docker Compose mit einem Multi-Container-Setup
- Schreibe dein erstes
Dockerfile
Weiterführende Ressourcen auf RootForge:
- Docker Cheatsheet (Debian 13) – alle Befehle kompakt
- SSH-Schlüssel erstellen und sicher verwenden
- Linux Terminal Grundlagen