DEV Community

AttractivePenguin
AttractivePenguin

Posted on

Docker Compose Services Won't Start? Here's Your Debugging Playbook

Docker Compose Services Won't Start? Here's Your Debugging Playbook

You've just added a new service to your docker-compose.yml, run docker compose up -d, and... nothing. The container exits immediately, restarts in an infinite loop, or just sits there refusing to work. No helpful error message. Just frustration.

Sound familiar? Every developer who works with Docker Compose has been there. The good news is that container failures follow predictable patterns. Once you know where to look, you can diagnose most issues in under five minutes.

This guide will walk you through a systematic debugging approach, from the most common causes to the edge cases that make you question your life choices.


The First Thing You Should Do

Before diving into logs and configuration files, run this single command:

docker compose ps -a
Enter fullscreen mode Exit fullscreen mode

The -a flag is crucial—it shows all containers, including the ones that exited. Without it, you'd only see running containers, which isn't helpful when debugging failures.

The output tells you the current state of each service. But the real gold is in the exit codes:

Exit Code What It Means
0 Container finished successfully (normal for one-shot tasks)
1 Application error—your code crashed
137 Container was killed (OOM or docker stop)
139 Segmentation fault—usually a bug in the application or library
143 Container received SIGTERM—clean shutdown

If you see exit code 137, your container ran out of memory. Exit code 1? Your application threw an unhandled error. This single command often points you directly to the problem.


Step 2: Actually Read the Logs

Logs are your primary debugging tool, but most developers use them incorrectly. Here's the right way:

# View logs for a specific service
docker compose logs api

# Follow logs in real time (most useful)
docker compose logs -f api

# Show only the last 100 lines (when logs are noisy)
docker compose logs --tail=100 api

# Include timestamps (for timing issues)
docker compose logs -t api
Enter fullscreen mode Exit fullscreen mode

Sometimes a container exits so fast it produces no logs. In that case, run the service in the foreground:

docker compose up api
Enter fullscreen mode Exit fullscreen mode

This runs the service attached to your terminal, so you'll see every output line before it exits.


The 10 Most Common Causes (And How to Fix Them)

1. Image Pull Failures

Your service can't start because Docker can't find or pull the image.

Symptoms: Container stays in "creating" state or exits immediately with image-related error.

# Check if the image exists locally
docker compose images

# Force pull images
docker compose pull
Enter fullscreen mode Exit fullscreen mode

Fix: Verify the image name and tag. If using a private registry, make sure you're logged in:

docker login registry.example.com
Enter fullscreen mode Exit fullscreen mode

2. Port Conflicts

Another process is already using the port you're trying to bind.

Symptoms: Error message like Bind for 0.0.0.0:3000 failed: port is already allocated

# Find what's using the port
lsof -i :3000

# Or use ss
ss -tlnp | grep 3000
Enter fullscreen mode Exit fullscreen mode

Fix: Either stop the conflicting process or change the host port in your compose file:

services:
  api:
    ports:
      - "3001:3000"  # Changed host port to 3001
Enter fullscreen mode Exit fullscreen mode

3. Volume Mount Errors

A bind mount references a directory that doesn't exist on the host.

Symptoms: Error response from daemon: invalid mount config for type "bind": bind source path does not exist

Fix: Docker won't create bind mount directories for you. Create them before starting:

mkdir -p ./data ./config ./logs
docker compose up -d
Enter fullscreen mode Exit fullscreen mode

4. Dependency Failures

A service depends on another service that isn't healthy yet.

Symptoms: Service exits immediately after startup, even though dependencies are running.

services:
  app:
    depends_on:
      db:
        condition: service_healthy
Enter fullscreen mode Exit fullscreen mode

Debug: Check the health status:

# Check health check logs
docker inspect $(docker compose ps -q db) --format '{{json .State.Health}}' | python3 -m json.tool
Enter fullscreen mode Exit fullscreen mode

Fix: Increase health check retries or start_period:

healthcheck:
  test: ["CMD-SHELL", "pg_isready -U postgres"]
  interval: 10s
  timeout: 10s
  retries: 10
  start_period: 30s  # Give the service time to initialize
Enter fullscreen mode Exit fullscreen mode

5. OOM Killed (Out of Memory)

The container ran out of memory and was killed by the kernel.

Symptoms: Exit code 137, or container restarts repeatedly with no logs.

# Check if a container was OOM killed
docker inspect $(docker compose ps -q api) --format '{{.State.OOMKilled}}'
Enter fullscreen mode Exit fullscreen mode

You can also check kernel logs:

dmesg | grep -i "killed process"
Enter fullscreen mode Exit fullscreen mode

Fix: Increase the memory limit:

services:
  api:
    deploy:
      resources:
        limits:
          memory: 1G  # Increase from default
Enter fullscreen mode Exit fullscreen mode

6. Entrypoint or Command Errors

The container's entrypoint or command is wrong, or a shell script has issues.

Symptoms: Container exits with code 127 (command not found) or immediately after startup.

# Override the command to get a shell
docker compose run --rm --entrypoint sh api
Enter fullscreen mode Exit fullscreen mode

Common issues:

  • The binary doesn't exist in the image
  • Shell script is missing executable permissions
  • Windows-style line endings (CRLF) in shell scripts

The CRLF issue is sneaky—it works on Windows but fails on Linux:

# Convert CRLF to LF in entrypoint scripts
sed -i 's/\r$//' entrypoint.sh
Enter fullscreen mode Exit fullscreen mode

Or prevent it by configuring Git:

git config --global core.autocrlf false
Enter fullscreen mode Exit fullscreen mode

7. Environment Variable Issues

Missing or incorrect environment variables cause crashes at startup.

Symptoms: Application logs show "environment variable not set" or similar errors.

# Check what environment variables are set
docker compose config | grep -A 50 "api:"

# Or inside the container
docker compose run --rm api env | sort
Enter fullscreen mode Exit fullscreen mode

Fix: Make required variables explicit:

services:
  api:
    environment:
      DATABASE_URL: ${DATABASE_URL:?DATABASE_URL must be set}
      SECRET_KEY: ${SECRET_KEY:?SECRET_KEY must be set}
Enter fullscreen mode Exit fullscreen mode

The :? syntax causes Docker Compose to fail with a clear error message if the variable isn't set.


8. Network Issues

The container can't reach a service it needs.

Symptoms: Connection timeouts, DNS resolution failures, "connection refused" errors.

# Check network connectivity
docker compose exec api ping db

# Check DNS resolution
docker compose exec api nslookup db

# Check if the target port is open
docker compose exec api nc -zv db 5432
Enter fullscreen mode Exit fullscreen mode

Fix: Ensure all services that need to communicate are on the same network:

services:
  api:
    networks:
      - backend
  db:
    networks:
      - backend

networks:
  backend:
Enter fullscreen mode Exit fullscreen mode

Important: Never use localhost for inter-container communication. Use the service name instead. This is the #1 networking mistake.


9. File Permission Issues

The container process can't read or write to mounted volumes.

Symptoms: Permission denied errors in logs, or application can't write data.

# Check what user the container runs as
docker compose exec api id

# Check permissions on the mounted directory
docker compose exec api ls -la /app/data
Enter fullscreen mode Exit fullscreen mode

Fix: Set correct ownership or run the container as the right user:

services:
  api:
    user: "1000:1000"
    volumes:
      - ./data:/app/data
Enter fullscreen mode Exit fullscreen mode

Or fix permissions on the host:

sudo chown -R 1000:1000 ./data
Enter fullscreen mode Exit fullscreen mode

10. Compose File Syntax Errors

A typo or indentation error in the compose file.

Symptoms: Docker Compose fails to parse the file, or services don't start.

# Validate the compose file syntax
docker compose config -q
Enter fullscreen mode Exit fullscreen mode

If there are errors, show the full output:

docker compose config
Enter fullscreen mode Exit fullscreen mode

Common syntax problems:

  • Incorrect indentation (YAML requires spaces, not tabs)
  • Using tabs instead of spaces
  • Missing quotes around values with special characters
  • Incorrect variable interpolation syntax

The Nuclear Option: Start Fresh

When nothing else works, sometimes the cleanest approach is to start from scratch:

# Stop everything and remove all resources
docker compose down -v --remove-orphans

# Remove all cached images for this project
docker compose down --rmi all

# Clean up Docker system (optional)
docker system prune -f

# Start fresh
docker compose up --build
Enter fullscreen mode Exit fullscreen mode

This is especially useful after updating Docker, after changing base images, or when you've tried everything else and just want a clean slate.


Your Debug Checklist

When a service won't start, go through this checklist in order:

# 1. Validate compose file syntax
docker compose config -q

# 2. Check service status and exit codes
docker compose ps -a

# 3. Read service logs
docker compose logs --tail=50 <service>

# 4. Check container state details
docker inspect $(docker compose ps -q <service>) --format '{{json .State}}'

# 5. Check if image exists
docker compose images

# 6. Check port conflicts
docker compose ps --format "table {{.Name}}\t{{.Ports}}"

# 7. Check volume mounts exist
docker compose config --volumes

# 8. Check environment variables
docker compose run --rm <service> env

# 9. Get a shell in the container
docker compose run --rm --entrypoint sh <service>

# 10. Check Docker daemon logs (last resort)
sudo journalctl -u docker --since "10 minutes ago"
Enter fullscreen mode Exit fullscreen mode

FAQ

Q: My container keeps restarting. How do I debug it?

Use docker compose logs -f <service> to follow logs in real-time. If it restarts too quickly, run it in the foreground with docker compose up <service> to catch the initial output.

Q: Why does my container work locally but fail in CI?

Check for differences in environment variables, volume paths, and available resources (memory/CPU). CI environments often have resource limits that your local machine doesn't.

Q: How do I debug a container that exits immediately with no logs?

Run it interactively:

docker compose run --rm --entrypoint sh <service>
Enter fullscreen mode Exit fullscreen mode

Then try running your command manually to see what happens.

Q: What's the difference between docker compose up and docker compose run?

up creates and starts all services defined in the compose file. run creates a one-off container for a specific service, which is useful for debugging or running one-time commands.


Conclusion

Docker Compose startup failures are frustrating, but they're not mysterious. Most issues fall into a handful of categories: port conflicts, missing volumes, OOM kills, network issues, or configuration errors.

The key is to be systematic. Start with docker compose ps -a to see exit codes, then docker compose logs to see what happened. If those don't reveal the problem, inspect the container state and work through the common causes.

And when all else fails—the nuclear option exists for a reason. Sometimes a clean slate is the fastest path to a working system.


Found this helpful? Bookmark the debug checklist above for quick reference.

Top comments (0)