Docker Compose als Linux-service met systemd uitvoeren
Docker Compose bij het opstarten, beheerd door systemd.
Docker Compose op een Linux-server moet bij het opstarten starten, tijdens het afsluiten netjes stoppen en herstarts overleven zonder handmatige ingrepen.
Docker Compose is geen Kubernetes, en dat is prima voor de werklasten die deze gids behandelt. Voor veel echte systemen is een Compose-project op een enkele Linux-host de juiste hoeveelheid infrastructuur: simpel, leesbaar, makkelijk te back-uppen en goed genoeg voor interne tools, bijprojecten, self-hosted services, staging-omgevingen, kleine productie-apps en ontwikkelaarsinfrastructuur.

Het ontbrekende stuk is meestal servicemanagement. Dit handmatig uitvoeren is niet genoeg:
docker compose up -d
Een enkel commando start de stack, maar het documenteert niet hoe de stack bij het opstarten moet starten, tijdens het afsluiten moet stoppen, na wijzigingen moet herladen, logs moet schrijven, zich moet herstellen na fouten of veilig geüpdatet kan worden. Daar helpt systemd bij.
Deze gids behandelt het uitvoeren van een Docker Compose-project als een Linux-service met systemd — unit-bestanden, startvolgorde, updates, logs en back-ups. De verdeling van verantwoordelijkheden is bewust: Docker draait containers, Compose definieert de stack en systemd start en stopt het project op de host. Het maakt deel uit van Developer Tools - een gids voor ontwikkelingsworkflows.
Wanneer Docker Compose als service zinvol is
Het uitvoeren van Compose onder systemd is zinvol wanneer je:
- Een enkele Linux-server hebt
- Een kleine self-hosted applicatie hebt
- Een reverse proxy-stack hebt
- Een monitoring-stack hebt
- Een lokaal ontwikkelingsplatform hebt
- Een intern hulpmiddel hebt
- Een staging-omgeving hebt
- Een eenvoudige productieservice met bekende beperkingen hebt
Voorbeelden:
- Nginx Proxy Manager
- Traefik
- Gitea
- Grafana en Prometheus
- PostgreSQL plus een kleine webapp
- Uptime Kuma
- Home Assistant-hulpservices
- Private registry
- Interne API plus worker plus Redis
Compose is een goede keuze wanneer het operationele model nog begrijpelijk is voor één persoon die één map leest.
Wanneer Docker Compose niet genoeg is
Gebruik iets anders wanneer je nodig hebt:
- Scheduling over meerdere knooppunten
- Automische herscheduling over hosts heen
- Service discovery op clusterniveau
- Horizontale autoscaling
- Rolling deployments over veel machines
- Fijngegranuleerde workload-identiteit
- Complexe netwerkbeleid
- Grote platformoperaties voor meerdere teams
Op dat punt kunnen Kubernetes, Nomad, Swarm of een beheerd platform een betere keuze zijn.
Mijn praktische regel is om Kubernetes te vermijden alleen om systemd niet te hoeven leren, en om Compose te vermijden wanneer de werklast duidelijk orchestration over meerdere hosts nodig heeft.
De basisarchitectuur
Een schone opstelling scheidt projectbestanden, de systemd-unit en persistente data op de host. Het Compose-project zit onder /opt/myapp/ met compose.yaml, .env, data/, backups/ en optionele scripts zoals scripts/update.sh. Het systemd-unit-bestand staat op /etc/systemd/system/myapp.service.
Elke laag heeft een duidelijke taak: Docker draait containers, Compose definieert de applicatiestack, systemd start en stopt het Compose-project bij het opstarten en afsluiten, het host-bestandssysteem bewaart persistente data, back-ups blijven expliciet en updates gaan door gescriptte, reviewbare stappen. Deze indeling is bewust saai, want saaie infrastructuur is makkelijker te repareren als er iets om 2 uur ’s nachts kapotgaat.
Bereid de Compose-projectmap voor
Maak een map aan onder /opt:
sudo mkdir -p /opt/myapp
sudo chown -R "$USER":"$USER" /opt/myapp
cd /opt/myapp
Maak een Compose-bestand:
nano compose.yaml
Voorbeeld:
services:
web:
image: nginx:stable
restart: unless-stopped
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
healthcheck:
test: ["CMD-SHELL", "nginx -t || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 10s
volumes: {}
Maak de contentmap aan:
mkdir -p html
echo "Hello from Docker Compose" > html/index.html
Test eerst handmatig:
docker compose up -d
docker compose ps
docker compose logs --tail=50
Stop het dan voordat je de levenscyclus overdraagt aan systemd:
docker compose down
Maak geen systemd-service totdat het Compose-project handmatig werkt. Terwijl je test, houd de Docker Compose Cheatsheet in de buurt voor ps, logs, pull en projectstructuur.
Gebruik het moderne docker compose-commando
Docker Engine en de Compose-plugin moeten geïnstalleerd zijn voordat je een unit-bestand schrijft. Op Ubuntu, Install Docker on Ubuntu behandelt APT, Snap, rootless mode en post-install beveiliging zodat je eindigt met een werkend docker compose-commando.
Gebruik dit:
docker compose version
Niet dit:
docker-compose version
Het oude docker-compose-binary bestaat nog op veel machines, maar modern Docker gebruikt Compose als Docker CLI-plugin.
In servicebestanden en scripts, geef de voorkeur aan:
/usr/bin/docker compose
Je kunt het Docker-pad vinden met:
command -v docker
Meestal is het:
/usr/bin/docker
Maak een systemd-service voor Docker Compose
Als unit-bestanden nieuw voor je zijn, Run any Executable as a Service in Linux legt Type, ExecStart, systemctl en de algemene systemd-workflow uit. Deze sectie past die patronen specifiek toe op een Compose-stack.
Maak het servicebestand:
sudo nano /etc/systemd/system/myapp.service
Gebruik deze unit:
[Unit]
Description=MyApp Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Laad systemd opnieuw:
sudo systemctl daemon-reload
Start de service:
sudo systemctl start myapp.service
Schakel het in bij het opstarten:
sudo systemctl enable myapp.service
Controleer de status:
systemctl status myapp.service
Controleer containers:
cd /opt/myapp
docker compose ps
Waarom Type=oneshot en RemainAfterExit=yes?
Dit is het deel dat veel gidsen subtiel verkeerd krijgen.
docker compose up -d start containers in detached mode en eindigt, dus er is geen langlopend foreground Compose-proces voor systemd om te superviseren. De systemd-unit zou niet moeten doen alsof docker compose up -d een langlopend daemon is.
Gebruik:
Type=oneshot
RemainAfterExit=yes
Dit vertelt systemd:
- Voer het startcommando uit.
- Beschouw de unit als actief nadat het commando succesvol is afgerond.
- Voer
ExecStopuit wanneer de service wordt gestopt.
Dit komt overeen met het werkelijke gedrag van detached Compose, waardoor Type=oneshot met RemainAfterExit=yes de juiste standaard is voor de meeste stacks.
Waarom niet Type=simple?
Met Type=simple verwacht systemd dat het ExecStart-proces blijft lopen, maar docker compose up -d eindigt na het starten van containers. Dat kan er voor zorgen dat systemd denkt dat de service is beëindigd, vervolgens de stop-logiek aanroept of de unit als inactief markeert, afhankelijk van de configuratie.
Als je Type=simple wilt, zou je meestal Compose in de foreground draaien:
ExecStart=/usr/bin/docker compose up
Dat kan werken, maar ik heb daar meestal geen voorkeur voor bij Compose-stacks op servers. Detached containers plus expliciete ExecStop zijn makkelijker te bedienen.
Een meer productie-vriendelijke unit
Voor een echte server geef ik de voorkeur aan een iets strengere unit:
[Unit]
Description=MyApp Docker Compose stack
Documentation=https://example.com/docs/myapp
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
EnvironmentFile=-/opt/myapp/.env.systemd
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Belangrijke details:
WorkingDirectoryverwijst naar het Compose-project.ExecStartPrevalideert de Compose-configuratie.ExecReloadhermaakt gewijzigde services.ExecStopstopt en verwijdert de Compose-projectcontainers en het standaardnetwerk.EnvironmentFile=-...betekent dat het bestand optioneel is.
Maak het optionele systemd-omgevingsbestand:
nano /opt/myapp/.env.systemd
Voorbeeld:
COMPOSE_PROJECT_NAME=myapp
Laad dan systemd opnieuw:
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Compose .env vs systemd EnvironmentFile
Compose en systemd hebben elk hun eigen omgevingsmechanisme, en het mengen ervan veroorzaakt verwarrende “variabele niet ingesteld”-fouten bij het opstarten.
Compose leest automatisch een .env-bestand in de projectmap voor variabele substitutie in het Compose-bestand.
Voorbeeld .env:
APP_TAG=1.2.3
WEB_PORT=8080
Voorbeeld compose.yaml:
services:
web:
image: nginx:${APP_TAG}
ports:
- "${WEB_PORT}:80"
Een systemd EnvironmentFile stelt omgevingsvariabelen in voor het docker compose-commando zelf.
Voorbeeld:
EnvironmentFile=-/opt/myapp/.env.systemd
Voor veel projecten heb je alleen Compose .env nodig.
Gebruik een systemd-omgevingsbestand wanneer je dingen wilt definiëren zoals:
COMPOSE_PROJECT_NAME=myapp
COMPOSE_FILE=compose.yaml
DOCKER_HOST=unix:///var/run/docker.sock
Gebruik geen van beide bestanden als een casual secrets-vault. Als secrets belangrijk zijn, gebruik dan Docker secrets, een externe secret manager, gecrypteerde bestanden of in ieder geval strikte permissies.
Stel restrictieve permissies in:
chmod 600 /opt/myapp/.env
chmod 600 /opt/myapp/.env.systemd
Herstartbeleid: Docker vs systemd
Er zijn twee herstartlagen — het containerherstartbeleid in Compose en het systemd-serviceherstartbeleid — en ze mogen niet blindeling worden gemengd.
Voor langlopende containers, stel herstartbeleiden in Compose:
services:
web:
image: nginx:stable
restart: unless-stopped
Vevoorkomen herstartwaarden:
| Policy | Meaning |
|---|---|
| no | Niet automatisch herstarten |
| always | Herstarten na exit en daemon restart |
| on-failure | Alleen herstarten na falen |
| unless-stopped | Herstarten tenzij handmatig gestopt |
Voor de meeste persistente services geef ik de voorkeur aan:
restart: unless-stopped
Het is voorspelbaar en respecteert intentionele handmatige stops.
De systemd-unit zelf zou meestal niet herhaaldelijk moeten herstarten, omdat docker compose up -d niet de lopende werklast is. De containers zijn dat.
Vermijd dit dus tenzij je een specifieke reden hebt:
Restart=always
In de meeste Compose-as-service-units, laat Docker het containerherstart afhandelen.
Health Checks
Herstartbeleiden herstarten containers wanneer processen eindigen. Ze lossen niet magisch elke ongezonde applicatie op.
Voeg health checks toe waar ze nuttig zijn:
services:
app:
image: example/app:latest
restart: unless-stopped
healthcheck:
test: ["CMD-SHELL", "curl -fsS http://localhost:8080/health || exit 1"]
interval: 30s
timeout: 5s
retries: 3
start_period: 20s
Controleer de gezondheid:
docker compose ps
Inspecteer een container:
docker inspect container-name
Health checks zijn vooral nuttig voor:
- Webapps
- Reverse proxies
- Databases
- Queues
- Interne API’s
- Workers met een health-endpoint
Ze zijn minder nuttig wanneer ze alleen controleren of een proces bestaat, omdat een proces dat leeft maar vastzit er nog steeds gezond uitziet. Een slechte health check is slechts een andere leugen in YAML.
Startvolgorde en depends_on
Compose kan afhankelijkheden definiëren:
services:
app:
image: example/app:latest
depends_on:
db:
condition: service_healthy
db:
image: postgres:16
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
Dit kan helpen bij de startvolgorde, maar vertrouw er niet te veel op. Applicaties moeten nog steeds retries afhandelen — databases herstarten, netwerken flakkeren, DNS kost tijd, en een resiliente app probeert verbindingen opnieuw in plaats van uit te gaan van een perfecte startvolgorde.
Logs: journalctl en docker compose logs
Twee logweergaven dekken het meeste debuggen: systemd vangt de levenscyclus van de unit zelf, terwijl Compose applicatie-output vangt van lopende containers.
systemd-service logs:
journalctl -u myapp.service -n 100 --no-pager
Volg systemd-logs:
journalctl -u myapp.service -f
Compose-service logs:
cd /opt/myapp
docker compose logs --tail=100
docker compose logs -f
docker compose logs -f web
Voor de meeste app-debuggen is docker compose logs nuttiger; voor levenscyclus-debuggen — startfouten, unit-crashes, permissiefouten — is journalctl nuttiger. Als systemctl start myapp faalt, controleer dan eerst journalctl. Als de stack start maar de app kapot is, controleer dan docker compose logs.
Log Rotatie
Docker-logs kunnen voor altijd groeien als je ze niet configureert.
Voor kleine servers, configureer Docker-logrotatie in /etc/docker/daemon.json:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "5"
}
}
Herstart Docker:
sudo systemctl restart docker
Herstart dan de Compose-stack:
sudo systemctl restart myapp.service
Dit geldt voor nieuw gemaakte containers. Hermaak containers indien nodig:
cd /opt/myapp
docker compose up -d --force-recreate
Logrotatie is niet glamoureus, maar het is een van de makkelijkste manieren om een disk-full outage op een kleine server te voorkomen.
Een Compose-service updaten
Een eenvoudige handmatige update-flow:
cd /opt/myapp
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
Als beheerd door systemd, kun je gebruiken:
sudo systemctl reload myapp.service
Als je unit heeft:
ExecReload=/usr/bin/docker compose up -d --remove-orphans
Maar let op: ExecReload haalt geen images tenzij je die stap included.
Voor expliciete updates, maak een script.
mkdir -p /opt/myapp/scripts
nano /opt/myapp/scripts/update.sh
Script:
#!/usr/bin/env bash
set -euo pipefail
cd /opt/myapp
docker compose config --quiet
docker compose pull
docker compose up -d --remove-orphans
docker image prune -f
docker compose ps
Maak het uitvoerbaar:
chmod +x /opt/myapp/scripts/update.sh
Voer het uit:
/opt/myapp/scripts/update.sh
Dan kan de service-unit gericht blijven op levenscyclus, terwijl het update-script de deployment afhandelt.
Veiligere updatescript met backup-hook
Voor stateful services, update alleen na backup.
#!/usr/bin/env bash
set -euo pipefail
APP_DIR="/opt/myapp"
BACKUP_DIR="/opt/myapp/backups"
cd "$APP_DIR"
mkdir -p "$BACKUP_DIR"
echo "Validating compose file"
docker compose config --quiet
echo "Running backup hook"
if [ -x "$APP_DIR/scripts/backup.sh" ]; then
"$APP_DIR/scripts/backup.sh"
else
echo "No backup hook found"
fi
echo "Pulling images"
docker compose pull
echo "Recreating services"
docker compose up -d --remove-orphans
echo "Pruning unused images"
docker image prune -f
echo "Current status"
docker compose ps
Dit is nog steeds simpel, maar het codeert nu een operationele gewoonte: backup voor verandering.
De service stoppen
Stop de stack:
sudo systemctl stop myapp.service
Dat voert uit:
docker compose down
Standaard verwijdert docker compose down:
- Containers voor services in het Compose-bestand
- Netwerken gedefinieerd door het Compose-bestand
- Het standaardnetwerk
Het verwijdert geen benoemde volumes tenzij je het vraagt.
Gebruik niet casual:
docker compose down -v
Dat verwijdert benoemde volumes gedeclareerd in het Compose-bestand en anonieme volumes gekoppeld aan containers. Voor databases en stateful apps kan dat betekenen dat echte data wordt verwijderd.
Gebruik down -v alleen wanneer je “vernietig deze omgeving” bedoelt.
De service herstarten
Herstart de systemd-unit:
sudo systemctl restart myapp.service
Dit voert het stopcommando uit en dan het startcommando.
Voor alleen het herstarten van containers zonder ze te hermaken:
cd /opt/myapp
docker compose restart
Belangrijk onderscheid:
docker compose restartherstart bestaande containers.docker compose up -dpast config- of imagewijzigingen toe door containers te hermaken wanneer nodig.
Als je compose.yaml hebt gewijzigd, gebruik:
docker compose up -d
Niet alleen:
docker compose restart
Orphan-containers afhandelen
Als je een service in compose.yaml hernoemt of verwijdert, kunnen oude containers achterblijven als orphans.
Gebruik:
docker compose up -d --remove-orphans
Daarom gebruiken de systemd-servicevoorbeelden in deze gids:
ExecStart=/usr/bin/docker compose up -d --remove-orphans
Het houdt de stack dichter bij het huidige Compose-bestand.
Back-ups
Back-ups hangen af van de werklast, maar de principes zijn stabiel.
Voor bind mounts:
/opt/myapp/data/
Back-up die map.
Voor benoemde volumes:
docker volume ls
Inspecteer een volume:
docker volume inspect volume-name
Voor databases zijn bestandssysteemkopieën niet altijd genoeg. Gebruik application-aware back-ups:
PostgreSQL-voorbeeld:
docker compose exec -T db pg_dump -U postgres appdb > backups/appdb.sql
MariaDB-voorbeeld:
docker compose exec -T db mariadb-dump -u root -p appdb > backups/appdb.sql
Redis-voorbeeld:
docker compose exec redis redis-cli BGSAVE
Een Compose-stack zonder een backupplan is geen service — het is een tijdelijk experiment dat toevallig uptime heeft.
Beveiligingsbaseline
Voor een kleine Compose-service op Linux, begin met deze baseline:
- Houd het Compose-project onder
/opt/appname. - Gebruik expliciete imagetags, niet alleen
latest, wanneer stabiliteit belangrijk is. - Gebruik bind mounts of benoemde volumes bewust.
- Publiceer geen poorten die je niet nodig hebt.
- Zet publieke services achter een reverse proxy.
- Gebruik HTTPS aan de edge.
- Houd secrets buiten Git.
- Beperk
.env-permissies. - Vermijd privileged containers tenzij echt nodig.
- Vermijd het mounten van de Docker-socket in containers.
- Houd Docker en images up-to-date.
- Test firewallgedrag vanaf een andere machine.
Een gevaarlijk patroon:
volumes:
- /var/run/docker.sock:/var/run/docker.sock
Dit geeft de container controle over Docker. In de praktijk kan dat host-level controle worden. Gebruik het alleen wanneer je het risico begrijpt.
Resource Limits
Op kleine servers kan één slechte container de host consumeren.
Compose ondersteunt resource-gerelateerde instellingen, maar gedrag kan afhangen van Docker Engine en Compose-versie. Voor eenvoudige bescherming, begin met applicatie-level limits en Docker logging limits.
Voor sommige werklasten kun je memory limits toevoegen:
services:
app:
image: example/app:stable
restart: unless-stopped
mem_limit: 512m
Configureer ook app-level worker counts, queue limits en cache sizes. Container limits zijn nuttig, maar ze zijn geen vervanging voor het begrijpen van de applicatie.
Voorbeeld: Een realistische Compose-service
Map:
/opt/whoami/
compose.yaml
.env
Compose-bestand:
services:
whoami:
image: traefik/whoami:v1.10
restart: unless-stopped
ports:
- "${WHOAMI_PORT}:80"
healthcheck:
test: ["CMD-SHELL", "wget -qO- http://localhost || exit 1"]
interval: 30s
timeout: 5s
retries: 3
.env-bestand:
WHOAMI_PORT=8080
COMPOSE_PROJECT_NAME=whoami
systemd-unit:
[Unit]
Description=Whoami Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/whoami
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Installeer het:
sudo systemctl daemon-reload
sudo systemctl enable --now whoami.service
Test:
curl http://localhost:8080
Controleer status:
systemctl status whoami.service
cd /opt/whoami
docker compose ps
Probleemoplossing
Service start maar containers draaien niet
Controleer systemd:
journalctl -u myapp.service -n 100 --no-pager
Valideer Compose:
cd /opt/myapp
docker compose config
Controleer Docker:
systemctl status docker
docker info
WorkingDirectory is verkeerd
Als systemd je Compose-bestand niet kan vinden, bevestig:
WorkingDirectory=/opt/myapp
Controleer dan:
ls -la /opt/myapp
ls -la /opt/myapp/compose.yaml
De service draait vanaf WorkingDirectory, niet vanaf je huidige shell-directory.
Docker Permission Denied
Als de unit als root draait, kan het normaal Docker toegang krijgen.
Als je User=someuser instelt, moet die gebruiker toegang tot Docker hebben. Meestal betekent dat lidmaatschap van de docker-groep, of een rootless Docker-opstelling.
Controleer:
groups someuser
Voeg de gebruiker toe indien gepast:
sudo usermod -aG docker someuser
Wees voorzichtig. De Docker-groep is effectief privileged.
Compose-commando niet gevonden
Vind Docker:
command -v docker
Gebruik het volledige pad in de unit:
ExecStart=/usr/bin/docker compose up -d --remove-orphans
Als Compose-plugin ontbreekt:
docker compose version
Installeer het met je Docker-pakketbron.
Omgevingsvariabelen ontbreken
Controleer de Compose-configuratie zoals systemd het zou zien:
cd /opt/myapp
docker compose config
Als systemd extra omgevingsvariabelen nodig heeft, gebruik:
EnvironmentFile=-/opt/myapp/.env.systemd
Als Compose variabelen nodig heeft voor substitutie, gebruik:
/opt/myapp/.env
Deze zijn gerelateerd, maar niet identiek.
Containers starten niet na reboot
Controleer of de systemd-service is ingeschakeld:
systemctl is-enabled myapp.service
Schakel het in:
sudo systemctl enable myapp.service
Controleer Docker:
systemctl is-enabled docker
systemctl status docker
Controleer boot-logs:
journalctl -u myapp.service -b --no-pager
App start voordat database klaar is
Voeg een database health check en depends_on met service_healthy toe.
Fix ook de applicatie. Het zou databaseverbindingen moeten proberen opnieuw. Infrastructuurstartvolgorde is nuttig, maar applicatie-herhaallogica is beter.
Disk gevuld met Docker-logs
Controleer Docker-schijmgebruik:
docker system df
Controleer grote container-logs:
sudo du -h /var/lib/docker/containers | sort -h | tail
Configureer Docker-logrotatie in /etc/docker/daemon.json.
Herstel dan containers.
Veelgemaakte fouten
Fout 1: docker compose up uitvoeren in rc.local
Het uitvoeren van docker compose up vanuit rc.local of een login-script werkt totdat het niet werkt — gebruik een juiste systemd-unit in plaats daarvan.
Fout 2: Gebruik van Restart=always in systemd en restart: always in Compose
Meestal heb je alleen containerherstartbeleiden in Compose nodig. Vermijd dat twee supervisors elkaar bevechten.
Fout 3: Vergeten –remove-orphans
Servicernamen en -verwijderingen kunnen oude containers achterlaten. Gebruik:
docker compose up -d --remove-orphans
Fout 4: Gebruik van docker compose restart na config-wijzigingen
restart herstart containers. Het past niet alle configuratiewijzigingen toe.
Gebruik:
docker compose up -d
Fout 5: Uitvoeren van down -v zonder na te denken
Dit kan volumes verwijderen. Voor stateful services kan dat betekenen dat data wordt verwijderd.
Fout 6: Geen backup voor pull
Nieuwe images kunnen breken. Databases kunnen migreren. Tags kunnen bewegen. Back-up eerst.
Fout 7: Elke poort publiceren
Publiceer alleen wat de host nodig heeft om bloot te stellen. Intern service-naar-service-verkeer kan op het Compose-netwerk blijven.
Eind aanbevolen patroon
Voor de meeste single-host Linux-services, gebruik dit patroon:
Compose-bestand:
services:
app:
image: example/app:stable
restart: unless-stopped
ports:
- "8080:8080"
env_file:
- .env
systemd-unit:
[Unit]
Description=MyApp Docker Compose stack
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target
[Service]
Type=oneshot
RemainAfterExit=yes
WorkingDirectory=/opt/myapp
ExecStartPre=/usr/bin/docker compose config --quiet
ExecStart=/usr/bin/docker compose up -d --remove-orphans
ExecReload=/usr/bin/docker compose up -d --remove-orphans
ExecStop=/usr/bin/docker compose down
TimeoutStartSec=0
TimeoutStopSec=120
[Install]
WantedBy=multi-user.target
Schakel het in:
sudo systemctl daemon-reload
sudo systemctl enable --now myapp.service
Bedien het:
sudo systemctl status myapp.service
sudo systemctl restart myapp.service
journalctl -u myapp.service -f
cd /opt/myapp && docker compose logs -f
Dit patroon is niet fancy, en dat is het punt. Docker Compose is uitstekend voor kleine, begrijpelijke systemen, systemd is uitstekend in het starten en stoppen van host-services, en samen geven ze je een betrouwbaar single-server deploymentmodel zonder te doen alsof elk project een cluster nodig heeft. Voor container-level commando’s buiten Compose — images, volumes, netwerken en opschoning — zie de Docker Cheatsheet.