Docker Compose in Homelab: organizzazione, profili e best practice

Ultimo aggiornamento: Maggio 24 2026
  • Organizzare Docker Compose per profili e ruoli semplifica la gestione di homelab con decine di servizi.
  • Centralizzare la configurazione in .env, utilizzare le sovrascritture e gestire le versioni con Git rende l'ambiente portatile e facile da migrare.
  • Reti dedicate, Traefik e controlli sanitari migliorano la sicurezza, l'isolamento e la resilienza dei servizi.
  • Il monitoraggio, i registri controllati e i backup automatici rendono l'homelab una piattaforma stabile nel lungo termine.

Docker Compose Homelab

Allestire un moderno homelab con i container è diventato un hobby molto diffuso tra gli appassionati di tecnologia. Docker Compose è quasi sempre al centro di questa configurazione : permette di definire i servizi in formato YAML, di gestirne le versioni con Git e di avviare l'intero ambiente con un singolo comando.

Tuttavia, quando si inizia a crescere, le cose cambiano: si passa da due o tre container a decine di servizi, reti interne, proxy inversi, database e runner CI . È allora che sorge la grande domanda: un'unica gigantesca istanza di Docker Compose o tanti piccoli file? Come organizzare profili, reti, backup, sicurezza e, soprattutto, semplificare la migrazione?

Approcci pratici per configurare Docker Compose in un laboratorio domestico

Configurazione del laboratorio domestico con Docker Compose

In pratica, chi utilizza Homelabs da un po' di tempo di solito lavora con tre diversi modelli organizzativi di Compose, ognuno con i propri vantaggi e svantaggi. Scegliere l'approccio giusto evita molti problemi in fase di espansione o migrazione a una nuova macchina.

Da un lato, ci sono coloro che hanno iniziato con i comandi Docker Run standalone, poi sono passati a Portainer e infine sono approdati a Docker Compose . È uno scenario tipico: Portainer offre un'ottima visibilità, un'interfaccia intuitiva, modelli, ecc., ma alla fine, modificare parametri complessi o migrare configurazioni diventa complicato se non si dispone di file di configurazione.

All'estremo opposto si trova chi ha consolidato tutto in un unico "mega" docker-compose.yml in grado di eseguire assolutamente tutti i servizi dell'homelab: reverse proxy, media, utility, monitoraggio, LLM, database... Tutto in un unico stack.

Nel frattempo, molti utenti optano per un approccio misto: diversi piccoli file docker-compose.yml raggruppati per contesto (ad esempio, media, infrastruttura, produttività, monitoraggio), tutti nello stesso repository e solitamente con variabili d'ambiente globali condivise.

Una soluzione piuttosto elegante unisce i due mondi: un file docker-compose "root" che include altri file (ciascuno in una sottocartella di app o servizi). In questo modo si mantiene una visione globale dell'homelab, senza però dover destreggiarsi tra un file YAML di migliaia di righe illeggibile.

Profili, raggruppamento per funzione e grandi laboratori domestici

profili docker compose homelab

Quando il tuo homelab inizia ad avvicinarsi a 30, 40 o 50 servizi (inclusi servizi di backup come database, cache o indicizzatori), è fondamentale metterli in ordine. È qui che entrano in gioco sia il raggruppamento per funzione che l'utilizzo dei profili Docker Compose.

Un modello molto comune è quello di raggruppare tutto in un unico "progetto" Compose, ma logicamente suddiviso per profili. Ad esempio:

  • Profilo principale: nucleo del laboratorio domestico, con Traefik come proxy inverso e un provider di identità (ad esempio, OAuth o Authentik) per autenticare tutte le app sotto lo stesso dominio con HTTPS.
  • Profilo mediaticoServizi come Plex, Sonarr, Radarr, Ombi, SABnzbd o qBittorrent, responsabili della selezione, del download e della distribuzione di contenuti multimediali.
  • Profilo dei servizi pubbliciStrumenti come Portainer, Watchtower (se utilizzato), Diun, dockcheck o simili per gestire e monitorare i container e gli aggiornamenti.
  • Profilo di infrastruttura/monitoraggio: Traefik, cAdvisor, Prometheus, Grafana, Uptime Kuma, Dozzle e tutto ciò che riguarda il monitoraggio e la registrazione dei log.
  • Profili sperimentali o LLM: stack specifici per LLM o applicazioni particolari (ChatGPT Next Web locale, LibreOffice Online, ecc.) che di solito sono disabilitati per impostazione predefinita.

Il bello dei profili è che permettono di implementare solo una parte dell'infrastruttura, a seconda delle necessità. Ad esempio, è possibile eseguire solo il profilo core + infrastruttura su un mini PC a basso consumo e implementare solo il profilo multimediale sul server più potente, dotato di più dischi e GPU.

Nei repository ben progettati, di solito è presente un file docker-compose.yml "master" nella directory principale che utilizza l'istruzione include per inserire singoli file in una cartella apps/ o services/ . Inoltre, quasi tutti i servizi sono configurati tramite un singolo file .env globale e alcuni segreti sono memorizzati in una directory secrets/ , il che semplifica notevolmente la configurazione iniziale.

Seguendo questo schema, la gestione dell'homelab si riduce sostanzialmente alla modifica del file .env e dei segreti, all'attivazione o disattivazione dei profili e alla scelta dei servizi da avviare su ciascun host . Questa soluzione è ideale se si intende distribuire lo stesso set di applicazioni su più macchine.

Un unico file docker-compose di grandi dimensioni contro diversi file di piccole dimensioni.

Struttura dei file di Docker Compose Homelab

Questo è l'eterno dilemma: un singolo file docker-compose.yml contenente tutto, oppure più file per ogni servizio/stack? La vera risposta di solito è "dipende da cosa si vuole privilegiare: semplicità di migrazione o chiarezza per ogni servizio".

Coloro che sostengono l'adozione di un unico file master solitamente ne evidenziano diversi vantaggi:

  • La migrazione degli host è semplicissimaÈ sufficiente clonare il repository, copiare il file .env e i segreti, montare i volumi ed eseguire `docker compose up -d`. Non è necessario procedere directory per directory.
  • L'infrastruttura come codice di verità: l'intera topologia dell'homelab (servizi, reti, volumi, dipendenze) è centralizzata.
  • Aggiornamenti centralizzati: se modifichi la versione di un'immagine, i criteri di riavvio o le impostazioni di registrazione, sai esattamente dove intervenire.
  Sicurezza nei sistemi operativi: consigli e raccomandazioni

Ma presenta anche degli svantaggi evidenti: un file YAML enorme è più difficile da gestire, aumentano i conflitti di unione e, quando si esegue il debug di un problema specifico, ci si ritrova a navigare in un mostro di centinaia di righe. Non è raro provare un certo rammarico quando tutto diventa troppo grande.

L'altro approccio consiste nell'avere un file docker-compose.yml per ogni applicazione o per ogni stack logico , con una struttura simile a questa:

docker/
├── bookstack/
│   └── docker-compose.yml
├── dashy/
│   └── docker-compose.yml
└── traefik/
    └── docker-compose.yml

In questo modo, ogni container viene denominato in modo simile a bookstack-app-1 o traefik-reverse-proxy-1 , il che consente di individuare rapidamente i problemi: se il container bookstack-app-1 si blocca, si sa esattamente in quale cartella cercare.

Dal punto di vista visivo, è molto più pulito e permette di gestire ogni servizio in modo indipendente (avviandolo, arrestandolo o aggiornandolo senza influire sugli altri). Inoltre, applicazioni come Dozzle sfruttano la presenza di stack separati per organizzare meglio i log.

Lo svantaggio è che, se si separa troppo tutto, il coordinamento tra servizi comuni (come Traefik o reti condivise) richiede un po' più di attenzione : bisogna dichiarare le reti esterne, le etichette Traefik specifiche e ricordare la nomenclatura delle reti create da altri file docker-compose.

Procedure consigliate per l'utilizzo di file .env, override e controllo di versione.

Uno dei trucchi più sottovalutati è centralizzare la configurazione nei file .env . Invece di riempire il file docker-compose.yml di variabili d'ambiente, si definisce qualcosa del genere:

DB_USERNAME=myuser
DB_PASSWORD=secretpassword

Nel file YAML vengono quindi richiamati come ${DB_USERNAME} o ${DB_PASSWORD} . Questo rende Compose leggibile a colpo d'occhio, consente di condividere variabili tra più servizi e, soprattutto, memorizza le password in un file separato (che è possibile escludere da Git).

Per i diversi ambienti (produzione, test, sviluppo), è molto utile sfruttare il file docker-compose.override.yml . L'idea è di avere un file docker-compose.yml di base e, nella sezione override, sovrascrivere solo ciò che cambia: porte, percorsi, flag di debug, ecc.

Ad esempio, in fase di sviluppo è possibile caricare un override in cui si espone una porta diversa, si abilita il debug e si monta il codice sorgente locale . Non si modifica il file YAML principale, ma si adatta lo stack all'ambiente in cui viene eseguito.

Ovviamente, il controllo di versione con Git è obbligatorio se si desidera che il proprio homelab abbia un aspetto anche solo lontanamente professionale . In genere, la configurazione sarà simile a questa:

homelab-docker/
├── docker-compose.yml
├── .env.example
├── services/
│   ├── media/
│   ├── infra/
│   └── ...
└── scripts/

Da lì, si inizializza il repository, si confermano le modifiche all'infrastruttura e, se qualcosa si rompe, si può ripristinare una versione precedente di Compose in pochi secondi . Per gli homelab più ambiziosi, questa non è solo un'opzione; è l'unico modo per non impazzire.

Reti, Traefik e vulnerabilità dei servizi sicuri

Nella quasi totalità degli homelab di livello intermedio, si riscontra la stessa combinazione: Traefik come reverse proxy e un provider di identità centralizzato (Auth o Authentik) . Questo permette di esporre numerose applicazioni su sottodomini con HTTPS e SSO.

Un approccio classico consiste nel configurare una rete Docker dedicata, come ad esempio reverse_proxy o simili, a cui sono collegati Traefik e tutti i servizi web che si intendono rendere accessibili dall'esterno. I container rimanenti (database, cache, ecc.) restano su reti interne isolate.

Se utilizzi Traefik e separi i tuoi servizi in diverse istanze Docker Compose, devi definire una rete esterna condivisa . Qualcosa del genere:

services:
  bookstack:
    image: lscr.io/linuxserver/bookstack
    networks:
      - traefik-net
    labels:
      - "traefik.docker.network=traefik_default"

networks:
  traefik-net:
    name: traefik_default
    external: true

In questo caso, la rete traefik_default viene creata dallo stack di Traefik e gli altri servizi vengono aggiunti ad essa tramite una rete esterna chiamata traefik-net. Le etichette indicano a Traefik quale rete utilizzare per instradare il traffico.

Quando un singolo stack include servizi di backend (ad esempio, un container web e il relativo database), è possibile connetterli a una rete predefinita condivisa e concedere al container web l'accesso alla rete Traefik soltanto . Al database verrà assegnata l'etichetta `traefik.enable=false` in modo che Traefik lo ignori.

Questo tipo di configurazione offre due vantaggi principali: isolamento tra i servizi ed esposizione controllata . Solo i container etichettati con le etichette di Traefik e che si trovano sulla rete proxy diventano accessibili dall'esterno.

Persistenza dei dati, volumi e struttura del disco

Un homelab senza dati persistenti non è molto utile: database, configurazioni, file multimediali, documenti... tutto deve sopravvivere a un arresto anomalo di Docker Compose. I volumi e i bind mount sono la vostra ancora di salvezza.

  systemd 259: supporto per musl, sicurezza e modifiche alle chiavi

Molte persone organizzano i propri spazi di archiviazione utilizzando una struttura simile a questa:

/mnt/storage/
├── downloads/
│   ├── movies/
│   └── tv/
├── media/
│   ├── movies/
│   ├── tv/
│   └── music/
└── srv/
    └── 

L'idea è che i programmi di download (qBittorrent, SABnzbd, ecc.) vedano solo la cartella dei download , i gestori come Radarr/Sonarr abbiano accesso sia ai download che ai file multimediali (per spostare/creare collegamenti fisici), e i server come Plex o Jellyfin vedano solo la cartella dei file multimediali.

In questo modo si applica il principio del minimo privilegio : ogni container accede solo a ciò di cui ha effettivamente bisogno. E la netta separazione è utile anche per decidere quali volumi o percorsi eseguire il backup sul cloud o su unità esterne.

La directory srv viene in genere utilizzata per memorizzare le configurazioni delle applicazioni (ad esempio, /srv/jellyfin/config, /srv/traefik, /srv/paperless, ecc.). Di solito, questa directory è parzialmente versionata (modelli, file Caddyfile, ecc.), escludendo qualsiasi elemento critico o che richieda molte risorse.

In alcuni casi, è utile utilizzare hard link nella catena di download: servizi come Radarr o Sonarr possono collegare i file scaricati per mantenere la condivisione senza duplicare lo spazio su disco. La struttura di directory proposta da guide come TRaSHGuides si basa proprio su questo principio.

Automatizzare le distribuzioni con GitHub Actions e i runner locali.

Se vuoi spingerti oltre, puoi automatizzare gli aggiornamenti del tuo homelab con CI/CD . Diversi utenti hanno sostituito Jenkins e strumenti simili con un flusso di lavoro che utilizza GitHub Actions e un runner ospitato direttamente all'interno dell'homelab.

Il meccanismo è semplice: ogni volta che effettui un push sul ramo principale del tuo repository homelab, viene avviato un flusso di lavoro di GitHub Actions che esegue test, controlli logici e, se tutto va bene, distribuisce le modifiche sul server.

Un flusso di lavoro tipico include fasi quali:

  • Scanner di segreti tipo Gitleaks: nel caso in cui tu abbia caricato accidentalmente password o token nel repository.
  • linting di codice YAML o di infrastruttura, per mantenere un formato leggibile e coerente.
  • Aggiornamento del repository all'interno dell'homelab stesso: git pull sul server di destinazione.
  • Ricreazione controllata dei contenitori: interrompi i vecchi, avvia i nuovi e verifica lo stato.

Vantaggi: maggiore sicurezza (controllo delle fughe di dati sensibili), migliore qualità del codice e implementazioni ripetibili con un singolo push . Inoltre, poiché si utilizza un runner locale, le immagini e i volumi non escono dalla rete; è sufficiente sfruttare l'interfaccia di GitHub per visualizzare le pipeline.

Perché Docker Compose semplifica la vita in un homelab

Molte persone hanno trascorso anni affidandosi a Docker Run e Portainer, finché, a seguito di un incidente o di una migrazione, sono state costrette a rivalutare il proprio approccio. Quando si perde un host o si devono spostare i servizi su un'altra macchina, dipendere esclusivamente da comandi o configurazioni isolate all'interno di Portainer è una trappola.

La grande differenza quando si passa a Compose è che l'intera definizione del servizio diventa testo : volumi, porte, reti, etichette, variabili... Tutto in un file YAML che è possibile copiare, condividere, versionare e riutilizzare.

Modificare un servizio non significa più "ricostruire un container manualmente"; ora si tratta semplicemente di modificare una riga in un file, salvarlo ed eseguire `docker compose up -d` . Non è più necessario ricordare il comando originale o cliccare su più schermate di Portainer.

Inoltre, se lavori con più server (mini PC, NAS, desktop), è estremamente comodo poter copiare lo stesso file Compose su un'altra macchina, modificare quattro percorsi ed eseguire lo stesso stack su hardware diverso . Infatti, molti utenti confermano che, dopo un'esperienza traumatica legata alla perdita di dati o a migrazioni caotiche, Compose ha fatto risparmiare loro molto tempo in seguito.

Come ulteriore vantaggio, la creazione di nuovi servizi a partire da quelli esistenti diventa banale: ad esempio, clonare la configurazione di Plex per configurare Jellyfin riutilizzando gli stessi percorsi multimediali e dispositivi di transcodifica richiede solo pochi minuti se lo si fa copiando i blocchi YAML.

Ottimizzazione: contesto di compilazione, compilazioni multi-fase e risorse

Sebbene molti container di Homelab provengano da immagini pubbliche, in alcuni casi dovrai compilarne di tue. In queste situazioni, è importante gestire il contesto di build : non caricare l'intero repository senza filtri, ma limitati alla cartella del tuo progetto (utilizzando una direttiva `.dockerignore` efficace) per garantire build veloci e leggere.

Un'altra tecnica molto utile è quella di utilizzare build multi-stadio nei Dockerfile: nella prima fase si installano le dipendenze e si compila, mentre nella seconda fase si copiano solo gli artefatti necessari in una piccola immagine di base. Il risultato: immagini finali molto più piccole e sicure , perché non includono toolchain o librerie superflue.

  Architettura CPU multi-core e sistemi multiprocessore

Nella sezione Compose, è possibile definire limiti di CPU e RAM (soprattutto negli ambienti Swarm o quando Docker rispetta tali parametri) per impedire che le applicazioni che richiedono molte risorse le monopolizzino. In Homelabs, questo aiuta a evitare che un servizio configurato in modo errato comprometta il resto del sistema.

Non dimenticate le policy di riavvio (restart: always, unless-stopped, on-failure): con esse vi assicurate che i servizi critici (reverse proxy, VPN, database chiave) si riavviino automaticamente dopo un riavvio o un guasto occasionale.

Infine, è consigliabile programmare attività di pulizia periodiche con comandi come `docker image prune`, `docker container prune` e `docker volume prune` per rimuovere i residui di vecchie build, container arrestati o volumi orfani e recuperare così spazio su disco.

Servizi sanitari, registrazione e monitoraggio

Per evitare che il tuo homelab diventi una scatola nera, è importante concentrarsi su tre aspetti chiave: controlli di integrità, registrazione controllata e monitoraggio . Docker Compose ti permette di dichiarare controlli di integrità per ogni servizio (utilizzando comandi come `curl -f http://localhost` o script specifici) che determinano se un container è integro.

Questo permette di garantire che solo i container "integri" ricevano traffico (ad esempio, tramite Traefik) e che, se smettono di rispondere, vengano riavviati secondo la policy configurata. Ciò aumenta significativamente la resilienza con il minimo sforzo.

Per quanto riguarda i log, la configurazione del driver json-file con i limiti max-size e max-file impedisce che il disco si riempia di gigabyte di log dimenticati. Strumenti web come Dozzle consentono di visualizzare i log di tutti i container da un browser, il che è molto comodo per il debug di servizi specifici.

Per metriche e monitoraggio continuo, la combinazione classica è cAdvisor + Prometheus + Grafana . cAdvisor espone statistiche sull'utilizzo di CPU, memoria, disco e rete per ogni container; Prometheus le raccoglie periodicamente e Grafana le visualizza in dashboard accattivanti, con avvisi in caso di picchi anomali.

Un homelab ben configurato in genere include Uptime Kuma per i controlli di disponibilità (HTTP, ICMP, TCP, ecc.) e un sistema di backup automatico come Duplicati per copiare i dati critici su altri dischi o sul cloud. In questo modo, si ha sempre sotto controllo la situazione e, in caso di problemi, si evita di perdere i dati importanti.

Sicurezza e accesso remoto all'homelab

Tuttavia, anche se si opta per il fai-da-te, la sicurezza non è un'opzione, bensì una necessità. Molti scelgono di non esporre direttamente il proprio NAS o i suoi servizi al mondo esterno , limitando l'accesso remoto tramite una VPN (WireGuard è un'opzione molto diffusa grazie alle sue prestazioni e alla sua semplicità).

In questo modello, il router funge da gateway: viene aperta solo una porta casuale verso il server VPN e, una volta stabilita la connessione, tutte le richieste ai servizi interni passano attraverso un tunnel crittografato . Né Traefik né le app sono esposte a Internet senza questo filtraggio preliminare.

Chi preferisce non gestire la propria VPN a volte ricorre a Cloudflare Tunnel o Tailscale per accedere al proprio laboratorio domestico senza aprire porte. Si tratta di alternative pratiche, ma se la privacy è la vostra priorità assoluta, dovrete valutare quali metadati potrebbero raccogliere queste terze parti.

Un'altra buona pratica è crittografare i dischi del server e del NAS , applicare regolarmente le patch e limitare gli aggiornamenti automatici (molti evitano Watchtower a favore di aggiornamenti manuali controllati). È meglio essere un po' indietro ma avere il controllo, piuttosto che mandare in tilt metà del proprio Homelab a causa di un aggiornamento non verificato.

Come potete vedere, non è necessario raggiungere un livello "aziendale", ma è consigliabile stabilire un livello minimo di sicurezza e disciplina affinché il vostro homelab non diventi un colabrodo o una fonte costante di preoccupazioni.

In definitiva, configurare un homelab serio con Docker Compose è un mix di organizzazione, buon senso e voglia di sperimentare: se si raggruppano i servizi, si definiscono bene le reti, si documenta tutto con Git e si automatizza un po', si ottiene un ambiente che si può avviare con un singolo comando, migrare facilmente su un'altra macchina ed espandere gradualmente senza che diventi una giungla incontrollabile.