$docker.recipes
·13 min read·Updated February 2026

Debugging Docker Compose: A Practical Troubleshooting Guide

The systematic approach to diagnosing and fixing common Docker Compose problems — from container crashes to networking issues to volume permission errors.

docker-composedebuggingtroubleshootinglogs

01A Systematic Approach to Docker Debugging

When a Docker container isn't working, there's a temptation to start changing random things — different images, different ports, different environment variables — until something works. I've been there. It's frustrating and slow. Over the years, I've developed a systematic debugging approach that solves most Docker Compose issues in under 10 minutes. The key insight is that 90% of problems fall into just four categories: container not starting, container starting but crashing, networking issues, and volume/permission problems. Each has a specific diagnostic path.

02Container Won't Start

If docker compose up shows an error or the container immediately exits, start here:
[terminal]
1# Check container status and exit codes
2docker compose ps -a
3
4# Read the logs (most answers are here)
5docker compose logs servicename
6
7# Check if the image exists and can be pulled
8docker compose pull servicename
9
10# Validate your compose file syntax
11docker compose config
12
13# Check for port conflicts
14docker compose ps --format "table {{.Name}} {{.Ports}}"
15# Or check host ports directly
16ss -tlnp | grep :8080

03Container Starts Then Crashes

A container that starts and immediately exits is usually a configuration problem. The exit code tells you what happened: Exit code 0: The container completed successfully. If you expected it to run continuously, check that the entrypoint/command keeps a foreground process running. Exit code 1: Generic application error. Read the logs carefully — the error message is almost always there. Exit code 137: Killed by the system (OOM). The container ran out of memory. Increase the memory limit or reduce the application's memory usage. Exit code 139: Segmentation fault. Usually a bug in the application or incompatible architecture (running an amd64 image on arm64).
[terminal]
1# Check exit code
2docker inspect --format='{{.State.ExitCode}}' container_name
3
4# Check if OOM killed
5docker inspect --format='{{.State.OOMKilled}}' container_name
6
7# Run the container interactively to debug
8docker compose run --rm servicename sh
9
10# Check resource usage of running containers
11docker stats --no-stream

docker compose run --rm servicename sh is your best friend for debugging. It starts a new container with the same configuration but drops you into a shell where you can inspect files, test connectivity, and run commands manually.

04Networking Issues

"Connection refused" between containers is the most common networking problem. The diagnostic steps: Verify containers are on the same network: docker network inspect networkname shows which containers are connected. Containers on different networks can't communicate. Use the service name, not container_name: Docker Compose DNS resolves service names (the key in your YAML), not container_name values. Check the target port is the container port, not the host port: When connecting between containers, use the internal port (e.g., 5432 for PostgreSQL), not the mapped host port.
[terminal]
1# List networks and their containers
2docker network ls
3docker network inspect myapp_default
4
5# Test connectivity from inside a container
6docker compose exec app ping db
7docker compose exec app nslookup db
8
9# Check if a port is listening inside the container
10docker compose exec db ss -tlnp

05Volume and Permission Problems

Permission denied errors with volumes are extremely common, especially with non-root containers. The issue is a mismatch between the user inside the container and the owner of the mounted files. Diagnosis: Check what user the container runs as (docker compose exec servicename id) and what user owns the files on the host (ls -la on the volume path). Common fixes: - Set user: "1000:1000" in your compose file to match your host user - Use named volumes instead of bind mounts (Docker manages permissions) - Run an init container that sets correct permissions before the main container starts - Set PUID and PGID environment variables (supported by linuxserver.io images) Permission issues with volumes account for roughly a third of all Docker Compose problems I help people debug. Getting the user/group mapping right from the start saves hours of frustration. The troubleshooting sections in our recipes on docker.recipes address these permission patterns for each specific service.

About the Author

Frank Pegasus

DevOps engineer and self-hosting enthusiast with over a decade of experience running containerized workloads in production. Creator of docker.recipes.