Docker Compose in Homelab: organisatie, profielen en best practices

Laatste update: Mei 24 2026
  • Door Docker Compose te organiseren op basis van profielen en rollen wordt het beheer van thuisnetwerken met tientallen services vereenvoudigd.
  • Door de configuratie te centraliseren in .env-bestanden, gebruik te maken van overrides en versiebeheer toe te passen in Git, wordt de omgeving draagbaar en eenvoudig te migreren.
  • Speciaal daarvoor bestemde netwerken, Traefik en healthchecks verbeteren de veiligheid, isolatie en veerkracht van diensten.
  • Monitoring, gecontroleerde logboeken en geautomatiseerde back-ups maken van het homelab een stabiel platform op de lange termijn.

Docker Compose Homelab

Het opzetten van een modern thuisnetwerk met containers is een geliefde hobby geworden voor veel techneuten. Docker Compose vormt vrijwel altijd de kern van deze setup : definieer je services in YAML, beheer de versies met Git en start je hele omgeving met één commando.

Maar naarmate je bedrijf groeit, verandert er veel: je gaat van twee of drie containers naar tientallen services, interne netwerken, reverse proxies, databases en CI-runners . Dan komt de grote vraag op: één grote Docker Compose-instantie of veel kleine bestanden? Hoe organiseer ik profielen, netwerken, back-ups, beveiliging en hoe zorg ik er bovendien voor dat migratie eenvoudig is?

Praktische methoden voor het opzetten van Docker Compose in een thuisomgeving.

Homelab-configuratie met Docker Compose

In de praktijk werken mensen die Homelabs al een tijdje gebruiken meestal met drie verschillende Compose-organisatiemodellen, elk met zijn eigen voor- en nadelen. De juiste aanpak kiezen bespaart je een hoop problemen bij het opschalen of migreren naar een nieuwe machine.

Aan de ene kant zijn er mensen die begonnen met de losstaande Docker Run-opdrachten, vervolgens overstapten op Portainer en uiteindelijk op Docker Compose . Het is een typisch scenario: Portainer biedt veel inzicht, een gebruiksvriendelijke interface, sjablonen, enzovoort, maar uiteindelijk wordt het bewerken van complexe parameters of het migreren van configuraties een gedoe als je niets in bestanden hebt staan.

Aan het andere uiterste bevindt zich degene die alles heeft samengevoegd in één "mega" docker-compose.yml- bestand dat absoluut alle homelab-services kan draaien: reverse proxy, media, hulpprogramma's, monitoring, LLM's, databases... Alles in één stack.

Daartussenin kiezen veel gebruikers voor een gemengde aanpak: meerdere kleine docker-compose.yml-bestanden gegroepeerd per context (bijv. media, infrastructuur, productiviteit, monitoring), allemaal in dezelfde repository en meestal met gedeelde globale omgevingsvariabelen.

Een tamelijk elegante oplossing combineert beide werelden: een "root" docker-compose die andere bestanden bevat (elk in een submap van apps of services). Op deze manier behoud je een globaal overzicht van je homelab, zonder dat je je hoeft te verdiepen in een YAML-bestand van duizend regels dat onleesbaar is.

Profielen, groepering op functie en grote thuisnetwerken

docker compose homelab profielen

Wanneer je homelab de grens van 30, 40 of 50 services nadert (inclusief back-upservices zoals databases, caches of indexeerders), is het essentieel om orde in deze services te scheppen. Hier komen zowel het groeperen op functie als het gebruik van Docker Compose-profielen van pas.

Een veelvoorkomend patroon is om alles in één Compose-project te groeperen, maar logisch onderverdeeld in profielen. Bijvoorbeeld:

  • Kernprofiel: homelab core, met Traefik als reverse proxy en een identiteitsprovider (bijv. OAuth of Authentik) om alle apps onder hetzelfde domein te authenticeren met HTTPS.
  • MediaprofielDiensten zoals Plex, Sonarr, Radarr, Ombi, SABnzbd of qBittorrent zijn verantwoordelijk voor het samenstellen, downloaden en aanbieden van multimediacontent.
  • NutsbedrijvenprofielTools zoals Portainer, Watchtower (indien gebruikt), Diun, dockcheck of vergelijkbare programma's voor het beheren en bewaken van containers en updates.
  • Infrastructuur-/monitoringprofielTraefik, cAdvisor, Prometheus, Grafana, Uptime Kuma, Dozzle en alles wat te maken heeft met monitoring en logging.
  • Experimentele profielen of LLM: specifieke stacks voor LLM's of bijzondere apps (ChatGPT Next Web lokaal, LibreOffice Online, enz.) die doorgaans standaard zijn uitgeschakeld.

Het mooie van profielen is dat je slechts een deel van de infrastructuur kunt implementeren, afhankelijk van de behoefte. Je kunt bijvoorbeeld alleen het core- en infrastructuurprofiel uitvoeren op een energiezuinige mini-pc en het mediaprofiel alleen implementeren op de grote server met meer schijven en GPU's.

In goed ontworpen repositories is er meestal een "master" docker-compose.yml-bestand in de rootmap dat met behulp van `include` individuele bestanden naar een `apps/` of `services/` map pusht . Bovendien worden bijna alle services geconfigureerd via één globaal `.env`-bestand en worden sommige geheimen opgeslagen in een `secrets/` map , wat de initiële installatie aanzienlijk vereenvoudigt.

Volgens dit patroon komt het beheren van de homelab in principe neer op het bewerken van het .env-bestand en de geheimen, het in- of uitschakelen van profielen en het bepalen welke services op elke host moeten worden gestart . Dit is ideaal als u dezelfde applicaties op meerdere machines wilt implementeren.

Eén enorm docker-compose-bestand versus meerdere kleine bestanden.

Docker Compose Homelab-bestandsstructuur

Dit is de eeuwige discussie: één enkel docker-compose.yml-bestand met alles erin, of meerdere bestanden per service/stack? Het echte antwoord is meestal: "Het hangt ervan af wat je prioriteit geeft: eenvoud van de migratie of duidelijkheid per service."

Voorstanders van één centraal masterbestand wijzen doorgaans op verschillende voordelen:

  • Hosts migreren is heel eenvoudig.Je kloont de repository, kopieert het .env-bestand en de secrets, koppelt de volumes en voert `docker compose up -d` uit. Je hoeft niet map voor map te navigeren.
  • Infrastructuur als waarheidscodeDe volledige topologie van het homelab (services, netwerken, volumes, afhankelijkheden) bevindt zich op één plek.
  • Gecentraliseerde updatesAls je een afbeeldingsversie, een herstartbeleid of een logboekregistratie wijzigt, weet je precies waar je moet aanpassen.
  Beveiliging in besturingssystemen: tips en aanbevelingen

Maar het heeft ook duidelijke nadelen: een enorm YAML-bestand is lastiger te onderhouden, het aantal samenvoegingsconflicten neemt toe en bij het debuggen van een specifiek probleem moet je je een weg banen door een monster van honderden regels. Het is niet ongebruikelijk om een ​​beetje spijt te hebben als alles te groot wordt.

Een andere aanpak is om per app of per logische stack een docker-compose.yml-bestand te hebben , binnen een structuur zoals deze:

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

Hierdoor krijgt elke container een naam zoals bookstack-app-1 of traefik-reverse-proxy-1 , wat helpt om problemen snel te lokaliseren: als de bookstack-app-1-container crasht, weet je precies in welke map je moet zoeken.

Visueel gezien is het veel overzichtelijker en kun je elke service onafhankelijk beheren (starten, stoppen of bijwerken zonder de andere services te beïnvloeden). Bovendien maken applicaties zoals Dozzle gebruik van aparte stacks om logbestanden beter te organiseren.

Het nadeel is dat als je alles te veel scheidt, de coördinatie tussen gemeenschappelijke services (zoals Traefik of gedeelde netwerken) wat meer aandacht vereist : je moet externe netwerken declareren, specifieke Traefik-labels instellen en de naamgeving van netwerken die door andere docker-compose-processen zijn aangemaakt, onthouden.

Aanbevelingen voor het gebruik van .env-bestanden, overrides en versiebeheer.

Een van de meest onderschatte trucs is het centraliseren van configuratie in .env-bestanden . In plaats van je docker-compose.yml te overspoelen met omgevingsvariabelen, definieer je zoiets als dit:

DB_USERNAME=myuser
DB_PASSWORD=secretpassword

En vervolgens worden ze in de YAML-code aangeduid als ${DB_USERNAME} of ${DB_PASSWORD} . Dit maakt Compose in één oogopslag leesbaar, stelt je in staat variabelen te delen tussen meerdere services en, belangrijker nog, slaat wachtwoorden op in een apart bestand (dat je kunt uitsluiten van Git).

Voor verschillende omgevingen (productie, testen, ontwikkeling) is het erg handig om docker-compose.override.yml te gebruiken . Het idee is om een ​​basis docker-compose.yml-bestand te hebben en in de override alleen de wijzigingen aan te passen: poorten, paden, debug-vlaggen, enz.

Tijdens de ontwikkeling kun je bijvoorbeeld een override laden waarmee je een andere poort beschikbaar stelt, debuggen inschakelt en de lokale broncode koppelt . Je raakt het hoofd-YAML-bestand niet aan, maar je past de stack aan de omgeving aan waarin je het uitvoert.

Het is vanzelfsprekend dat versiebeheer met Git verplicht is als je wilt dat je thuisomgeving er ook maar enigszins professioneel uitziet . Je hebt meestal zoiets als dit:

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

Van daaruit initialiseer je de repository, commit je de infrastructuurwijzigingen en als er iets misgaat, kun je binnen enkele seconden terugkeren naar een eerdere versie van je Compose . Voor ambitieuze thuisomgevingen is dit niet zomaar een optie; het is de enige manier om niet gek te worden.

Netwerken, Traefik en beveiligde serviceblootstelling

In vrijwel alle enigszins geavanceerde homelabs zie je dezelfde combinatie: Traefik als reverse proxy en een gecentraliseerde identiteitsprovider (Auth of Authentik) . Dit maakt het mogelijk om meerdere applicaties onder subdomeinen beschikbaar te stellen met HTTPS en SSO.

Een klassieke aanpak is om een ​​speciaal Docker-netwerk op te zetten, zoals reverse_proxy of iets dergelijks, waarop Traefik en alle webservices die je extern wilt aanbieden, zijn aangesloten. De overige containers (databases, caches, enz.) blijven op geïsoleerde interne netwerken.

Als je Traefik gebruikt en je services in verschillende Docker Compose-instanties onderbrengt, moet je een gedeeld extern netwerk definiëren . Zoiets als dit:

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

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

Hier wordt het netwerk traefik_default gecreëerd door de Traefik-stack, en de andere services worden eraan toegevoegd via een extern netwerk genaamd traefik-net. Labels vertellen Traefik welk netwerk te gebruiken voor het routeren van verkeer.

Wanneer een enkele stack backend-services bevat (bijvoorbeeld een webcontainer en de bijbehorende database), kunt u deze verbinden met een gedeeld standaardnetwerk en alleen de webcontainer toegang verlenen tot het Traefik-netwerk . De database krijgt dan het label `traefik.enable=false`, zodat Traefik deze negeert.

Deze configuratie biedt twee belangrijke voordelen: isolatie tussen services en gecontroleerde toegang . Alleen de containers die u labelt met Traefik-labels en die zich op het proxynetwerk bevinden, zijn van buitenaf toegankelijk.

Gegevenspersistentie, volumes en schijfstructuur

Een homelab zonder persistente data is niet erg nuttig: databases, configuraties, media, documenten... alles moet een Docker Compose Down-situatie overleven. Volumes en bind mounts zijn je redding.

  systemd 259: ondersteuning voor musl, beveiliging en belangrijke wijzigingen

Veel mensen organiseren hun opslagruimte volgens een structuur zoals deze:

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

Het idee is dat downloadprogramma's (qBittorrent, SABnzbd, enz.) alleen de downloadmap zien , beheerders zoals Radarr/Sonarr toegang hebben tot zowel downloads als media (om harde links te verplaatsen/aan te maken), en servers zoals Plex of Jellyfin alleen de mediamap zien.

Op deze manier pas je het principe van minimale bevoegdheden toe : elke container heeft alleen toegang tot wat hij daadwerkelijk nodig heeft. De duidelijke scheiding helpt ook bij het bepalen welke volumes of paden naar de cloud of externe schijven moeten worden geback-upt.

De srv-directory wordt doorgaans gebruikt om applicatieconfiguraties op te slaan (bijvoorbeeld /srv/jellyfin/config, /srv/traefik, /srv/paperless, enz.). Deze configuraties worden meestal gedeeltelijk beheerd met versiebeheer (templates, Caddyfile, enz.), waarbij kritieke of resource-intensieve bestanden worden weggelaten.

In sommige gevallen is het handig om harde links in de downloadketen te gebruiken: diensten zoals Radarr of Sonarr kunnen gedownloade bestanden aan elkaar koppelen om het seeden te behouden zonder schijfruimte te dupliceren. De mapstructuur die wordt voorgesteld door handleidingen zoals TRaSHGuides is precies op dit principe gebaseerd.

Implementaties automatiseren met GitHub Actions en lokale runners

Als je nog een stap verder wilt gaan, kun je homelab-updates automatiseren met CI/CD . Verschillende gebruikers hebben Jenkins en vergelijkbare tools vervangen door een workflow met GitHub Actions en een runner die zelf in het homelab draait.

Het mechanisme is eenvoudig: elke keer dat je naar de hoofdbranch van je homelab-repository pusht, wordt een GitHub Actions-workflow gestart die tests en linters uitvoert en, als alles goed gaat, de wijzigingen naar de server implementeert.

Een typische workflow omvat stappen zoals:

  • Gitleaks-achtige geheime scanner: voor het geval je per ongeluk wachtwoorden of tokens naar de repository hebt geüpload.
  • Pluis van YAML of infrastructuurcode, om een ​​leesbaar en consistent formaat te behouden.
  • Het bijwerken van de repository binnen de homelab zelf.: git pull op de doelserver.
  • Gecontroleerde recreatie van containersStop de oude processen, start de nieuwe en controleer de status.

Voordelen: verhoogde beveiliging (u hebt controle over het lekken van geheimen), betere codekwaliteit en herhaalbare implementaties met één enkele push . En omdat u een lokale runner gebruikt, verlaten de images en volumes uw netwerk niet; u gebruikt eenvoudigweg de GitHub-interface om de pipelines te visualiseren.

Waarom Docker Compose het leven in een thuislab zoveel gemakkelijker maakt

Veel mensen hebben jarenlang vertrouwd op Docker Run en Portainer, totdat ze na een incident of een migratie gedwongen werden hun aanpak te herzien. Wanneer je een host verliest of services naar een andere machine moet verplaatsen, is het een valkuil om uitsluitend te vertrouwen op geïsoleerde commando's of configuraties binnen Portainer.

Het grote verschil bij de overstap naar Compose is dat de volledige servicedefinitie tekst wordt : volumes, poorten, netwerken, labels, variabelen... Alles in een YAML-bestand dat je kunt kopiëren, delen, versiebeheer toepassen en hergebruiken.

Het bewerken van een service is niet langer een kwestie van "een container handmatig opnieuw opbouwen"; het gaat nu om het wijzigen van een regel in een bestand, opslaan en het uitvoeren van `docker compose up -d` . Je hoeft het oorspronkelijke commando niet te onthouden of door meerdere Portainer-schermen te klikken.

Bovendien is het, als u met meerdere servers werkt (mini-pc's, NAS, desktops), uiterst handig om hetzelfde Compose-bestand naar een andere machine te kopiëren, vier paden aan te passen en dezelfde stack op verschillende hardware uit te voeren . Sterker nog, veel mensen erkennen dat Compose hen, na een angstige ervaring met dataverlies of chaotische migraties, veel tijd heeft bespaard bij latere incidenten.

Als bijkomend voordeel wordt het bouwen van nieuwe services op basis van bestaande services kinderspel: het klonen van de Plex-configuratie om Jellyfin in te stellen door dezelfde mediapaden en transcoderingsapparaten te hergebruiken, duurt bijvoorbeeld slechts een paar minuten als je dit doet door YAML-blokken te kopiëren.

Optimalisatie: bouwcontext, meerfasige builds en resources

Hoewel veel Homelab-containers afkomstig zijn van openbare images, compileert u in sommige gevallen uw eigen image. In deze gevallen is het belangrijk om uw buildcontext te beheren : upload niet de volledige repository zonder filter, maar beperk uzelf tot uw projectmap (met behulp van een sterke `.dockerignore`-richtlijn) om snelle en lichtgewicht builds te garanderen.

Een andere zeer nuttige techniek is het gebruik van multistage builds in je Dockerfiles: in de eerste fase installeer je de afhankelijkheden en compileer je, en in de tweede fase kopieer je alleen de benodigde artefacten naar een kleine basisimage. Het resultaat: veel kleinere en veiligere uiteindelijke images , omdat ze geen onnodige toolchains of libraries bevatten.

  Multicore CPU-architectuur en multiprocessorsystemen

Aan de Compose-kant heb je de mogelijkheid om CPU- en RAM-limieten te definiëren (vooral in Swarm-omgevingen of wanneer Docker deze parameters respecteert) om te voorkomen dat resource-intensieve applicaties alle resources opslokken. In Homelabs helpt dit voorkomen dat een verkeerd geconfigureerde service de rest van het systeem lamlegt.

Vergeet de herstartbeleidsregels niet (herstarten: altijd, tenzij gestopt, bij storing): hiermee zorgt u ervoor dat kritieke services (reverse proxy, VPN, belangrijke databases) automatisch opnieuw opstarten na een herstart of een eenmalige storing.

Tot slot is het raadzaam om periodiek opschoontaken in te plannen met commando's zoals `docker image prune`, `docker container prune` en `docker volume prune` om restanten van oude builds, gestopte containers of achtergebleven volumes te verwijderen en zo schijfruimte vrij te maken.

Gezondheidszorg, registratie en monitoring

Om te voorkomen dat je thuisnetwerk een black box wordt, is het belangrijk om aan drie belangrijke aspecten te werken: healthchecks, gecontroleerde logging en monitoring . Docker Compose stelt je in staat om per service healthchecks te definiëren (met behulp van commando's zoals `curl -f http://localhost` of specifieke scripts) die bepalen of een container gezond is.

Dit zorgt ervoor dat alleen "gezonde" containers verkeer ontvangen (bijvoorbeeld via Traefik) en dat ze, als ze niet meer reageren, opnieuw worden opgestart volgens het geconfigureerde beleid. Dit verhoogt de veerkracht aanzienlijk met minimale inspanning.

Wat betreft logbestanden: het aanpassen van de JSON-bestandsdriver met limieten voor maximale grootte en maximale bestandsgrootte voorkomt dat de schijf vol raakt met gigabytes aan vergeten logbestanden. Webtools zoals Dozzle helpen je om de logbestanden van alle containers vanuit een browser te bekijken, wat erg handig is voor het debuggen van specifieke services.

Voor het verzamelen van statistieken en continue monitoring is de klassieke combinatie cAdvisor + Prometheus + Grafana . cAdvisor toont statistieken over CPU-, geheugen-, schijf- en netwerkgebruik per container; Prometheus verzamelt deze periodiek en Grafana visualiseert ze in aantrekkelijke dashboards, met waarschuwingen als er iets plotseling oploopt.

Een goed ingericht thuislab omvat doorgaans Uptime Kuma voor beschikbaarheidscontroles (HTTP, ICMP, TCP, enz.) en een geautomatiseerd back-upsysteem zoals Duplicati om belangrijke gegevens naar andere schijven of de cloud te kopiëren. Zo weet u wat er gebeurt en raakt u uw belangrijke gegevens niet kwijt als er iets misgaat.

Beveiliging en toegang op afstand tot het thuislab

Hoe je de installatie ook zelf uitvoert, beveiliging is niet optioneel. Veel mensen kiezen ervoor om hun NAS of de bijbehorende services niet direct aan de buitenwereld bloot te stellen en beperken de toegang op afstand via een VPN (WireGuard is een zeer populaire optie vanwege de prestaties en eenvoud).

In dit model fungeert de router als gateway: er wordt slechts een willekeurige poort geopend naar de VPN-server, en zodra de verbinding tot stand is gebracht, gaan alle verzoeken aan interne services via een versleutelde tunnel . Noch Traefik, noch de apps worden zonder deze voorafgaande filtering blootgesteld aan het internet.

Wie liever geen eigen VPN beheert, maakt soms gebruik van Cloudflare Tunnel of Tailscale om toegang te krijgen tot zijn thuisnetwerk zonder poorten te hoeven openen. Dit zijn handige alternatieven, maar als privacy uw hoogste prioriteit is, moet u wel overwegen welke metadata deze derde partijen mogelijk verzamelen.

Een andere goede gewoonte is om de server- en NAS-schijven te versleutelen , regelmatig patches toe te passen en automatische updates te beperken (veel mensen vermijden Watchtower en geven de voorkeur aan gecontroleerde handmatige updates). Het is beter om iets achter te lopen, maar wel de controle te behouden, dan de helft van je thuisnetwerk plat te leggen vanwege een update die je niet hebt gecontroleerd.

Zoals je ziet, hoef je geen "bedrijfsniveau" te bereiken, maar het is wel raadzaam om een ​​minimaal beveiligingsniveau en discipline te hanteren, zodat je thuisnetwerk geen zeef wordt of een constante bron van angst vormt.

Uiteindelijk is het opzetten van een serieuze thuisomgeving met Docker Compose een combinatie van organisatie, gezond verstand en de bereidheid om te experimenteren: als je services groepeert, de netwerken goed definieert, documenteert in Git en een beetje automatiseert, krijg je een omgeving die je met één commando kunt starten, gemakkelijk naar een andere machine kunt migreren en beetje bij beetje kunt uitbreiden zonder dat het een onbeheersbare jungle wordt.