Skip to Content
DokumentationServerDocker Verfassen

Docker Verfassen

Docker Compose ist ein Tool zum Definieren und Ausführen von Multi-Container-Anwendungen. Mit einer einzigen YAML-Datei, die alle Dienste beschreibt, können Sie einen gesamten Anwendungsstapel mit einem Befehl starten.

Installieren von Docker und Docker Compose

Installieren der Docker-Engine

# Remove old versions sudo apt remove docker docker-engine docker.io containerd runc 2>/dev/null # Install dependencies sudo apt update sudo apt install ca-certificates curl gnupg -y # Add Docker's official GPG key 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 # Add the repository 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 # Install Docker Engine (includes Compose plugin) sudo apt update sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y # Add current user to the docker group (no sudo needed) sudo usermod -aG docker $USER newgrp docker # Verify installation docker --version docker compose version

Verwendung von Spiegelregistern für schnellere Pulls

sudo tee /etc/docker/daemon.json << 'EOF' { "registry-mirrors": [ "https://mirror.ccs.tencentyun.com", "https://docker.mirrors.ustc.edu.cn" ] } EOF sudo systemctl restart docker

docker-compose.yml Grundlagen

Dateistruktur

# docker-compose.yml # Modern Docker Compose no longer needs the version field (it is deprecated) services: web: image: nginx:latest ports: - "80:80" volumes: - ./html:/usr/share/nginx/html:ro restart: unless-stopped app: build: ./app environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb depends_on: - db db: image: postgres:16 volumes: - db-data:/var/lib/postgresql/data environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: mydb volumes: db-data: networks: default: driver: bridge

Allgemeine Konfigurationsoptionen

services: myservice: # Image image: ubuntu:26.04 # Or build from Dockerfile build: context: ./app dockerfile: Dockerfile args: VERSION: "1.0" # Container name container_name: my-app # Port mapping (host:container) ports: - "8080:80" - "127.0.0.1:3000:3000" # Local access only # Volumes volumes: - ./data:/app/data # Bind mount - app-data:/app/storage # Named volume - /etc/localtime:/etc/localtime:ro # Sync timezone # Environment variables environment: - NODE_ENV=production - SECRET_KEY=mysecret # Or load from file env_file: - .env # Restart policy restart: unless-stopped # always | on-failure | no # Dependencies depends_on: db: condition: service_healthy # Health check healthcheck: test: ["CMD", "curl", "-f", "http://localhost:80"] interval: 30s timeout: 10s retries: 3 start_period: 40s # Resource limits deploy: resources: limits: cpus: '0.50' memory: 512M reservations: cpus: '0.25' memory: 256M # Networks networks: - frontend - backend # Logging configuration logging: driver: json-file options: max-size: "10m" max-file: "3"

Allgemeine Befehle

# Start all services (detached mode) docker compose up -d # View running status docker compose ps # View logs docker compose logs docker compose logs -f web # Follow logs for a specific service docker compose logs --tail=100 # Last 100 lines # Stop all services docker compose down # Stop and remove volumes docker compose down -v # Rebuild images docker compose build docker compose up -d --build # Enter a container docker compose exec web bash # Run a one-off command docker compose run --rm app python manage.py migrate # Scale services docker compose up -d --scale web=3 # View resource usage docker compose top docker stats

Gängige Tech-Stack-Beispiele

LEMP-Stack (Nginx + PHP + MySQL)

# docker-compose.yml services: nginx: image: nginx:alpine ports: - "80:80" volumes: - ./src:/var/www/html - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - php restart: unless-stopped php: image: php:8.3-fpm volumes: - ./src:/var/www/html restart: unless-stopped mysql: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: rootpass MYSQL_DATABASE: myapp MYSQL_USER: appuser MYSQL_PASSWORD: apppass volumes: - mysql-data:/var/lib/mysql restart: unless-stopped phpmyadmin: image: phpmyadmin:latest ports: - "8080:80" environment: PMA_HOST: mysql depends_on: - mysql restart: unless-stopped volumes: mysql-data:

WordPress

services: wordpress: image: wordpress:latest ports: - "80:80" environment: WORDPRESS_DB_HOST: db WORDPRESS_DB_USER: wordpress WORDPRESS_DB_PASSWORD: wordpress_pass WORDPRESS_DB_NAME: wordpress volumes: - wp-content:/var/www/html depends_on: db: condition: service_healthy restart: unless-stopped db: image: mariadb:11 environment: MARIADB_ROOT_PASSWORD: root_pass MARIADB_DATABASE: wordpress MARIADB_USER: wordpress MARIADB_PASSWORD: wordpress_pass volumes: - db-data:/var/lib/mysql healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 10s timeout: 5s retries: 5 restart: unless-stopped volumes: wp-content: db-data:

Gitea + PostgreSQL

services: gitea: image: gitea/gitea:latest ports: - "3000:3000" - "2222:22" environment: - GITEA__database__DB_TYPE=postgres - GITEA__database__HOST=db:5432 - GITEA__database__NAME=gitea - GITEA__database__USER=gitea - GITEA__database__PASSWD=gitea_pass volumes: - gitea-data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro depends_on: - db restart: unless-stopped db: image: postgres:16-alpine environment: POSTGRES_USER: gitea POSTGRES_PASSWORD: gitea_pass POSTGRES_DB: gitea volumes: - postgres-data:/var/lib/postgresql/data restart: unless-stopped volumes: gitea-data: postgres-data:

Überwachungsstapel (Prometheus + Grafana)

services: prometheus: image: prom/prometheus:latest ports: - "9090:9090" volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus command: - '--config.file=/etc/prometheus/prometheus.yml' - '--storage.tsdb.retention.time=30d' restart: unless-stopped grafana: image: grafana/grafana:latest ports: - "3000:3000" environment: - GF_SECURITY_ADMIN_USER=admin - GF_SECURITY_ADMIN_PASSWORD=admin_pass volumes: - grafana-data:/var/lib/grafana depends_on: - prometheus restart: unless-stopped node-exporter: image: prom/node-exporter:latest ports: - "9100:9100" volumes: - /proc:/host/proc:ro - /sys:/host/sys:ro - /:/rootfs:ro command: - '--path.procfs=/host/proc' - '--path.sysfs=/host/sys' - '--path.rootfs=/rootfs' restart: unless-stopped volumes: prometheus-data: grafana-data:

Verwenden von .env-Dateien

# .env file (in the same directory as docker-compose.yml) MYSQL_ROOT_PASSWORD=secretpass MYSQL_DATABASE=myapp APP_PORT=8080
# Reference in docker-compose.yml services: db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_DATABASE: ${MYSQL_DATABASE} app: ports: - "${APP_PORT}:80"

Netzwerkkonfiguration

services: frontend: networks: - front-tier backend: networks: - front-tier - back-tier db: networks: - back-tier networks: front-tier: driver: bridge back-tier: driver: bridge internal: true # Isolated network, no external access

Datensicherung und -wiederherstellung

# Back up a volume docker run --rm -v myproject_db-data:/data -v $(pwd):/backup ubuntu \ tar czf /backup/db-backup-$(date +%Y%m%d).tar.gz -C /data . # Restore a volume docker run --rm -v myproject_db-data:/data -v $(pwd):/backup ubuntu \ bash -c "cd /data && tar xzf /backup/db-backup-20260324.tar.gz" # Database export (MySQL example) docker compose exec db mysqldump -u root -p myapp > backup.sql # Database import docker compose exec -T db mysql -u root -p myapp < backup.sql

Best Practices

  1. Pin-Versionen: Verwenden Sie feste Versions-Tags in der Produktion (z. B. nginx:1.27); Vermeiden Sie latest
  2. Separate Umgebungsvariablen: Bewahren Sie vertrauliche Informationen in .env-Dateien auf und fügen Sie sie zu .gitignore hinzu
  3. Gesundheitsprüfungen: Konfigurieren Sie healthcheck für kritische Dienste, um sicherzustellen, dass Abhängigkeiten bereit sind
  4. Protokolllimits: Konfigurieren Sie die Protokollrotation, um eine Erschöpfung des Speicherplatzes zu verhindern
  5. Ressourcenlimits: Verwenden Sie deploy.resources, um CPU und Arbeitsspeicher zu begrenzen
  6. Schreibgeschützte Bereitstellungen: Verwenden Sie :ro für die schreibgeschützte Bereitstellung von Konfigurationsdateien
  7. Benannte Volumes: Verwenden Sie benannte Volumes anstelle von Bind-Mounts für persistente Daten
  8. Netzwerkisolation: Verwenden Sie internal-Netzwerke für Datenbanken und andere Dienste. Geben Sie Ports nicht unnötig frei
Last updated on