When docker-compose up Fails: Systematic Troubleshooting of Common Errors
This tutorial is a systematic, command-driven approach to diagnosing and fixing failures when running docker-compose up (or docker compose up with the newer CLI). It focuses on repeatable steps rather than one-off fixes, so you can apply the same workflow to almost any Compose-related failure.
Table of Contents
- 1. Know Your Compose Variant and Versions
- 2. First Pass: Reproduce Cleanly and Capture Evidence
- 3. Validate the Compose Configuration Before Running
- 4. Categorize the Failure: Where Is It Breaking?
- 5. Common Error Class: Docker Daemon / Permissions
- 6. Common Error Class: Ports and Networking
- 7. Common Error Class: Volumes, Mounts, and File Permissions
- 8. Common Error Class: Image Pull / Build Failures
- 9. Common Error Class: Containers Start Then Exit
- 10. Common Error Class: Healthchecks and Dependency Ordering
- 11. Common Error Class: DNS / Service Discovery Inside Compose
- 12. Common Error Class: Resource Limits (Memory/CPU/Disk)
- 13. Cleaning Up Safely (Without Nuking Everything)
- 14. A Repeatable Troubleshooting Checklist
1. Know Your Compose Variant and Versions
There are two common ways to run Compose:
- Legacy v1 binary:
docker-compose ... - Modern v2 plugin:
docker compose ...
They behave similarly, but error messages and some features differ. Start by identifying what you’re actually running.
docker version
docker compose version
docker-compose version || true
Typical outcomes:
- If
docker compose versionworks, you’re using the v2 plugin. - If only
docker-compose versionworks, you’re using the legacy binary. - If neither works, Compose isn’t installed or your PATH is wrong.
Why this matters:
- Some online fixes apply only to v1 or v2.
- Compose file features may require newer versions.
- Output formatting and flags differ slightly.
Also check the OS context:
uname -a
On macOS/Windows, Docker runs inside a VM; filesystem mounts and networking can behave differently than Linux.
2. First Pass: Reproduce Cleanly and Capture Evidence
When docker-compose up fails, avoid guessing. Capture the exact error, then expand your visibility.
Run with explicit project context and no stale leftovers
From the directory containing your compose.yaml / docker-compose.yml:
pwd
ls -la
Then:
docker compose up
If it fails quickly, rerun with more verbose output:
docker compose --verbose up
If output is too noisy, keep it but redirect to a file:
docker compose --verbose up 2>&1 | tee compose-debug.log
Check what Compose created before failing
Even if up fails, Compose may have created networks/containers.
docker compose ps
docker ps -a --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}'
docker network ls
docker volume ls
Inspect the failing container(s)
If a container exists but is exited:
docker logs <container_name>
docker logs --tail=200 <container_name>
If it crashes immediately, get the exit code:
docker inspect <container_name> --format '{{.State.ExitCode}}'
docker inspect <container_name> --format '{{.State.Error}}'
3. Validate the Compose Configuration Before Running
Many “runtime” failures are actually configuration problems.
Render the fully-resolved Compose config
This is one of the most powerful commands:
docker compose config
It expands:
- environment variable substitutions
- anchors/extends (where supported)
- merged settings
If docker compose config fails, fix that first. Common messages include:
- “Additional property … is not allowed”
- “services.
must be a mapping” - “invalid type, expected string”
Check which file Compose is using
Compose looks for compose.yaml, compose.yml, docker-compose.yml by default. If you have multiple files, be explicit:
docker compose -f compose.yaml config
docker compose -f docker-compose.yml config
Verify environment variables used by Compose
If your compose file uses ${VAR} substitutions, confirm they’re set:
env | sort | less
If using an .env file, ensure it exists and is in the correct directory (Compose reads .env from the project directory by default):
ls -la .env
cat .env
To see what Compose thinks the environment is after interpolation, again use:
docker compose config
4. Categorize the Failure: Where Is It Breaking?
Most docker-compose up failures fall into one of these buckets:
- Docker daemon not reachable / permissions
- Network/port binding problems
- Volume mount / filesystem permissions
- Image pull failures
- Build failures
- Container starts then exits (app-level errors)
- Healthcheck/dependency issues
- DNS/service discovery issues
- Resource constraints (disk/memory/CPU)
The rest of this tutorial walks through each category with concrete commands and fixes.
5. Common Error Class: Docker Daemon / Permissions
Symptom: “Cannot connect to the Docker daemon”
Examples:
Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?error during connect: ...
On Linux: check daemon status
systemctl status docker
sudo systemctl start docker
sudo systemctl enable docker
Check socket permissions:
ls -l /var/run/docker.sock
If you see something like root docker, your user may need to be in the docker group:
sudo usermod -aG docker "$USER"
newgrp docker
Then verify:
docker ps
Note: Using the
dockergroup grants root-equivalent access to the host. In production environments, consider rootless Docker or tighter controls.
On macOS/Windows: Docker Desktop running?
Ensure Docker Desktop is started and healthy. Then:
docker ps
If Docker Desktop is running but docker ps fails, try restarting Docker Desktop and/or resetting Kubernetes (if enabled and interfering).
6. Common Error Class: Ports and Networking
Symptom: “Bind for 0.0.0.0:XXXX failed: port is already allocated”
This means something on your host is already using that port.
Find what’s using the port (Linux)
sudo ss -ltnp | grep ':8080'
Or:
sudo lsof -iTCP:8080 -sTCP:LISTEN -n -P
Find what’s using the port (macOS)
lsof -iTCP:8080 -sTCP:LISTEN -n -P
Fix options
-
Stop the conflicting service (if safe):
sudo systemctl stop nginx -
Change the published port in Compose (host side). If your compose maps
8080:80, change to8081:80and rerun. -
Bind to localhost only (reduces exposure):
- Use
127.0.0.1:8080:80style mapping in Compose (conceptually: host IP + host port -> container port). - Then access via
http://127.0.0.1:8080.
- Use
Symptom: “network … not found” or “Pool overlaps”
If networks were partially created or you have conflicting subnets.
Inspect existing networks
docker network ls
docker network inspect <network_name>
Remove only the project’s networks
docker compose down
If the project name changed (e.g., directory rename), list networks and remove the specific one:
docker network rm <network_name>
If you see “Pool overlaps with other one on this address space”, you likely have a custom subnet conflicting with another Docker network or your corporate VPN. Fix by choosing a different subnet or removing the conflicting network.
7. Common Error Class: Volumes, Mounts, and File Permissions
Mount issues are among the most frequent Compose problems, especially across OSes.
Symptom: “Mounts denied” (Docker Desktop)
On macOS/Windows:
- Docker Desktop only shares certain directories by default.
Fix:
- In Docker Desktop settings, add the host path to “File Sharing” (or the equivalent).
- Then retry.
Symptom: “no such file or directory” for a bind mount
Example:
invalid mount config for type "bind": bind source path does not exist
Check the path exists on the host:
ls -la ./path/on/host
Remember: relative paths are relative to the Compose file’s directory (project directory), not your current shell directory if you run Compose elsewhere.
Confirm the resolved config:
docker compose config | sed -n '/volumes:/,/networks:/p'
Symptom: Permission denied inside container
Example:
- App fails to write to
/datawhich is mounted from the host.
Diagnose by checking ownership on host
ls -lan ./data
id
The container may run as a different UID/GID than your host user.
Inspect container user
If the container exists:
docker inspect <container_name> --format '{{.Config.User}}'
If empty, it runs as the image default (often root, but not always).
Practical fixes
-
Chown the host directory to match container UID/GID (common for Linux dev setups):
sudo chown -R 1000:1000 ./data(Replace
1000:1000with the container’s expected UID/GID.) -
Run container as your user (development convenience):
- Many images support
user: "${UID}:${GID}"conceptually; ensure your environment exports them:export UID GID echo "$UID $GID" - Then rerun Compose.
- Many images support
-
Use a named volume instead of a bind mount if you don’t need host visibility:
docker volume ls docker volume inspect <volume>
Named volumes avoid many host filesystem permission problems because Docker manages them.
8. Common Error Class: Image Pull / Build Failures
Symptom: “pull access denied” / “manifest unknown” / auth errors
Confirm the image name and tag
Try pulling manually:
docker pull yourimage:yourtag
If it fails:
- The repository may be private.
- The tag may not exist.
- You may be blocked by a proxy.
Authenticate to registries
For Docker Hub or generic registries:
docker login
For a specific registry:
docker login registry.example.com
For cloud registries (examples):
-
AWS ECR (requires AWS CLI configured):
aws ecr get-login-password --region us-east-1 \ | docker login --username AWS --password-stdin <account_id>.dkr.ecr.us-east-1.amazonaws.com -
GitHub Container Registry:
echo "$GITHUB_TOKEN" | docker login ghcr.io -u <username> --password-stdin
Symptom: Build fails during docker compose up --build
First, isolate the build:
docker compose build --no-cache
If it fails, build a single service:
docker compose build --no-cache <service_name>
Common build failure causes
-
Missing build context files
- Dockerfile references files not in context.
- Diagnose by checking the build context directory and
.dockerignore.
-
Proxy / network issues during build
- If
apt-getorpipfails, test connectivity from host:curl -I https://deb.debian.org - If you’re behind a proxy, you may need to pass build args or configure Docker daemon proxy.
- If
-
Multi-arch mismatch
- On Apple Silicon, pulling/building
linux/amd64vslinux/arm64matters. - Check your platform:
uname -m docker info | sed -n '/Architecture/,+2p' - Try building with a specific platform:
docker buildx ls docker compose build --pull
- On Apple Silicon, pulling/building
9. Common Error Class: Containers Start Then Exit
This is the most important category to understand: Compose may be fine; the application is failing.
Symptom: Exited (1) or Exited (127) etc.
Step 1: Read logs
docker compose logs -f --tail=200
Or per-service:
docker compose logs -f --tail=200 <service_name>
Step 2: Inspect the container’s command and environment
docker compose ps
docker inspect <container_name> --format '{{json .Config.Cmd}}'
docker inspect <container_name> --format '{{json .Config.Entrypoint}}'
docker inspect <container_name> --format '{{json .Config.Env}}' | jq .
If you don’t have jq, omit it:
docker inspect <container_name> --format '{{json .Config.Env}}'
Step 3: Run an interactive shell in the image
If the container won’t stay up, start a one-off container:
docker compose run --rm <service_name> sh
If the image uses bash:
docker compose run --rm <service_name> bash
Now you can test:
- config files exist
- environment variables are set
- network connectivity to dependencies works
Example checks:
env | sort
ls -la
cat /etc/os-release
Common exit-code patterns
- 127: command not found (entrypoint/command wrong, missing binary)
- 1: generic application error (misconfig, missing env vars, cannot connect to DB)
- 137: killed (often out-of-memory)
10. Common Error Class: Healthchecks and Dependency Ordering
Symptom: Service depends on DB but starts too early
Compose’s depends_on controls startup order, not readiness (unless you use healthcheck conditions in some setups). The robust approach is:
- Add a healthcheck to the dependency (e.g., database).
- Make the application retry connections on startup (best practice).
Diagnose health status
docker compose ps
docker inspect <container_name> --format '{{json .State.Health}}' | jq .
Also view healthcheck logs:
docker inspect <container_name> --format '{{range .State.Health.Log}}{{println .Output}}{{end}}'
If a DB healthcheck is failing, the app may never see it “healthy.”
Test dependency connectivity from inside a container
For example, from the app container:
docker compose exec <app_service> sh -lc 'getent hosts db && nc -vz db 5432'
If nc isn’t installed, use alternatives:
curlfor HTTP serviceswgetpython -c ...if Python exists
11. Common Error Class: DNS / Service Discovery Inside Compose
Compose provides built-in DNS: services can reach each other by service name on the same network.
Symptom: “Name or service not known” when connecting to another service
Verify both services are on the same network
List networks for a container:
docker inspect <container_name> --format '{{json .NetworkSettings.Networks}}' | jq .
If they’re not on the same network, they can’t resolve each other.
Verify DNS resolution from inside the container
docker compose exec <service> sh -lc 'cat /etc/resolv.conf; getent hosts other_service'
If getent isn’t present:
docker compose exec <service> sh -lc 'nslookup other_service || true'
Common mistake: using localhost
Inside a container, localhost refers to the container itself, not another service and not the host. To reach another service, use its Compose service name (e.g., db, redis). To reach the host:
- On Docker Desktop:
host.docker.internal - On Linux: you may need to use the gateway IP or set up
--add-hostequivalents.
Test:
docker compose exec <service> sh -lc 'ping -c 1 host.docker.internal || true'
12. Common Error Class: Resource Limits (Memory/CPU/Disk)
Symptom: Random crashes, Killed, exit code 137, or build failures
Check disk usage
docker system df
df -h
If disk is full, builds and pulls fail in confusing ways.
Clean up unused resources (careful—see cleanup section):
docker image prune
docker builder prune
Check memory constraints (Docker Desktop)
Docker Desktop has configurable memory limits. If too low, builds and containers may be OOM-killed.
On Linux, check kernel messages:
dmesg -T | tail -n 100 | grep -i -E 'killed process|oom'
Check container resource usage
docker stats
If a service spikes memory and dies, it’s likely an application or configuration issue (e.g., Java heap too large, caching misconfigured).
13. Cleaning Up Safely (Without Nuking Everything)
When troubleshooting, you often need to remove broken containers/networks/volumes. Do it in increasing order of destructiveness.
Stop and remove only this project’s containers/networks
docker compose down
If you want to remove volumes created by the project (this deletes data):
docker compose down -v
Remove orphaned containers (from renamed services)
docker compose up --remove-orphans
Rebuild from scratch
docker compose down
docker compose build --no-cache
docker compose up
Prune unused Docker objects (global impact)
These commands affect the whole Docker host, not just your project:
docker container prune
docker network prune
docker volume prune
docker image prune
docker system prune
If you want the most aggressive cleanup (dangerous; deletes unused images, containers, networks, and build cache):
docker system prune -a
Use docker system df before and after to understand what you’re deleting.
14. A Repeatable Troubleshooting Checklist
Use this sequence to avoid thrashing:
-
Confirm tooling
docker version docker compose version -
Validate configuration
docker compose config -
Run with visibility
docker compose --verbose up 2>&1 | tee compose-debug.log -
Check container states
docker compose ps docker ps -a -
Read logs
docker compose logs -f --tail=200 -
Inspect failing container
docker inspect <container> --format '{{.State.Status}} {{.State.ExitCode}}' docker inspect <container> --format '{{.State.Error}}' -
Check ports
sudo ss -ltnp | grep ':<port>' || true -
Check mounts
ls -la <mounted_path> -
Test service-to-service connectivity
docker compose exec <service> sh -lc 'getent hosts <other_service> && nc -vz <other_service> <port>' -
Clean project artifacts and retry
docker compose down
docker compose up --build
Closing Notes: How to Think About Compose Failures
A Compose “up” failure is rarely mysterious if you separate concerns:
- Compose layer: parsing, interpolation, creating networks/volumes, starting containers.
- Docker engine layer: pulling images, building, mounting, port binding.
- Application layer: the process inside the container exits, misconfigured env vars, dependency not ready.
The goal is to identify which layer is failing, then use the right command to confirm it. If you want, paste the exact error output (and your docker compose config output with secrets removed), and you can troubleshoot it using the workflow above.