# ============================================================ # docker-compose.secure.yml — Secure Docker Compose Template # ============================================================ # Використовуйте цей шаблон як базу для всіх сервісів # ============================================================ version: '3.8' # Ізольовані мережі networks: frontend: driver: bridge # Доступ до інтернету (для nginx, gateway) backend: driver: bridge internal: true # БЕЗ доступу до інтернету! database: driver: bridge internal: true # БЕЗ доступу до інтернету! services: # ============================================================ # ПРИКЛАД: Безпечний PostgreSQL # ============================================================ postgres: # ✅ Завжди використовуйте digest, не тег! image: postgres@sha256:ЗАМІНІТЬ_НА_ПЕРЕВІРЕНИЙ_DIGEST container_name: dagi-postgres # ⚠️ НІКОЛИ auto-restart для нових сервісів! # Змініть на "unless-stopped" ТІЛЬКИ після верифікації restart: "no" # 🔒 Security options security_opt: - no-new-privileges:true # 📁 Read-only root filesystem read_only: true # 📂 Тимчасові директорії (noexec!) tmpfs: - /tmp:noexec,nosuid,nodev,size=100m - /var/run/postgresql:noexec,nosuid,nodev,size=10m # 💾 Volumes (тільки необхідні) volumes: - postgres_data:/var/lib/postgresql/data # 🔧 Resource limits deploy: resources: limits: cpus: '2' memory: 2G reservations: cpus: '0.5' memory: 512M # 🔓 Capabilities (мінімум!) cap_drop: - ALL cap_add: - CHOWN - SETUID - SETGID - DAC_OVERRIDE # ❌ No privileged mode! privileged: false # 🌐 Network (тільки database!) networks: - database # 🔐 Environment environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} # 🏥 Healthcheck healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER}"] interval: 30s timeout: 10s retries: 3 start_period: 30s # ============================================================ # ПРИКЛАД: Безпечний Redis # ============================================================ redis: image: redis@sha256:ЗАМІНІТЬ_НА_ПЕРЕВІРЕНИЙ_DIGEST container_name: dagi-redis restart: "no" security_opt: - no-new-privileges:true read_only: true tmpfs: - /tmp:noexec,nosuid,nodev,size=50m volumes: - redis_data:/data deploy: resources: limits: cpus: '1' memory: 512M cap_drop: - ALL privileged: false networks: - database healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 30s timeout: 10s retries: 3 # ============================================================ # ПРИКЛАД: Безпечний Router (з доступом до мережі) # ============================================================ router: image: ghcr.io/daarion-dao/dagi-router@sha256:ЗАМІНІТЬ container_name: dagi-router restart: "no" security_opt: - no-new-privileges:true # Router потребує запис для логів read_only: false tmpfs: - /tmp:noexec,nosuid,nodev,size=100m deploy: resources: limits: cpus: '2' memory: 1G cap_drop: - ALL cap_add: - NET_BIND_SERVICE privileged: false # Router має доступ до frontend і backend networks: - frontend - backend ports: - "9102:9102" healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9102/health"] interval: 30s timeout: 10s retries: 3 # ============================================================ # Volumes # ============================================================ volumes: postgres_data: driver: local redis_data: driver: local # ============================================================ # SECURITY CHECKLIST: # ============================================================ # [ ] Всі images pinned by SHA256 digest # [ ] restart: "no" для нових сервісів # [ ] security_opt: no-new-privileges # [ ] read_only: true де можливо # [ ] tmpfs з noexec для /tmp # [ ] Resource limits встановлені # [ ] cap_drop: ALL + тільки необхідні cap_add # [ ] privileged: false # [ ] Мережі ізольовані (internal: true для backend/database) # [ ] Healthcheck налаштований # ============================================================