# Docker Compose für Full Stack Application # SICHERHEITS-OPTIMIERT für Gitea Actions & Production version: "3.8" services: app: # Automatischer Build aus dem aktuellen Verzeichnis build: context: . dockerfile: Dockerfile args: NODE_ENV: ${NODE_ENV:-production} BUILD_VERSION: ${BUILD_VERSION:-latest} # Optional: Image-Name für Registry-Push (für CI/CD) # image: ${REGISTRY:-localhost}/${IMAGE_NAME:-fullstack-app}:${TAG:-latest} container_name: ${APP_CONTAINER_NAME:-fullstack-app} restart: unless-stopped # Non-root User (UID/GID 1000) user: "1000:1000" environment: - NODE_ENV=${NODE_ENV:-production} # Optional: Nur wenn PostgreSQL verwendet wird - DATABASE_URL=${DATABASE_URL:-} - JWT_SECRET=${JWT_SECRET} # Security Options security_opt: - no-new-privileges:true cap_drop: - ALL cap_add: - NET_BIND_SERVICE # Erlaubt Binding an Ports < 1024 (falls nötig) # Resource Limits (verhindern DoS) deploy: resources: limits: cpus: '2.0' memory: 2G reservations: cpus: '0.5' memory: 512M networks: - app-network # Optional: Nur aktivieren wenn PostgreSQL verwendet wird # depends_on: # postgres: # condition: service_healthy ports: - "${APP_PORT:-8080}:8080" # Port 8080 für non-root # Volumes für persistente Daten volumes: - app-data:/data healthcheck: test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s # ============================================================================= # PostgreSQL Service (OPTIONAL) # ============================================================================= # Nur aktivieren wenn PostgreSQL benötigt wird. # Für SQLite oder andere Datenbanken kann dieser Service entfernt werden. # # Um PostgreSQL zu aktivieren: # 1. Entferne die Kommentare (#) vor dem gesamten postgres-Service # 2. Aktiviere "depends_on" im app-Service (siehe oben) # 3. Setze DATABASE_URL in .env # ============================================================================= # postgres: # image: postgres:15-alpine # container_name: ${POSTGRES_CONTAINER_NAME:-postgres-db} # restart: unless-stopped # # # Non-root User (postgres verwendet UID 70 standardmäßig) # user: "70:70" # # environment: # POSTGRES_DB: ${POSTGRES_DB:-appdb} # POSTGRES_USER: ${POSTGRES_USER:-postgres} # POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} # MUSS in .env gesetzt werden! # POSTGRES_INITDB_ARGS: "--auth-host=scram-sha-256" # Sichere Auth # POSTGRES_HOST_AUTH_METHOD: scram-sha-256 # # # Security Options # security_opt: # - no-new-privileges:true # cap_drop: # - ALL # cap_add: # - CHOWN # - DAC_OVERRIDE # - FOWNER # - SETGID # - SETUID # # # Resource Limits # deploy: # resources: # limits: # cpus: '1.0' # memory: 1G # reservations: # cpus: '0.25' # memory: 256M # # volumes: # - postgres_data:/var/lib/postgresql/data # # networks: # - app-network # # # KEIN Port-Expose nach außen - nur intern erreichbar! # # Für lokales Debugging kann der Port freigegeben werden: # # ports: # # - "${POSTGRES_PORT:-5432}:5432" # # healthcheck: # test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres}"] # interval: 10s # timeout: 5s # retries: 5 # start_period: 10s networks: app-network: driver: bridge # Optional: Netzwerk isolieren internal: false # Auf 'true' setzen wenn kein Internet-Zugriff nötig volumes: # Persistente Daten für die App (z.B. SQLite-Datenbank, Uploads, etc.) app-data: driver: local # Optional: Nur wenn PostgreSQL verwendet wird # postgres_data: # driver: local