Debugging Docker Issues
1. Inspecting Container Exit Codes
| Exit Code | Description | Common Cause |
|---|---|---|
| 0 | Successful termination | Container completed its task without errors |
| 1 | General error | Application or command failed to execute properly |
| 125 | Container failed to start | Docker daemon issue or invalid configuration |
| 126 | Command cannot be executed | Permission denied or command not found |
| 127 | Command not found | Executable path is incorrect or missing |
| 137 | Killed by SIGKILL | OOM (Out of Memory) or manual kill |
| 143 | Killed by SIGTERM | Graceful shutdown initiated by Docker or application |
Note: Use
docker inspect to get detailed exit code information for stopped containers.
2. Viewing Container Logs for Errors
| Command | Description | Notes |
|---|---|---|
| docker logs <container> | View the logs of a running or stopped container | Shows all logs since container started |
| docker logs -f <container> | Follow logs in real-time | Useful for monitoring ongoing activity |
| docker logs --since <time> <container> | View logs since a specific time | Format: 2024-01-01T12:00:00 or 1h |
| docker logs --until <time> <container> | View logs until a specific time | Format: 2024-01-01T12:00:00 or 1h |
| docker logs --tail <number> <container> | View only the last N lines of logs | Useful for debugging recent errors |
| docker logs --details <container> | View detailed log information | Includes timestamps and stream types |
Note: Logs are stored in a container's filesystem and will be lost if the container is removed. Use
docker logs --details to get more context about log entries.
Warning: Large containers or long-running applications can produce massive logs. Use
--tail or --since to limit output.
3. Executing Shell in Container
| Command | Description | Notes |
|---|---|---|
| docker exec -it <container_id> /bin/bash | Execute an interactive shell session in a running container | Use /bin/sh for POSIX shell or /bin/bash for bash shell |
| docker exec -it <container_id> /bin/sh | Execute an interactive shell session using POSIX shell | More portable across different container images |
| docker exec -d <container_id> <command> | Execute a command in the background without attaching to shell | Useful for running one-time commands or scripts |
Example: Executing Shell in Container
$ docker exec -it my_container /bin/bash
root@abc123:/# ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.1 0.2 12345 6789 ? Ss 09:00 0:01 /usr/bin/some_process
root 45 0.0 0.1 12345 6789 ? R+ 09:01 0:00 ps aux
root@abc123:/# exit
Note: The
-it flags are essential for interactive sessions. -i keeps STDIN open, and -t allocates a pseudo-TTY.
Warning: Be cautious when running commands as root inside containers. Ensure you understand the implications of executing shell commands in a production environment.
4. Checking Container Resource Usage
| Resource | Command | Description |
|---|---|---|
| CPU Usage | docker stats <container> |
Shows real-time CPU usage of a running container |
| Memory Usage | docker stats <container> |
Shows real-time memory consumption of a running container |
| Disk I/O | docker stats <container> |
Displays disk read/write operations for the container |
| Network I/O | docker stats <container> |
Shows network input/output for the container |
Note: The
docker stats command provides live updates. Use Ctrl+C to stop the stream.
| Flag | Description | Usage |
|---|---|---|
| --no-stream | Display stats once and exit | docker stats --no-stream myapp |
| --format | Format output using Go template | docker stats --format "table {{.Name}}\t{{.CPUPerc}}" |
| --all | Include stopped containers | docker stats --all myapp |
5. Inspecting Network Connectivity
| Command | Description | Example |
|---|---|---|
| docker network ls | List all Docker networks | docker network ls |
| docker network inspect <network> | Inspect a specific network's configuration | docker network inspect bridge |
| docker exec -it <container> ping <host> | Ping another host from within a container | docker exec -it myapp ping google.com |
| docker exec -it <container> netstat -tuln | Check listening ports inside a container | docker exec -it webapp netstat -tuln |
Example: Testing Internal Container Connectivity
docker run -d --name test-container nginx
docker exec -it test-container ping 172.17.0.1
Note: The default
bridge network allows containers to communicate with each other by default.
Warning: If containers are on different networks, they may not be able to communicate without proper network configuration.
6. Verifying Volume Mounts
| Command | Description | Example |
|---|---|---|
| docker inspect | Inspect container configuration including mounts | docker inspect <container_id> | grep -A 10 "Mounts" |
| docker volume ls | List all volumes | docker volume ls |
| docker volume inspect | Inspect specific volume details | docker volume inspect <volume_name> |
Example: Check mounted volumes in a running container
docker inspect my_container | grep -A 15 "Mounts"
Note: Ensure the volume paths exist on the host machine and have correct permissions.
Warning: If a volume is mounted to a directory that already contains data, it will be hidden by the mount.
7. Testing Port Mappings
| Command | Description | Example |
|---|---|---|
| docker port | Lists port mappings for a running container | docker port my-container |
| docker ps | Shows running containers with port mappings in the PORTS column | docker ps |
| netstat / ss | Check host-level port bindings (Linux) | ss -tuln | grep :8080 |
Note: If
docker port returns no output, the container may not be exposing the port correctly or the mapping was not applied.
8. Checking Dockerfile Syntax
| Command | Description | Notes |
|---|---|---|
| docker build | docker build --file <Dockerfile> |
Validate Dockerfile syntax without building the image |
| docker build --dry-run | docker build --dry-run . |
Simulate the build process to check for syntax errors |
| docker validate | docker validate <Dockerfile> |
Validate Dockerfile syntax using Docker CLI (if supported) |
Note: The
--dry-run flag is not available in all Docker versions. For older versions, use docker build --file <Dockerfile> to check syntax.
Warning: Ensure that the Dockerfile path is correct to avoid unintended validation of a different file.
9. Validating docker-compose.yml
| Command | Description | Notes |
|---|---|---|
| docker-compose config | Validate and view the configuration | Checks syntax and shows effective config |
| docker-compose config --quiet | Validate without outputting config | Useful for CI/CD validation |
| docker-compose config --no-ansi | Disable ANSI color codes | Helpful for logs or scripts |
Note: The
docker-compose config command will show errors if the YAML is malformed or contains invalid keys.
Warning: Invalid
docker-compose.yml files will cause docker-compose config to exit with a non-zero status code.
Validation Steps
- Run
docker-compose configto validate syntax - Check for missing or incorrect service definitions
- Ensure all environment variables are properly set
- Verify volume and network configurations
10. Using Docker Events for Troubleshooting
| Filter | Description | Usage Example |
|---|---|---|
| event | Filter by event type (e.g., die, start) |
--filter event=die |
| container | Filter by container name or ID | --filter container=webapp |
| image | Filter by image name | --filter image=nginx |
| status | Filter by status (e.g., create, kill) |
--filter status=kill |
Note: Docker events are useful for real-time monitoring of container lifecycle changes.
Common Event Types
create- Container createdstart- Container starteddie- Container exitedkill- Container killedoom- Out of memory event
11. Analyzing Image Layers
| Command | Description | Example |
|---|---|---|
| docker history | Shows the history of an image's layers | docker history myapp:latest |
| docker inspect | Displays detailed low-level information about an image or container | docker inspect myapp:latest |
| docker image ls --digests | List images with their digests to understand layer differences | docker image ls --digests |
Note: The
docker history command does not show the full command that created each layer, but it provides a high-level view of how the image was built.
12. Debugging Build Failures
| Issue | Description | Solution |
|---|---|---|
| Build context too large | Exceeds Docker's 100MB limit for build context | Use .dockerignore to exclude unnecessary files |
| Missing dependencies | Build fails due to missing packages or files | Ensure all required files are in context; use COPY carefully |
| Permission errors | Build fails due to file permissions in the container | Use RUN chmod or USER directive to adjust permissions |
| Syntax errors in Dockerfile | Invalid Dockerfile syntax causes build to fail | Validate Dockerfile using docker build --dry-run |
Note: Use
--no-cache to ensure all steps are re-run and logs are fresh.
Warning: Avoid including large files or directories in the build context to prevent long build times and errors.