← Terug naar tutorials

Als `docker-compose up` faalt: systematisch veelvoorkomende fouten oplossen

docker-composedockertroubleshootingdebuggingdevopscontainerslinuxnetwerkenvolumespoorten

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

  1. Vooraf: Compose v1 vs v2 en wat je precies draait
  2. Een herhaalbare diagnose-workflow
  3. Stap 1 — Is Docker Engine bereikbaar?
  4. Stap 2 — Valideer je Compose-config
  5. Stap 3 — Logs: het verschil tussen Compose-fouten en container-fouten
  6. Stap 4 — Build-problemen (Dockerfile, context, cache, platform)
  7. Stap 5 — Poorten en netwerkconflicten
  8. Stap 6 — Volumes, bind mounts en permissies
  9. Stap 7 — DNS, service discovery en “depends_on” misverstanden
  10. Stap 8 — Omgevingsvariabelen, .env en secrets
  11. Stap 9 — Healthchecks en startvolgorde
  12. Stap 10 — Resourceproblemen (disk, memory, ulimits)
  13. Stap 11 — Opruimen en “resetten” zonder data te verliezen
  14. 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”:

  1. Reproduceer het probleem met maximale signalen (logs, exit codes).
  2. Classificeer: faalt het bij config parsing, build, pull, network create, container start, of applicatie runtime?
  3. Observeer: inspecteer containers, events, logs, mounts, netwerken.
  4. Minimaliseer: start één service, of start zonder build, of zonder volumes.
  5. 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

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

sudo systemctl start docker
sudo systemctl enable docker
sudo usermod -aG docker "$USER"
newgrp docker
docker info
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:

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:

  1. Orchestratie: netwerk aanmaken, volumes, pull/build, container create/start.
  2. 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:

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:

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

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 volumes zijn vaak stabieler; bind mounts geven sneller permissieproblemen.

Symptomen

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:

Oplossing:

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:

Oplossingen:

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

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:

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

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:

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 --volumes kan data verwijderen. Gebruik dit alleen als je zeker weet wat weg mag.

Memory / OOM

Symptomen:

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:

Ulimits / file descriptors

Symptomen:

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:

Systematisch:

  1. Status:
docker compose ps -a
  1. Logs van api:
docker compose logs --tail=200 api
  1. Conclusie: app probeert localhost. Dat is fout in containers.

  2. 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.

  1. Fix: wijzig app-config naar DB_HOST=db (of connection string naar postgres://...@db:5432/...).

  2. 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.

standard_init_linux.go:xxx: exec user process caused: exec format error

Architectuur mismatch (ARM/AMD64) of verkeerd binary.

Mounts denied (Docker Desktop)

Je probeert een host-pad te mounten dat niet gedeeld is met Docker Desktop.

no such host of Temporary failure in name resolution

DNS in Docker netwerk of upstream DNS faalt.


Slot: de kernprincipes

  1. Valideer eerst config (docker compose config).
  2. Kijk naar status en logs (docker compose ps -a, docker compose logs).
  3. Test netwerk vanuit containers, niet vanaf je host.
  4. Behandel volumes en permissies als eerste-orde problemen.
  5. Reset gericht (down, --force-recreate, pas daarna prune).

Als je een specifieke foutmelding hebt, plak:

dan kun je meestal in één iteratie naar de echte oorzaak.