Docker in produzione su un VPS: cosa si rompe e come risolvere

12 min di lettura·Matthieu·productionsecurityvpsdocker-composedocker|

Docker funziona sul tuo portatile. Su un VPS pubblico, aggira il firewall, riempie il disco di log, esegue tutto come root e non ha una strategia di aggiornamento. Ecco gli 8 problemi da risolvere.

Hai installato Docker sul tuo VPS. Hai lanciato docker compose up. La tua applicazione è online. Fatto, giusto?

Non proprio. Sul tuo portatile, nessuno scansiona le tue porte, lo spazio disco è abbondante e la sicurezza conta poco. Su un VPS esposto a Internet, le impostazioni predefinite di Docker lavorano attivamente contro di te.

Questa pagina copre gli 8 problemi che incontrerai e rimanda a una guida dedicata per ciascuno. Scorrila, trova cosa si applica al tuo server, segui la guida dettagliata.

Prerequisiti

Questa guida presuppone che tu conosca già le basi di Docker. Se hai bisogno di metterti in pari:

  • Comandi e concetti Docker
  • Applicazioni multi-servizio con Compose

Questo articolo è destinato a Debian 12 e Ubuntu 24.04 con Docker Engine 29.x e Compose v2 (versione 5.x).

Cosa si rompe quando esegui Docker su un VPS pubblico?

Otto cose si rompono quando sposti Docker dallo sviluppo a un VPS pubblico: il tuo firewall smette di funzionare, i container girano come root con accesso completo all'host, i log riempiono il disco senza rotazione, la rete dei container va in conflitto con quella dell'host, i servizi non hanno limiti di risorse né health check, i volumi non hanno strategia di backup, le porte sono esposte senza TLS e le immagini dei container diventano obsolete senza un piano di aggiornamento. Sono tutte impostazioni predefinite di Docker. Ognuna di queste ti creerà problemi in produzione.

Panoramica rapida prima delle guide dettagliate:

# Problema Comando diagnostico Rischio
1 Aggiramento del firewall sudo iptables -L DOCKER-USER -n Critico
2 Container root docker info --format '{{.SecurityOptions}}' Critico
3 Disco pieno per i log du -sh /var/lib/docker/containers/*/*-json.log Alto
4 Conflitti di rete docker network ls Medio
5 Nessun limite di risorse docker stats --no-stream Alto
6 Nessun backup dei volumi docker volume ls Alto
7 Nessun reverse proxy / TLS ss -tlnp | grep -E ':80|:443' Critico
8 Immagini obsolete docker compose images Medio

Esegui questi comandi sul tuo server adesso. Se un output ti sorprende, leggi la sezione corrispondente qui sotto.

Docker aggira il tuo firewall?

Sì. Docker manipola iptables direttamente, inserendo regole nelle tabelle nat e filter che vengono valutate prima che UFW o firewalld vedano il traffico. Quando pubblichi una porta con -p 8080:80, quella porta è aperta a tutto Internet, anche se le tue regole UFW dicono deny incoming.

Verifica se questo ti riguarda:

sudo iptables -L DOCKER-USER -n -v

Se l'output mostra una catena vuota o solo una regola RETURN incondizionata senza filtraggio, ogni porta pubblicata è completamente aperta.

La causa: i pacchetti destinati ai container Docker passano attraverso la catena FORWARD e la catena DOCKER. UFW opera sulla catena INPUT. Le due non si incontrano mai.

La correzione immediata più semplice è vincolare le porte pubblicate solo a 127.0.0.1:

ports:
  - "127.0.0.1:8080:80"

Questo rende la porta accessibile solo dall'host stesso. Combinalo con un reverse proxy per gestire il traffico esterno.

Per una guida completa sulla correzione della catena DOCKER-USER, l'integrazione UFW e la configurazione nftables.

Eseguire Docker come root è pericoloso su un VPS?

Per impostazione predefinita, il demone Docker gira come root e i container girano come root nei loro namespace. Se un attaccante evade da un container, atterra sull'host come root. Su un VPS pubblico, è un percorso diretto alla compromissione totale del server.

Verifica la tua configurazione attuale:

docker info --format '{{.SecurityOptions}}'

Cerca name=rootless nell'output. Se non c'è, il tuo demone gira come root.

Verifica anche se i tuoi container girano come root internamente:

docker ps -q | xargs -I {} docker exec {} id

Se vedi uid=0(root) per la maggior parte dei container, stanno girando come root al loro interno. Un'immagine che imposta USER appuser nel suo Dockerfile mostrerà un uid non-root.

Hai tre livelli di difesa:

  1. Modalità rootless esegue l'intero demone Docker sotto un utente non-root. Anche un'evasione dal container atterra come utente senza privilegi sull'host.
  2. Profili seccomp limitano quali syscall possono usare i container. Docker include un profilo predefinito che blocca circa 44 syscall pericolose, ma puoi restringerlo ulteriormente.
  3. AppArmor / SELinux aggiunge il controllo d'accesso obbligatorio sopra tutto il resto.

Configurazione completa di Docker rootless, profili seccomp personalizzati e no-new-privileges.

Perché i container Docker riempiono il disco?

Il driver di log predefinito di Docker è json-file senza limite di dimensione né rotazione. Ogni riga che la tua applicazione scrive su stdout viene archiviata in /var/lib/docker/containers/<id>/<id>-json.log. Un'applicazione web attiva può generare gigabyte di log in pochi giorni.

Controlla quanto spazio stanno occupando i log in questo momento:

sudo du -sh /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -rh | head -5

Su un VPS che gira da qualche settimana senza rotazione dei log, potresti vedere un output come:

4.2G    /var/lib/docker/containers/a1b2c3.../a1b2c3...-json.log
1.8G    /var/lib/docker/containers/d4e5f6.../d4e5f6...-json.log
256M    /var/lib/docker/containers/g7h8i9.../g7h8i9...-json.log

I log non sono l'unico consumatore di disco. Controlla l'utilizzo disco complessivo di Docker:

docker system df

Output tipico su un server con 5 servizi:

TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          12        5         4.2GB     2.8GB (66%)
Containers      8         5         52MB      12MB (23%)
Local Volumes   6         4         1.1GB     245MB (22%)
Build Cache     18        0         890MB     890MB (100%)

Quella build cache è recuperabile al 100%. Quelle 7 immagini inutilizzate occupano 2,8 GB. Su un disco VPS da 40 GB, si accumula in fretta.

La soluzione ha due parti: configurare la rotazione dei log in /etc/docker/daemon.json e impostare la pulizia periodica delle immagini inutilizzate e della build cache.

Configurazione completa della rotazione log, monitoraggio disco e pulizia automatizzata:

Come funziona la rete Docker su un singolo VPS?

Docker crea la sua rete bridge (172.17.0.0/16 di default) e gestisce gli IP dei container internamente. Su un VPS, questo può andare in conflitto con la rete dell'host, le subnet VPN o altri servizi.

Guarda quali reti ha creato Docker:

docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
a1b2c3d4e5f6   bridge    bridge    local
f6e5d4c3b2a1   host      host      local
9i8h7g6f5e4d   none      null      local

Ogni docker compose up crea una rete aggiuntiva. Dopo qualche progetto, potresti avere una dozzina di reti con subnet sovrapposte.

Decisioni chiave per la rete su un VPS:

  • Modalità bridge (predefinita): i container ottengono IP interni, le porte vengono pubblicate via iptables. Funziona per la maggior parte delle configurazioni. Aggiunge un livello NAT.
  • Modalità host: i container condividono direttamente lo stack di rete dell'host. Nessun overhead NAT, ma nessun isolamento delle porte. Utile per servizi sensibili alle prestazioni.
  • Reti bridge personalizzate: i container sulla stessa rete personalizzata possono raggiungersi tramite nome del container. È quello che Compose crea automaticamente.

Il punto importante su un VPS: definisci le tue subnet esplicitamente in docker-compose.yml invece di lasciare che Docker scelga. Questo evita conflitti con le reti interne del tuo provider di hosting.

Guida dettagliata su bridge vs host, subnet personalizzate e DNS inter-container:

Cosa succede senza limiti di risorse e health check?

Senza limiti di memoria, un singolo container con un memory leak consumerà tutta la RAM disponibile, attiverà l'OOM killer di Linux e farà cadere container non correlati o perfino il demone SSH. Senza health check, Docker non ha modo di sapere che un container è guasto. Rimane "running" mentre restituisce errori.

Controlla se i tuoi container hanno limiti impostati:

docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.CPUPerc}}"

Se la colonna MEM % mostra valori ma non hai mai impostato limiti, quelle percentuali sono calcolate sulla RAM totale dell'host. Un container che mostra 45% sta usando il 45% dell'intera memoria del tuo VPS, e niente gli impedisce di prenderne di più.

La configurazione minima di produzione nel tuo docker-compose.yml:

services:
  app:
    deploy:
      resources:
        limits:
          memory: 512M
          cpus: "1.0"
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 10s
    restart: unless-stopped

La policy restart: unless-stopped riavvia automaticamente i container crashati ma rispetta le fermate manuali. L'healthcheck permette a Docker di marcare i container non sani e riavviarli in base al conteggio dei tentativi.

Guida completa sui limiti di risorse Compose, pattern di healthcheck e policy di riavvio:

Come fare il backup dei volumi Docker?

I volumi Docker persistono i dati al di fuori dei container. Se un volume viene cancellato o corrotto, il tuo database, i file caricati o la configurazione spariscono. Docker non ha un meccanismo di backup integrato per i volumi.

Elenca i tuoi volumi e le loro dimensioni:

docker system df -v | grep -A 100 "Local Volumes space usage"

O controlla i singoli mount point dei volumi:

docker volume ls -q | xargs -I {} docker volume inspect {} --format '{{.Name}}: {{.Mountpoint}}'

I mount point si trovano sotto /var/lib/docker/volumes/ di default. Puoi fare il backup con gli strumenti Linux standard, ma devi fermare o mettere in pausa il container prima per evitare snapshot inconsistenti. Per i database, una copia del filesystem di un database in esecuzione non è un backup affidabile. Devi prima fare un dump.

Strategie di backup, procedure di ripristino e pianificazione automatizzata:

Come esporre i servizi Docker con TLS?

Pubblicare le porte direttamente con -p 443:443 su ogni container non scala oltre un servizio. Ti serve un reverse proxy che termini il TLS, instradi il traffico al container giusto e gestisca il rinnovo dei certificati.

Controlla cosa è attualmente in ascolto sul tuo VPS:

ss -tlnp | grep -E ':80|:443'

Se vedi i tuoi container applicativi collegati direttamente alle porte 80 o 443, sono esposti senza un livello proxy. Questo significa che ogni servizio ha bisogno della propria gestione dei certificati, e non puoi ospitare più domini su un singolo VPS.

Tre opzioni di reverse proxy dominano l'ecosistema Docker:

Proxy Auto-discovery TLS automatico Stile di configurazione
Traefik Sì (label Docker) Let's Encrypt integrato Label + YAML
Caddy Via plugin Automatico di default Caddyfile
Nginx Proxy Manager Socket Docker UI Let's Encrypt Interfaccia web

Traefik è la scelta più comune per i deploy Docker-nativi perché legge le label dei container e genera le regole di routing automaticamente. Nessun file di configurazione da aggiornare quando aggiungi un servizio.

Confronto, guide di installazione e configurazione TLS per ogni opzione:

Qual è la strategia di aggiornamento per i container Docker su un VPS?

Le immagini Docker non si aggiornano da sole. Se esegui postgres:16 e una patch di sicurezza esce in postgres:16.4, il tuo container continua a girare con la vecchia immagine finché non la scarichi e ricrei il container esplicitamente.

Controlla quali immagini stanno usando i tuoi servizi:

docker compose images

Confronta i digest delle immagini con le ultime versioni disponibili:

docker compose pull --dry-run 2>&1

Se un'immagine appare come "pulled" nell'output del dry-run, la tua versione in esecuzione è obsoleta.

Le decisioni chiave:

  • Fissa i tag delle immagini: non usare mai :latest in produzione. Usa tag di versione specifici come postgres:16.4 o anche digest SHA.
  • Pull pianificati: esegui docker compose pull && docker compose up -d a intervalli regolari, ma testa prima gli aggiornamenti in staging.
  • Riavvii senza downtime: usa gli health check e docker compose up -d --no-deps <service> per aggiornare un servizio alla volta.
  • Scansione immagini: strumenti come Trivy scansionano le tue immagini alla ricerca di CVE note prima del deploy.

Strategie di aggiornamento, pattern di pinning delle immagini e deploy senza downtime:

Serve Kubernetes per eseguire Docker in produzione?

No. Docker Compose è uno strumento di deploy pronto per la produzione per carichi di lavoro su singolo server. Kubernetes risolve l'orchestrazione multi-nodo, lo scaling automatico e il self-healing su un cluster. Se la tua applicazione gira su un singolo VPS, Compose ti dà tutto ciò che serve senza l'overhead operativo di Kubernetes.

Dove Compose funziona:

  • Un singolo VPS con 3-15 container
  • Pattern di traffico statici o prevedibili
  • Team piccolo senza ingegneri di piattaforma dedicati
  • Servizi che tollerano secondi di downtime durante gli aggiornamenti

Dove superi Compose:

  • Più server necessari per l'alta disponibilità
  • Auto-scaling basato su picchi di traffico
  • Service mesh con centinaia di microservizi
  • Requisiti di zero downtime con deploy blue-green tra i nodi

La via di mezzo leggera è K3s, un Kubernetes ridotto che gira su un singolo VPS con circa 512 MB di overhead RAM. Ma per la maggior parte dei progetti personali, MVP SaaS e piccole applicazioni di produzione, Compose è lo strumento giusto.

Quanta RAM serve a un VPS per Docker in produzione?

Un VPS che esegue Docker in produzione ha bisogno di almeno 4 GB di RAM per 3-5 container. Il demone Docker stesso usa circa 100-200 MB. Ogni container aggiunge la propria impronta di memoria. Senza limiti di memoria impostati, un singolo container malfunzionante può consumare tutto.

Dimensione VPS Container Adatto per
4 GB di RAM 3-5 leggeri Blog, API, database, Redis
8 GB di RAM 5-10 misti MVP SaaS, servizi multipli, stack di monitoraggio
16 GB di RAM 10-20 Progetti multipli, runner CI, database pesanti
32 GB di RAM 20+ Inferenza IA, database grandi, server di build

Lo storage conta quanto la RAM. Le immagini Docker, i volumi, i log e la build cache si accumulano. Prevedi almeno 40 GB di storage NVMe e configura il monitoraggio descritto in dal primo giorno.

La CPU è raramente il collo di bottiglia per i servizi web containerizzati. 4 vCPU gestiscono la maggior parte dei carichi di lavoro. Eccezioni: transcodifica video, inferenza IA e server di build.

Per un VPS con storage NVMe dimensionato per carichi di lavoro Docker in produzione, vedi i piani VPS di Virtua Cloud.

Checklist di produzione

Prima di andare in produzione con Docker su un VPS, verifica ogni punto:

  • Le regole del firewall bloccano tutte le porte pubblicate da Docker eccetto tramite il reverse proxy
  • I container girano come utenti non-root dove possibile
  • Il demone Docker gira in modalità rootless o i container usano seccomp + no-new-privileges
  • La rotazione dei log è configurata in /etc/docker/daemon.json
  • docker system prune viene eseguito su programmazione (cron settimanale)
  • Ogni servizio ha limiti di memoria e CPU in docker-compose.yml
  • Ogni servizio ha un health check
  • La policy di riavvio è impostata (unless-stopped o on-failure)
  • I volumi con dati importanti hanno backup automatizzati
  • Un reverse proxy gestisce la terminazione TLS e il rinnovo dei certificati
  • I tag delle immagini sono fissati a versioni specifiche, non :latest
  • Hai una procedura di aggiornamento testata per scaricare nuove immagini
  • journalctl -u docker e docker logs <container> funzionano e sai dove guardare

Se non puoi spuntare ogni punto, lavora sugli articoli linkati in ogni sezione sopra.


Copyright 2026 Virtua.Cloud. Tutti i diritti riservati. Questo contenuto è un'opera originale del team Virtua.Cloud. La riproduzione, ripubblicazione o redistribuzione senza autorizzazione scritta è vietata.

Pronto a provare?

Esegui Docker in produzione su un VPS affidabile.

Vedi piani VPS
Docker in produzione su un VPS: 8 problemi da risolvere