services: # ============================================ # NEXTCLOUD - Cloud Storage # ============================================ nextcloud: image: nextcloud:latest container_name: nextcloud restart: unless-stopped security_opt: - apparmor=unconfined - seccomp=unconfined ports: - "8081:80" volumes: - /opt/docker/nextcloud/data:/var/www/html environment: - MYSQL_HOST=nextcloud-db - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD} depends_on: nextcloud-db: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost/status.php"] interval: 30s timeout: 10s retries: 3 start_period: 60s deploy: resources: limits: cpus: '2.0' memory: 2G logging: driver: "json-file" options: max-size: "10m" max-file: "3" networks: - nextcloud-net nextcloud-db: image: mariadb:10 container_name: nextcloud-db restart: unless-stopped security_opt: - apparmor=unconfined - seccomp=unconfined volumes: - /opt/docker/nextcloud/db:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=${NEXTCLOUD_DB_ROOT_PASSWORD} - MYSQL_DATABASE=nextcloud - MYSQL_USER=nextcloud - MYSQL_PASSWORD=${NEXTCLOUD_DB_PASSWORD} healthcheck: test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] interval: 30s timeout: 10s retries: 3 start_period: 30s deploy: resources: limits: cpus: '1.0' memory: 1G logging: driver: "json-file" options: max-size: "10m" max-file: "3" networks: - nextcloud-net # ============================================ # VAULTWARDEN - Password Manager # ============================================ vaultwarden: image: vaultwarden/server:latest container_name: vaultwarden restart: unless-stopped security_opt: - apparmor=unconfined - seccomp=unconfined ports: - "8083:80" volumes: - /opt/docker/vaultwarden:/data environment: - ADMIN_TOKEN=${VAULTWARDEN_ADMIN_TOKEN} - SIGNUPS_ALLOWED=false - INVITATIONS_ALLOWED=true - SHOW_PASSWORD_HINT=false healthcheck: test: ["CMD", "curl", "-f", "http://localhost/alive"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: cpus: '0.5' memory: 256M logging: driver: "json-file" options: max-size: "10m" max-file: "3" networks: - vaultwarden-net # ============================================ # N8N - Workflow Automation # ============================================ n8n: image: n8nio/n8n:latest container_name: n8n restart: unless-stopped security_opt: - apparmor=unconfined - seccomp=unconfined ports: - "5678:5678" volumes: - /opt/docker/n8n:/home/node/.n8n environment: - N8N_BASIC_AUTH_ACTIVE=true - N8N_BASIC_AUTH_USER=${N8N_USER} - N8N_BASIC_AUTH_PASSWORD=${N8N_PASSWORD} - N8N_PATH=/n8n/ - N8N_EDITOR_BASE_URL=https://eckardt-vault.duckdns.org/n8n/ - WEBHOOK_URL=https://eckardt-vault.duckdns.org/n8n/ healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:5678/healthz"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: cpus: '1.0' memory: 1G logging: driver: "json-file" options: max-size: "10m" max-file: "3" networks: - n8n-net # ============================================ # AUDIOBOOKSHELF - Audiobook Server # ============================================ audiobookshelf: image: ghcr.io/advplyr/audiobookshelf:latest container_name: audiobookshelf restart: unless-stopped security_opt: - apparmor=unconfined - seccomp=unconfined ports: - "13378:80" volumes: - /opt/docker/audiobookshelf/audiobooks:/audiobooks - /opt/docker/audiobookshelf/podcasts:/podcasts - /opt/docker/audiobookshelf/config:/config - /opt/docker/audiobookshelf/metadata:/metadata healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost:80/healthcheck"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: cpus: '1.0' memory: 512M logging: driver: "json-file" options: max-size: "10m" max-file: "3" networks: - audiobookshelf-net # ============================================ # WEBSITES - Static Website Hosting # ============================================ websites: image: nginx:alpine container_name: websites restart: unless-stopped security_opt: - apparmor=unconfined - seccomp=unconfined ports: - "8082:80" volumes: - /opt/docker/websites/html:/usr/share/nginx/html:ro - /opt/docker/websites/conf:/etc/nginx/conf.d:ro healthcheck: test: ["CMD", "wget", "-q", "--spider", "http://localhost/"] interval: 30s timeout: 10s retries: 3 deploy: resources: limits: cpus: '0.5' memory: 128M logging: driver: "json-file" options: max-size: "10m" max-file: "3" networks: - websites-net # ============================================ # API - FastAPI Backend # ============================================ api: image: python:3.11-slim container_name: api-server restart: unless-stopped security_opt: - apparmor=unconfined - seccomp=unconfined working_dir: /app ports: - "8000:8000" volumes: - /opt/docker/api:/app command: sh -c "pip install --quiet fastapi uvicorn httpx && python -m uvicorn main:app --host 0.0.0.0 --port 8000" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s timeout: 10s retries: 3 start_period: 30s deploy: resources: limits: cpus: '1.0' memory: 512M logging: driver: "json-file" options: max-size: "10m" max-file: "3" networks: - api-net # ============================================ # NETWORKS - Isolierte Netzwerke pro Service # ============================================ networks: nextcloud-net: driver: bridge vaultwarden-net: driver: bridge n8n-net: driver: bridge audiobookshelf-net: driver: bridge websites-net: driver: bridge api-net: driver: bridge