Docker Compose Hardening: Guida Completa per Homelab Sicuri

22/06/2026

Docker Compose Hardening: Guida Completa per Homelab Sicuri

Docker Compose è uno strumento essenziale per gestire stack di container in ambienti homelab, ma la sicurezza spesso viene trascurata. In questa guida approfondiamo le tecniche di hardening per proteggere i vostri servizi self-hosted.

Perché Hardening Docker Compose?

I container Docker, se non configurati correttamente, possono rappresentare un rischio per la sicurezza dell'intero homelab. Privilegi elevati, mount point pericolosi e configurazioni di rete aperte sono vulnerabilità comuni.

Best Practices Fondamentali

1. User Namespace Remapping

La remappatura degli user namespace è una delle tecniche più efficaci per prevenire l'escalation di privilegi:

services:
  app:
    image: nginx:alpine
    user: "1000:1000"
    security_opt:
      - "no-new-privileges:true"

2. Limitazione delle Capabilities

Rimuovere le capabilities non necessarias riduce drasticamente la superficie di attacco:

services:
  database:
    image: postgres:15
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - DAC_OVERRIDE
      - SETGID
      - SETUID

3. Read-Only Filesystem

Configurare i container con filesystem di sola lettura quando possibile:

services:
  web:
    image: nginx:alpine
    read_only: true
    tmpfs:
      - /tmp
      - /run
      - /var/cache/nginx

Configurazione di Rete Sicura

Isolamento di Rete

Utilizzare reti Docker dedicate per ogni stack:

networks:
  app-network:
    driver: bridge
    internal: true
    ipam:
      config:
        - subnet: 172.28.0.0/16

services:
  app:
    networks:
      - app-network

Limitazione delle Porte

Esporre solo le porte strettamente necessarie:

services:
  webapp:
    ports:
      - "8080:80"  # Solo HTTP
      # - "8443:443" # Solo se serve HTTPS

Gestione dei Volumi e Mount Point

Volumi Named vs Bind Mounts

Preferire volumi named invece di bind mounts per maggior sicurezza:

volumes:
  app-data:
    driver: local

services:
  app:
    volumes:
      - app-data:/app/data
      # Evitare: - /host/path:/container/path

Limitazioni di Accesso

services:
  database:
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - PGDATA=/var/lib/postgresql/data/pgdata

Resource Limits e Security Opt

Limitazione delle Risorse

services:
  app:
    deploy:
      resources:
        limits:
          cpus: "2"
          memory: 512M
        reservations:
          cpus: "0.5"
          memory: 256M

Opzioni di Sicurezza Avanzate

services:
  critical-app:
    security_opt:
      - "apparmor:docker-default"
      - "seccomp=unconfined"
    pids_limit: 100

Checklist di Hardening Completa

  • [ ] User namespace remapping configurato
  • [ ] Capabilities non necessarie rimosse
  • [ ] Filesystem in read-only dove possibile
  • [ ] Reti isolate e internal
  • [ ] Solo porte necessarie esposte
  • [ ] Volumi named invece di bind mounts
  • [ ] Resource limits appropriati
  • [ ] Security opt configurati
  • [ ] No-new-privileges abilitato
  • [ ] PIDs limit impostato

Esempio Completo di docker-compose.yml Hardened

version: "3.8"

networks:
  app-net:
    driver: bridge
    internal: true
    ipam:
      config:
        - subnet: 172.22.0.0/16

volumes:
  app-data:
    driver: local
  db-data:
    driver: local

services:
  web:
    image: nginx:alpine
    user: "101:101"
    read_only: true
    tmpfs:
      - /tmp
      - /run
      - /var/cache/nginx
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - "no-new-privileges:true"
    networks:
      - app-net
    ports:
      - "8080:80"
    deploy:
      resources:
        limits:
          memory: 256M
          cpus: "1"

  app:
    image: node:18-alpine
    user: "1000:1000"
    read_only: true
    tmpfs:
      - /tmp
    cap_drop:
      - ALL
    security_opt:
      - "no-new-privileges:true"
    networks:
      - app-net
    volumes:
      - app-data:/app/data
    environment:
      - NODE_ENV=production
      - PORT=3000

  database:
    image: postgres:15-alpine
    user: "999:999"
    cap_drop:
      - ALL
    cap_add:
      - CHOWN
      - SETGID
      - SETUID
    security_opt:
      - "no-new-privileges:true"
    networks:
      - app-net
    volumes:
      - db-data:/var/lib/postgresql/data
    environment:
      - POSTGRES_DB=appdb
      - POSTGRES_USER=appuser
      - POSTGRES_PASSWORD_FILE=/run/s...rd
    secrets:
      - db_password

secrets:
  db_password:
    file: ./secrets/db_password.txt

Conclusioni

L'hardening di Docker Compose non è un processo one-time ma una pratica continua. Ogni nuovo service aggiunto allo stack dovrebbe essere valutato secondo queste linee guida. La sicurezza dei container è un investimento che protegge non solo i singoli servizi ma l'intera infrastruttura homelab.

Ricordate: la sicurezza perfetta non esiste, ma ridurre la superficie di attacco è il primo passo verso un homelab più resiliente.

Fonti: OWASP Docker Security Cheat Sheet, Docker Official Documentation, Reddit r/homelab discussions