Docker Compose Troubleshooting Guide: Quick Solutions for 5 Common Errors

Friday afternoon, 3:30 PM. Two hours until the code submission deadline.
I stared at that red error message in my terminal — Error starting userland proxy: Bind for 0.0.0.0:8080 failed: port is already allocated. It was working fine yesterday, and now it won’t start.
Ctrl+C, retry. Still fails. Googled “docker compose port already allocated”, opened five or six Stack Overflow threads, tried every solution: restart Docker, delete containers, change ports… The error message wouldn’t budge. Palms started sweating.
If you’ve been through this, you know exactly what I’m talking about. Docker Compose error messages can span dozens of lines, with the one useful piece of information buried on line 23, while you’re already panicking at line 1. Worse yet, every new error means starting the troubleshooting process from scratch.
This article summarizes the pitfalls I (and my team) have encountered over two years. We’ve organized 5 major categories of common Docker Compose errors, each following the pattern: “Error Characteristics → Root Causes → Solutions (from simple to complex).” You’ll find that 90% of errors can be resolved in 5 minutes — once you know where to start.
Troubleshooting Basics - Master 3 Core Tools
Before diving into specific errors, let’s talk about the three essential tools for troubleshooting Docker Compose issues — I use these commands dozens of times every day.
Tool 1: docker-compose ps - Check Status Quickly
This command tells you which containers are up and which are down.
docker-compose psFocus on the State column:
Up- Running normally, breathe easyExit- Startup failed or crashed during runtimeRestarting- Constantly restarting, indicates startup command issues
When I see a service with Exit 1 status, I know it’s time to check the logs.
Tool 2: docker-compose logs - Find Clues in Logs
This is the core of troubleshooting.
# View all services' logs
docker-compose logs
# View only nginx logs
docker-compose logs nginx
# Follow logs in real-time (like tail -f)
docker-compose logs -f
# Show only last 100 lines
docker-compose logs --tail 100 nginxHonestly, Docker’s log output can be messy, but 90% of the time, the real error message is in the last few dozen lines. Scroll up and look for keywords: ERROR, failed, cannot.
Tool 3: docker inspect - Deep Inspection (When Needed)
Only use this when the first two commands don’t solve the problem.
# View complete container configuration
docker inspect container_name
# Check only status
docker inspect --format='{{.State.Status}}' container_name
# Get IP address
docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' container_nameGeneral Troubleshooting Process (Remember This)
Don’t panic when problems arise, follow this flow:
docker-compose ps- See which service faileddocker-compose logs [service_name]- Check specific errorsdocker inspect- Deep analysis (rarely needed)
Alright, tools ready. Now let’s tackle the 5 most frequent errors.
Port Conflicts - “port is already allocated”
I’ve seen this error way too many times. You’ll see something like:
Error starting userland proxy: Bind for 0.0.0.0:8080 failed: port is already allocatedOr:
ERROR: for nginx Cannot start service nginx: driver failed programming external connectivity on endpoint xxx: Bind for 0.0.0.0:80 failed: port is already allocatedWhy Does This Happen?
Usually three scenarios:
- After last
docker-compose up, you hit Ctrl+C but didn’t rundocker-compose down, containers still running in background - You changed port configuration in docker-compose.yml, but old containers weren’t cleaned up
- Another program on your machine is using that port (like local Nginx, MySQL)
Solutions (Try in Order, Simple to Complex)
Solution 1: Clean and Restart (90% effective)
docker-compose down
docker-compose up -dThis works for me every time. The down command stops all containers and removes them while preserving volume data.
Solution 2: Find Container Occupying the Port
If solution 1 doesn’t work, you might have “ghost containers” — containers not part of current project but occupying the port.
# List all containers (including stopped ones)
docker ps -a | grep 8080
# After finding container_id, kill it
docker stop <container_id>
docker rm <container_id>Solution 3: Check docker-proxy Processes
Sometimes containers are deleted but docker-proxy processes remain.
# Check docker-proxy processes
ps aux | grep docker-proxy | grep 8080
# If remnants exist, restart Docker service
sudo systemctl restart docker # Linux
# Or on Mac: Docker Desktop menu → RestartSolution 4: Check Host Port Usage
Maybe a local program is using the port.
# Linux/Mac
lsof -i :8080
netstat -tlnp | grep 8080
# Windows
netstat -ano | findstr 8080If you find another program, either stop it or change the port in docker-compose.yml.
Solution 5: Modify Port Configuration (Last Resort)
Edit docker-compose.yml:
services:
web:
ports:
- "8081:80" # Change 8080 to 8081My Recommendations
Develop the habit: stop containers with docker-compose down, not just Ctrl+C. I used to take shortcuts with Ctrl+C, resulting in frequent port conflicts. After changing this habit, these errors basically disappeared.
Also, use non-standard ports in development environments. Don’t use 80, 3306 directly; change to 8080, 3307 to avoid conflicts with system services.
Network Issues - “network declared as external but could not be found”
This error typically looks like:
ERROR: Network my_network declared as external, but could not be found. Please create the network manually using `docker network create my_network` and try again.Why This Error?
Docker Compose has an easy pitfall: if you mark a network as external: true in docker-compose.yml, Docker assumes the network already exists and won’t create it automatically. Then it searches, can’t find it, and errors out.
Common scenarios:
- You copied someone’s config file with an external network, but you don’t have it locally
- You restarted Docker and some network configurations were lost
- Network name case is wrong (Docker network names are case-sensitive!)
Solutions
Solution 1: List Existing Networks, Verify Name
docker network lsYou might discover the actual network name is myproject_app_network, not the app_network you configured. Docker Compose automatically prefixes network names with the project name.
Solution 2: Manually Create Missing Network
If the network truly doesn’t exist, create it:
docker network create my_networkSolution 3: Fix Configuration File
Three ways, pick one:
# Method A: Remove external, let Compose create automatically
networks:
app_network:
driver: bridge
# Method B: Use name field to explicitly specify network name
networks:
app_network:
external: true
name: my_actual_network_name
# Method C: Manually create network first, then reference with externalI personally prefer Method A. Unless you need to share networks across multiple Compose projects, letting Compose manage networks is much easier.
Solution 4: Clean and Rebuild (Network Lost After Docker Restart)
docker-compose down
docker network prune # Clean unused networks
docker-compose up -dPitfall Prevention
- Clearly distinguish which networks should be external (cross-project sharing) and which should be Compose-managed (single project use)
- Use the
namefield to explicitly specify network names, avoiding confusion from Compose auto-prefixing - Document pre-created external networks in team README to prevent newcomers from stumbling
Build Failures - “service failed to build”
Don’t panic when you see this error:
ERROR: Service 'app' failed to build: Build failedKey Technique: Scroll Up the Logs
“service failed to build” is just a summary error; the real problem is earlier. You need to scroll up 50-100 lines and look for keywords: ERROR, failed, cannot, not found, permission denied.
First time I encountered this error, I stared at the last line forever before realizing I needed to scroll up. The real error could be “npm install failed” or “file not found”, buried in piles of output.
Common Sub-Error Types
Type 1: File Not Found
COPY failed: stat /var/lib/docker/tmp/.../package.json: no such file or directoryCauses:
- Incorrect
build contextpath .dockerignoreexcluded necessary files
Solutions:
# Check context configuration in docker-compose.yml
services:
app:
build:
context: ./my-app # Confirm this path is correct
dockerfile: Dockerfile
# Temporarily rename .dockerignore for testing
mv .dockerignore .dockerignore.bak
docker-compose build appType 2: Dependency Installation Failure
npm ERR! 404 Not Found - GET https://registry.npmjs.org/xxxOr:
E: Unable to locate package xxxCauses: Wrong package name, non-existent version, network issues
Solutions:
# Use domestic mirror (in Dockerfile)
RUN npm config set registry https://registry.npmmirror.com
RUN npm install
# Or switch apt source
RUN sed -i 's/deb.debian.org/mirrors.aliyun.com/g' /etc/apt/sources.list
RUN apt-get update && apt-get install -y xxxType 3: Out of Memory
The command '/bin/sh -c npm install' returned a non-zero code: 137
signal: killedExit code 137 usually indicates insufficient memory.
Solutions:
- Docker Desktop → Settings → Resources → Memory, increase to 4GB+
- Or reduce concurrent builds in Dockerfile:
RUN npm install --max_old_space_size=4096
Type 4: Dockerfile Syntax Error
For example, misspelled instruction names or incorrect COPY source file paths.
Solution: Test build separately:
cd build_directory
docker build -t test-build .This gives clearer error messages.
Debugging Methods
Rebuild Without Cache:
docker-compose build --no-cache service_nameSometimes cached intermediate layers are problematic; clearing cache and rebuilding can solve it.
Check Build Context:
docker-compose configThis command shows the complete parsed configuration, helping you spot path issues.
My Experience
- Save a successfully building version as baseline, test changes before continuing
- Modify Dockerfile one thing at a time; don’t change everything then get lost when errors occur
- For slow builds, consider multi-stage builds or reorder instructions to leverage cache for unchanging instructions
Container Exits After Starting - “exited with code X”
This situation is more subtle: image builds successfully, container starts, then immediately exits.
Running docker-compose ps shows:
Name State
app_web_1 Exit 1
app_db_1 UpExit Code Meanings (Remember These)
- Exit 0: Normal program exit — but might be a problem for containers (command finished and ended)
- Exit 1: Application error (most common)
- Exit 137: Out of memory (OOM) or killed
- Exit 139: Segmentation fault
- Exit 143: Received SIGTERM signal (usually manual stop)
Troubleshooting Steps
Step 1: Check Logs
docker-compose logs service_name90% of the time, logs will tell you why it exited.
Step 2: Manually Enter Container for Debugging
If logs don’t reveal the problem, modify docker-compose.yml to keep container running:
services:
app:
command: sleep infinity # Keep container from exitingThen:
docker-compose up -d
docker-compose exec app sh # Enter container
# Manually execute original startup command, observe errorsTargeted Solutions
Exit 0 - Command Finishes and Exits
For example, if your command is echo "Hello", it has nothing to do after execution, container naturally exits.
Solution: Change to daemon or blocking command:
# Wrong example
command: echo "Started"
# Correct example
command: npm start # A continuously running processExit 1 - Application Error
Check logs to pinpoint specific cause, common ones:
- Configuration file path errors
- Missing environment variables
- Database connection failure (database not ready yet)
- Permission issues
Exit 137 - Out of Memory
Add memory limit to container:
services:
app:
mem_limit: 2g
memswap_limit: 2gOr adjust Docker Desktop’s total memory allocation.
Dependent Service Not Ready
I’ve stepped on this mine. Application container started, but database still initializing, application can’t connect and crashes.
Solution: Use depends_on with healthcheck:
services:
app:
depends_on:
db:
condition: service_healthy
db:
image: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5This way app waits until db is truly ready before starting.
Pitfalls I’ve Hit
Once had a container repeatedly exiting with Exit 1, logs only said “Config file not found”. Searched forever, turns out I used relative path for config file location, and the working directory in container was different from what I expected. Changed to absolute path and it worked.
Another time database password was wrong, application crashed on startup. Logs were actually clear, but I didn’t look carefully… wasted 20 minutes.
Permission Issues - “permission denied”
This error is particularly common when mounting volumes:
Error: EACCES: permission denied, open '/app/data/config.json'Or container logs say “Permission denied” but you don’t know which file.
Why Permission Issues?
Container’s user UID/GID doesn’t match host file owner. For example:
- File owner on host is you (UID 1000)
- Application runs as www-data user in container (UID 33)
- www-data has no permission to read/write your files, errors out
Solutions
Solution 1: Use user to Specify UID/GID (Recommended)
Let container run with your user identity:
services:
app:
user: "${UID}:${GID}"
volumes:
- ./data:/app/dataAt runtime:
UID=$(id -u) GID=$(id -g) docker-compose upOr write to .env file:
# .env
UID=1000
GID=1000Solution 2: Change Host File Permissions
Simple and crude:
chmod -R 777 ./data # Use cautiously, security risk
# Or
chmod -R 755 ./data # Safer
chown -R $(id -u):$(id -g) ./dataSolution 3: Add Flags for SELinux Systems (CentOS/RHEL)
If using CentOS/RHEL, might be SELinux restrictions:
volumes:
- ./data:/app/data:z # Allow multiple containers to share
# Or
- ./config:/app/config:Z # This container onlyDifference between lowercase z and uppercase Z: lowercase is shared permissions, uppercase is private permissions.
Solution 4: Use Named Volume Instead of Bind Mount
Docker-managed volumes don’t have permission issues:
services:
app:
volumes:
- app_data:/app/data # named volume
volumes:
app_data: # Docker automatically manages permissionsDownside is you can’t directly modify files on host, only access through container.
Solution 5: Adjust Permissions in Entrypoint Script
For complex scenarios:
# entrypoint.sh
#!/bin/sh
chown -R appuser:appuser /app/data
exec "$@"COPY entrypoint.sh /
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["node", "app.js"]My Recommendations
- Production: Use named volumes, secure and no permission worries
- Development: Use Solution 1 (user specify UID/GID), convenient to modify files directly on host
- Avoid 777 permissions: Unless you completely trust code running in container, don’t give 777
Permission issues are indeed tricky, but once you understand UID/GID matching logic, not that difficult.
General Debugging Techniques Summary
After covering specific errors, let’s discuss systematic troubleshooting approaches.
Standard Troubleshooting Process (Follow This)
1. docker-compose ps → Check status, locate problematic service
2. docker-compose logs <service> → Find key error messages in logs
3. docker-compose config → Validate config file syntax
4. docker inspect <container> → Deep inspection (when necessary)
5. Isolated testing → Start problematic service separatelyDevelop this habit, won’t be clueless when problems arise.
Common Cleanup Commands (Regular Maintenance)
# Stop and remove containers (keep volumes)
docker-compose down
# Delete volumes too (use cautiously!)
docker-compose down -v
# Clean dangling resources (unused networks, images, etc.)
docker system prune
# Complete cleanup (including all images)
docker system prune -a
# Rebuild without cache
docker-compose build --no-cache
# Check Docker disk usage
docker system dfI run docker system prune every Friday before leaving work, cleaning up the week’s accumulated garbage. Once found Docker using 50GB disk, after cleanup only 10GB remained…
Preventive Measures
Configuration Validation:
# Validate config file before starting
docker-compose configThis command checks YAML syntax, discovers configuration errors.
Health Checks:
services:
web:
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80/health"]
interval: 30s
timeout: 10s
retries: 3With healthcheck, you can quickly discover services that started but aren’t actually healthy.
Reasonable Restart Policies:
services:
app:
restart: unless-stopped # Recommended: always restart unless manually stopped
# restart: always # Always restart
# restart: on-failure # Only restart on failureCentralized Environment Variable Management:
# .env file
DB_PASSWORD=your_password
API_KEY=your_key
# docker-compose.yml
services:
app:
environment:
- DB_PASSWORD=${DB_PASSWORD}
- API_KEY=${API_KEY}This way changing configuration doesn’t require modifying YAML file, convenient for team collaboration.
Conclusion
Back to the opening scenario: Friday afternoon 3:30 PM, deadline approaching, containers won’t start. Now you know what to do:
- Don’t panic, take a deep breath
- Identify error type (port, network, build, exit, permission)
- Follow corresponding chapter’s solutions, try simple to complex in order
- If all else fails, check logs — the answer is there
Docker Compose errors aren’t scary; what’s scary is not having a systematic troubleshooting approach. Remember these 5 major error categories and corresponding solution patterns, next time you encounter problems, solve them in 5 minutes.
Final suggestion: build a team knowledge base, document pitfalls and solutions. Our team’s Wiki has a “Docker Common Issues” page, newcomers who read it avoid 80% of pitfalls.
Have you encountered any weird Docker Compose errors? Welcome to share in comments, might help others.
9 min read · Published on: Dec 17, 2025 · Modified on: Dec 26, 2025
Related Posts

Docker Container Debugging Guide: The Right Way to Use exec Command

Docker Container Exits Immediately? Complete Troubleshooting Guide (Exit Code 137/1 Solutions)

Comments
Sign in with GitHub to leave a comment