Als docker-compose up faalt: systematisch veelvoorkomende fouten oplossen
Wanneer docker-compose up faalt, voelt het vaak alsof je in één keer met netwerken, DNS, volumes, permissies, images, build-caches en applicatieconfig tegelijk moet vechten. De snelste manier om dit beheersbaar te maken is systematisch werken: eerst vaststellen waar het faalt (Compose zelf, Docker Engine, netwerk, image build, container runtime, applicatie), daarna gericht meten, en pas dan wijzigen.
Deze tutorial geeft een praktische, diepgaande aanpak met echte commando’s, inclusief veelvoorkomende foutmeldingen en hoe je ze oplost.
Inhoud
- Vooraf: Compose v1 vs v2 en wat je precies draait
- Een herhaalbare diagnose-workflow
- Stap 1 — Is Docker Engine bereikbaar?
- Stap 2 — Valideer je Compose-config
- Stap 3 — Logs: het verschil tussen Compose-fouten en container-fouten
- Stap 4 — Build-problemen (Dockerfile, context, cache, platform)
- Stap 5 — Poorten en netwerkconflicten
- Stap 6 — Volumes, bind mounts en permissies
- Stap 7 — DNS, service discovery en “depends_on” misverstanden
- Stap 8 — Omgevingsvariabelen,
.enven secrets - Stap 9 — Healthchecks en startvolgorde
- Stap 10 — Resourceproblemen (disk, memory, ulimits)
- Stap 11 — Opruimen en “resetten” zonder data te verliezen
- Cheatsheet: snelle commando’s per symptoom
Vooraf: Compose v1 vs v2 en wat je precies draait
Tegenwoordig is Compose meestal v2 (plugin) en roep je het aan als:
docker compose up
Oudere setups gebruiken v1:
docker-compose up
De foutoplossing is grotendeels gelijk, maar sommige flags/uitvoer verschillen. Check je versies:
docker version
docker compose version
docker-compose version 2>/dev/null || true
Belangrijk: als je documentatie volgt, vervang dan consistent docker-compose door docker compose als je v2 gebruikt.
Een herhaalbare diagnose-workflow
Gebruik deze volgorde. Het voorkomt “random fixes”:
- Reproduceer het probleem met maximale signalen (logs, exit codes).
- Classificeer: faalt het bij config parsing, build, pull, network create, container start, of applicatie runtime?
- Observeer: inspecteer containers, events, logs, mounts, netwerken.
- Minimaliseer: start één service, of start zonder build, of zonder volumes.
- Fix één oorzaak tegelijk, en valideer.
Een goede start:
# Start in de voorgrond om direct te zien waar het misgaat
docker compose up
# Of: bouw expliciet en start daarna
docker compose build --no-cache
docker compose up
Als het te veel output is, pak alleen de laatste regels:
docker compose up 2>&1 | tail -n 200
Stap 1 — Is Docker Engine bereikbaar?
Veel “Compose errors” zijn eigenlijk Docker-daemon problemen.
Symptomen
Cannot connect to the Docker daemonerror during connect: ...permission denied while trying to connect to the Docker daemon socket
Diagnose
docker info
Als dit al faalt, heeft Compose geen kans.
Op Linux: check of de daemon draait:
sudo systemctl status docker
sudo journalctl -u docker -n 200 --no-pager
Check socket permissies:
ls -l /var/run/docker.sock
id
groups
Oplossingen
- Start/enable Docker:
sudo systemctl start docker
sudo systemctl enable docker
- Voeg je gebruiker toe aan de
docker-groep (let op: security-implicaties; docker-groep is praktisch root):
sudo usermod -aG docker "$USER"
newgrp docker
docker info
- Als je via SSH werkt: controleer
DOCKER_HOST:
echo "$DOCKER_HOST"
unset DOCKER_HOST
Stap 2 — Valideer je Compose-config
Veel fouten ontstaan door een verkeerd bestand, een typfout in een sleutel, of een .env die anders werkt dan je denkt.
Gebruik config om de “samengevoegde waarheid” te zien
docker compose config
Dit commando:
- valideert syntax,
- resolveert variabelen,
- merge’t overrides (zoals
docker-compose.override.ymlindien aanwezig), - toont het uiteindelijke resultaat.
Wil je ook zien waar variabelen vandaan komen:
docker compose config --environment
Veelvoorkomende config-fouten
1) Verkeerde bestandsnaam of verkeerde map
Compose zoekt standaard naar compose.yml, compose.yaml, docker-compose.yml, docker-compose.yaml.
Check:
ls -la
pwd
Specificeer expliciet:
docker compose -f docker-compose.yml up
2) Variabelen niet gezet → lege strings
Als je image: myapp:${TAG} gebruikt en TAG is leeg, krijg je rare pull/build errors.
Check:
docker compose config | sed -n '1,200p'
En controleer .env:
ls -la .env
cat .env
Let op: .env wordt door Compose automatisch ingelezen uit de projectdirectory, maar env_file: is iets anders (dat gaat de container in).
Stap 3 — Logs: het verschil tussen Compose-fouten en container-fouten
Compose kan falen op twee niveaus:
- Orchestratie: netwerk aanmaken, volumes, pull/build, container create/start.
- Runtime: container start wel, maar applicatie crasht direct.
Zie welke containers bestaan en hun status
docker compose ps -a
Als je Exited (1) ziet, is Compose vaak “geslaagd” in starten, maar je app faalt.
Bekijk logs per service
docker compose logs
docker compose logs -f
docker compose logs --tail=200 <service>
Inspecteer exit code en startfout
docker compose ps -a
docker inspect <container_id> --format '{{.State.Status}} {{.State.ExitCode}} {{.State.Error}}'
Docker events (super nuttig bij “mystery failures”)
docker events --since 10m
Je ziet dan bijvoorbeeld oom, die, kill, health_status, network errors, etc.
Stap 4 — Build-problemen (Dockerfile, context, cache, platform)
Als docker-compose up faalt tijdens build, is het meestal één van deze categorieën:
- build context klopt niet,
- Dockerfile pad klopt niet,
- dependency download faalt (proxy/DNS),
- platform mismatch (ARM vs AMD64),
- cache houdt een fout in stand.
Snelle isolatie: build apart draaien
docker compose build --progress=plain
Met --progress=plain krijg je “klassieke” build output, vaak duidelijker.
Veelvoorkomende build-fouten en fixes
1) failed to read dockerfile
Controleer paden:
# Toon de uiteindelijke config (incl. build.context en build.dockerfile)
docker compose config | sed -n '1,200p'
Check of bestanden bestaan:
ls -la
ls -la path/naar/Dockerfile
2) Build context is te groot / traag
Als je per ongeluk je hele home directory als context stuurt, duurt het lang of faalt het.
Controleer .dockerignore:
cat .dockerignore
Praktische .dockerignore-regels (voorbeeld):
# node
node_modules
npm-debug.log
# python
__pycache__/
*.pyc
# git
.git
3) Platform mismatch (Apple Silicon / ARM)
Symptomen:
exec format error- image werkt op CI maar niet lokaal
Check je architectuur:
uname -m
docker info --format '{{.Architecture}}'
Forceer platform bij build/run (tijdelijk):
docker compose build --no-cache --pull --progress=plain --build-arg SOMEARG=1
docker compose up --force-recreate
Of (als je compose file platform gebruikt) start met:
docker compose up --pull=always
Je kunt ook expliciet een platform kiezen per service (maar dat is config). Als je geen YAML wilt aanpassen, kun je soms via DOCKER_DEFAULT_PLATFORM werken:
export DOCKER_DEFAULT_PLATFORM=linux/amd64
docker compose up --build
4) Cache-problemen
Gebruik:
docker compose build --no-cache
Of verwijder alleen build cache:
docker builder prune
Let op: dit kan veel opnieuw moeten downloaden.
Stap 5 — Poorten en netwerkconflicten
Een klassieker: Bind for 0.0.0.0:PORT failed: port is already allocated.
Diagnose: wie gebruikt die poort?
Linux:
sudo ss -lntp | grep ':5432'
sudo lsof -iTCP:5432 -sTCP:LISTEN
macOS:
lsof -nP -iTCP:5432 -sTCP:LISTEN
Windows (PowerShell):
netstat -ano | findstr :5432
Oplossingen
- Stop het proces dat de poort bezet.
- Of wijzig de host-poort (bijv. van
5432:5432naar15432:5432). - Of bind alleen op localhost (veiliger bij dev):
127.0.0.1:15432:5432.
Netwerknaam-conflicten
Soms faalt netwerk creatie door bestaande netwerken met dezelfde naam of “stale” resources.
Check:
docker network ls
docker compose ls
Verwijder het project (containers/netwerken) en probeer opnieuw:
docker compose down
docker compose up
Als een netwerk “vastzit”:
docker network rm <network_name>
Stap 6 — Volumes, bind mounts en permissies
Veel up-fails zijn eigenlijk filesystem-permissies, vooral bij database-volumes of bind mounts naar je broncode.
Begrippen
- Named volume: door Docker beheerd, pad ergens onder
/var/lib/docker/volumes/.... - Bind mount: jij koppelt een host-pad naar de container.
Named volumes zijn vaak stabieler; bind mounts geven sneller permissieproblemen.
Symptomen
permission deniedread-only file system- DB start niet en klaagt over data directory
EACCESin Node/Python/Go apps
Diagnose
Welke mounts gebruikt een container?
docker compose ps -a
docker inspect <container_id> --format '{{json .Mounts}}' | python -m json.tool 2>/dev/null || true
Check eigenaar/permissies op host (bij bind mounts):
ls -la ./data
id
Check gebruiker in container:
docker compose exec <service> sh -lc 'id && whoami && ls -la /pad/in/container'
Tip: als de container niet draait, kun je een tijdelijke shell starten met dezelfde image (of
docker run)—maar met Compose is het vaak makkelijker om eerst de service “alive” te krijgen.
Oplossingen
1) Host directory ownership fixen (bind mount)
Als je container als user 1000:1000 draait, moet de host directory schrijfbaar zijn voor die user.
sudo chown -R 1000:1000 ./data
sudo chmod -R u+rwX ./data
2) SELinux (Fedora/RHEL/CentOS) context issues
Symptoom: permissies lijken goed, maar toch permission denied.
Gebruik :Z of :z op bind mounts (config-wijziging), of zet context handmatig:
sudo chcon -Rt svirt_sandbox_file_t ./data
3) Named volume resetten (let op data!)
Als een database-volume corrupt is of verkeerde permissies heeft:
docker compose down
docker volume ls
docker volume rm <volume_name>
docker compose up
Als je data wil bewaren, maak eerst een backup (voorbeeld voor een volume):
docker run --rm -v <volume_name>:/v -v "$PWD":/backup alpine \
sh -lc 'cd /v && tar czf /backup/volume-backup.tgz .'
Stap 7 — DNS, service discovery en “depends_on” misverstanden
In Compose kunnen services elkaar bereiken via de service name als hostname (bijv. db, redis, api) op hetzelfde network.
Veelgemaakte fout: localhost gebruiken
Binnen een container betekent localhost de container zelf, niet je host en niet een andere container.
Symptoom:
- app probeert
localhost:5432en faalt metconnection refused
Oplossing:
- gebruik
db:5432(service name) in je app-config.
Diagnose: DNS en connectivity testen
Start een shell in een bestaande service:
docker compose exec <service> sh
Test DNS:
getent hosts db || nslookup db || ping -c 1 db
Test TCP connectiviteit (afhankelijk van tools in image):
# als nc aanwezig is:
nc -vz db 5432
# of met bash (werkt niet overal):
/bin/sh -lc 'echo > /dev/tcp/db/5432' && echo OK || echo FAIL
Als tools ontbreken, gebruik een tijdelijke debug container in hetzelfde network. Eerst achterhaal de networknaam:
docker network ls
docker compose ps
Vaak heet het netwerk <project>_default. Start dan:
docker run --rm -it --network <project>_default nicolaka/netshoot bash
In netshoot heb je dig, nslookup, curl, nc, tcpdump, etc.
“depends_on” is geen “wait until ready”
depends_on zorgt alleen dat containers in een volgorde gestart worden, niet dat de database al klaar is om verbindingen te accepteren.
Symptoom:
- app start, probeert meteen DB, crasht, Compose herstart, loop.
Oplossingen:
- Voeg retries/backoff toe in je applicatie.
- Gebruik healthchecks en wacht-logica (zie volgende sectie).
- Gebruik een entrypoint script dat wacht tot
db:5432open is.
Voorbeeld van wachten in een draaiende container (handmatig):
docker compose exec api sh -lc 'for i in $(seq 1 30); do nc -z db 5432 && exit 0; echo waiting; sleep 1; done; exit 1'
Stap 8 — Omgevingsvariabelen, .env en secrets
Omgevingsproblemen zijn verraderlijk: alles start “goed”, maar je app faalt door verkeerde credentials of endpoints.
Controleer wat Compose daadwerkelijk doorgeeft
Bekijk de uiteindelijke config:
docker compose config
Bekijk runtime env in een container:
docker compose exec <service> env | sort | sed -n '1,200p'
Veelvoorkomende valkuilen
1) .env vs env_file
.env(in projectmap) wordt gebruikt voor variabele substitutie in compose config.env_file:zet variabelen in de container.
Als je verwacht dat .env automatisch in de container komt: dat is niet zo (tenzij je environment: of env_file: gebruikt).
2) Quotes en speciale tekens
Wachtwoorden met $ kunnen door substitutie veranderen als je ze in de compose config zet. Zet ze liever in .env of env_file en escape waar nodig.
Test substitutie:
docker compose config --environment
3) Verkeerde “project name” → andere resources
Compose gebruikt een projectnaam (vaak directorynaam). Daardoor kunnen volume- en netwerk-namen verschillen dan je denkt.
Check:
docker compose ls
Forceer projectnaam:
docker compose -p mijnproject up
Stap 9 — Healthchecks en startvolgorde
Als docker-compose up faalt omdat een service “unhealthy” wordt of steeds herstart, moet je onderscheid maken tussen:
- container is running maar unhealthy
- container exited door crash
- container wordt killed (OOM, timeout, etc.)
Check health status
docker compose ps
docker inspect <container_id> --format '{{json .State.Health}}' | python -m json.tool 2>/dev/null || true
Bekijk healthcheck logs:
docker inspect <container_id> --format '{{range .State.Health.Log}}{{println .End .ExitCode .Output}}{{end}}'
Typische healthcheck-problemen
- Healthcheck gebruikt
curlmaar image heeft geencurl. - Endpoint vereist auth en geeft 401 → healthcheck faalt.
- Service luistert op andere poort/interface dan gedacht.
Diagnose in container:
docker compose exec <service> sh -lc 'ps aux; ss -lntp 2>/dev/null || netstat -lntp 2>/dev/null || true'
Stap 10 — Resourceproblemen (disk, memory, ulimits)
Soms faalt up door gebrek aan resources, vooral op laptops met Docker Desktop.
Disk vol
Symptomen:
no space left on device- pulls/builds falen
Check:
df -h
docker system df
Opruimen:
docker image prune
docker container prune
docker volume prune
docker network prune
docker system prune
Let op:
docker system prune --volumeskan data verwijderen. Gebruik dit alleen als je zeker weet wat weg mag.
Memory / OOM
Symptomen:
- container stopt plots
OOMKilledin inspect
Check:
docker inspect <container_id> --format '{{.State.OOMKilled}}'
docker compose logs --tail=200 <service>
Op Linux kun je ook kernel logs bekijken:
dmesg | tail -n 200 | grep -i oom
Oplossingen:
- Geef Docker Desktop meer RAM.
- Verlaag memory-honger van je stack (bijv. JVM heap).
- Start minder services tegelijk.
Ulimits / file descriptors
Symptomen:
too many open files
Check limieten in container:
docker compose exec <service> sh -lc 'ulimit -n; ulimit -a'
Oplossing zit vaak in service config (ulimits). Als snelle workaround: verlaag load of fix app.
Stap 11 — Opruimen en “resetten” zonder data te verliezen
Als je veel hebt geprobeerd, kan je omgeving inconsistent zijn. Reset gericht.
Alleen containers opnieuw aanmaken (behoud volumes)
docker compose down
docker compose up --force-recreate
Containers + netwerken weg, volumes behouden (standaard)
docker compose down
Ook volumes weg (data kwijt)
docker compose down -v
Alles van dit project opruimen (incl. orphan containers)
docker compose down --remove-orphans
“Nucleair” maar effectief: alles ongebruikt opruimen
docker system prune
Wil je ook ongebruikte volumes weg:
docker system prune --volumes
Cheatsheet: snelle commando’s per symptoom
Compose faalt meteen (config/syntax)
docker compose config
docker compose config --environment
Docker daemon/connectie issues
docker info
sudo systemctl status docker
ls -l /var/run/docker.sock
Service crasht direct
docker compose ps -a
docker compose logs --tail=200 <service>
docker inspect <container_id> --format '{{.State.ExitCode}} {{.State.Error}}'
Poort al in gebruik
sudo ss -lntp | grep ':<PORT>'
lsof -nP -iTCP:<PORT> -sTCP:LISTEN
DNS/verbinding tussen services
docker compose exec <service> sh -lc 'getent hosts db; nc -vz db 5432'
docker run --rm -it --network <project>_default nicolaka/netshoot bash
Volumes/permissies
docker inspect <container_id> --format '{{json .Mounts}}'
docker compose exec <service> sh -lc 'id; ls -la /data'
sudo chown -R 1000:1000 ./data
Disk/memory
docker system df
df -h
docker inspect <container_id> --format '{{.State.OOMKilled}}'
Praktische aanpak: een voorbeeld “debug sessie” van begin tot eind
Stel: docker compose up geeft een fout en je ziet:
apiblijft herstartendbdraaitapilogs tonenECONNREFUSED 127.0.0.1:5432
Systematisch:
- Status:
docker compose ps -a
- Logs van
api:
docker compose logs --tail=200 api
-
Conclusie: app probeert
localhost. Dat is fout in containers. -
Verifieer DNS naar db:
docker compose exec api sh -lc 'getent hosts db && nc -vz db 5432'
Als dit succeeded is, dan is netwerk OK.
-
Fix: wijzig app-config naar
DB_HOST=db(of connection string naarpostgres://...@db:5432/...). -
Herstart alleen
api:
docker compose up -d --force-recreate api
docker compose logs -f api
Veelvoorkomende foutmeldingen (herkenning → actie)
ERROR: for <service> Cannot start service ... driver failed programming external connectivity
Bijna altijd een poortconflict of firewall/proxy issue.
- Check poortgebruik (
ss/lsof) - Check of je poort mapping klopt
- Probeer tijdelijk een andere host-poort
standard_init_linux.go:xxx: exec user process caused: exec format error
Architectuur mismatch (ARM/AMD64) of verkeerd binary.
- Check
uname -m - Zet
DOCKER_DEFAULT_PLATFORM=linux/amd64 - Gebruik images die multi-arch zijn
Mounts denied (Docker Desktop)
Je probeert een host-pad te mounten dat niet gedeeld is met Docker Desktop.
- Voeg directory toe aan “File Sharing” (Docker Desktop settings)
- Of mount een pad binnen de gedeelde directories
no such host of Temporary failure in name resolution
DNS in Docker netwerk of upstream DNS faalt.
- Test met
netshoot - Check of corporate VPN/proxy DNS breekt
- Probeer Docker DNS settings (Desktop) of host resolv.conf issues (Linux)
Slot: de kernprincipes
- Valideer eerst config (
docker compose config). - Kijk naar status en logs (
docker compose ps -a,docker compose logs). - Test netwerk vanuit containers, niet vanaf je host.
- Behandel volumes en permissies als eerste-orde problemen.
- Reset gericht (
down,--force-recreate, pas daarna prune).
Als je een specifieke foutmelding hebt, plak:
- de output van
docker compose up(laatste ~200 regels), docker compose ps -a,- en
docker compose logs --tail=200 <service>van de falende service,
dan kun je meestal in één iteratie naar de echte oorzaak.