How to Debug Docker Containers on Debian 13
Introduction
In this tutorial, you learn how to debug Docker containers using practical, beginner friendly techniques. You identify issues by checking container status, analyzing logs, inspecting configuration, and accessing the container environment. This approach helps you quickly understand why a container fails and how to fix it.
End goal: By the end of this tutorial, you will be able to identify and troubleshoot common Docker container issues using logs, inspection, and runtime analysis tools.
Prerequisites
- Target audience: Beginner system administrators
- Estimated time: ~30 minutes
- Operating system: Debian 13
- Software: Docker 24.0 or later
- Permissions: User with sudo privileges or membership in the docker group
- Hardware requirements: At least 2 GB RAM and 10 GB free disk space
- Network requirements: Internet access for pulling images, no specific ports required for this tutorial
- Requirements: Basic command line usage and a running Docker service
- Compatibility: Tested on Debian 13 and works on Debian 12 and Ubuntu 22.04
Step 1: Check Docker System Information
Before debugging a specific container, verify that Docker itself is working correctly.
Run the following command:
docker system info
You see detailed information about the Docker environment, including:
- Server version
- Storage driver
- Number of containers and images
- CPU and memory availability
- Docker root directory
This helps you confirm that:
- Docker is running correctly
- The system has enough resources
- There are no global configuration issues
If Docker is not running, you may see an error such as "Cannot connect to the Docker daemon".
To check Docker service status:
systemctl status docker
You see whether the Docker service is active. If it is not running, start it:
sudo systemctl start docker
You should now see the service in active state.
Always verify Docker health before debugging containers. Many container issues are caused by Docker service or system-level problems.
Step 2: Check Container Status
Run the following command:
docker ps
You see a list of running containers with details such as container ID, image, and status. If your container appears with status "Up", it is currently running.
To include stopped containers:
docker ps -a
You now see all containers. If your container shows "Exited", it means it has stopped due to an error or completed execution.
A container stops when its main process exits. This is normal behavior but often indicates a problem if it exits unexpectedly.
Step 3: View Container Logs
Logs show what the application inside the container outputs. This is the most important step for debugging. You can get <CONTAINER_ID> via the docker ps command described in step 2.
Run:
docker logs <CONTAINER_ID>
You see application output, including errors and warnings. Look for messages that indicate failures such as missing files or connection errors.
To follow logs in real time:
docker logs -f <CONTAINER_ID>
You see new log entries as they appear. This is useful when restarting a container and observing behavior.
To view recent logs only:
docker logs --tail 50 <CONTAINER_ID>
You see the last 50 lines of output. This helps you focus on the most recent events.
Start with recent logs, then review full logs if needed.
Step 4: Inspect Container State
Docker stores detailed information about each container.
Run:
docker inspect <CONTAINER_ID>
You see a structured JSON output with configuration and runtime details.
To check container status:
docker inspect -f '{{.State.Status}}' <CONTAINER_ID>
You see a simple value such as "running" or "exited", which confirms the container state.
To check exit code:
docker inspect -f '{{.State.ExitCode}}' <CONTAINER_ID>
You see a number. A value of 0 means success, while any non zero value indicates an error.
To check restart policy:
docker inspect -f '{{.HostConfig.RestartPolicy.Name}}' <CONTAINER_ID>
You see whether the container is configured to restart automatically.
Exit codes help you understand why a container stopped. When a container exits, the main process inside it returns a numeric code to the system.
Common exit codes you may see:
0– The process completed successfully without errors. This usually means the container stopped normally. For example, a script finished its task and exited.1– A general error occurred. This is the most common failure code and usually means something inside the application failed, such as a missing file, invalid configuration, or runtime error.125– Docker failed to run the container. This usually indicates a problem with the docker run command itself, such as invalid options or incorrect parameters.126– The command inside the container cannot be executed. This often means permission issues or that the file is not executable.127– The command was not found. This typically means the specified binary or script does not exist inside the container.137– The container was stopped forcefully. This often happens when the system runs out of memory and kills the container process.139– The container crashed with a segmentation fault. This indicates a serious application error, often related to memory access issues.143– The container was stopped gracefully. This usually happens when you run docker stop and the container shuts down correctly.
Focus first on codes 1, 127, and 137, as they are the most common during troubleshooting. Always combine the exit code with docker logs to understand the exact cause of the failure.
Step 5: Access the Container Environment
Sometimes logs are not enough. You can enter the container to inspect it directly.
Run:
docker exec -it <CONTAINER_ID> /bin/bash
You enter an interactive shell inside the container.
If bash is not available:
docker exec -it <CONTAINER_ID> /bin/sh
You can now explore the container.
Check running container processes from host:
docker top <CONTAINER_ID>
You see active processes inside the container. If the main process is missing, the container may stop.
Verify configuration files and test commands manually inside the container.
Step 6: Monitor Resource Usage
Containers may fail due to limited resources.
Run:
docker stats
You see real time CPU, memory, and network usage for all containers.
To monitor a specific container:
docker stats <CONTAINER_ID>
You see a live table that updates continuously with resource usage for all running containers. Each row represents a container, and each column shows a specific type of resource usage.
The most important columns are:
- CPU % – Shows how much CPU the container is using. High values may indicate heavy processing or inefficient code.
- MEM USAGE / LIMIT – Shows how much memory the container is using compared to its limit. If usage is close to the limit, the container may slow down or be stopped.
- MEM % – Percentage of memory used relative to the limit.
- NET I/O – Network traffic. This shows how much data the container has received and sent. High values may indicate heavy network activity.
- BLOCK I/O – Disk read and write activity. This column shows how much data the container has read from and written to disk.
- PIDs – Number of processes running inside the container. A very high number may indicate a process leak or runaway application.
If BLOCK I/O is constantly increasing, the container is actively using storage. This is normal for databases, but unexpected spikes may indicate inefficient disk usage or excessive logging. When debugging, look for unusual spikes in CPU, memory, or BLOCK I/O. Combine this information with docker logs to understand what the container is doing at that moment.
Step 7: Check Docker Events
Docker records events that describe what is happening at the system and container level. These events help you understand when a container starts, stops, crashes, or restarts.
Run the following command:
docker events
You see a live stream of events such as container start, stop, and restart. The output updates continuously in real time.
Press Ctrl + C to stop the live stream.
Filter Events for a Specific Container
Run:
docker events --filter container=<CONTAINER_ID>
You see only events related to the selected container. This helps you focus on a single workload.
Show Events from a Specific Time Range
To view events from a specific point in time:
docker events --since 10m
You see events from the last 10 minutes.
To define both start and end time:
docker events --since 2026-01-01T10:00:00 --until 2026-01-01T11:00:00
You see events that occurred within that time range.
You can use relative time like 10m, 1h, or full timestamps.
Format Event Output
Run:
docker events --format '{{.Time}} {{.Type}} {{.Action}} {{.Actor.ID}}'
You see formatted output with selected fields. This makes it easier to read or integrate with scripts.
Use formatting to highlight only the information you need during debugging.
Filter Specific Event Types
You can filter events to focus on specific problems.
Container Stops or Crashes
Run:
docker events --filter event=die
You see events when containers stop. This helps identify unexpected shutdowns.
Out of Memory Events
Run:
docker events --filter event=oom
You see events when a container is killed due to memory limits. This is critical for diagnosing resource issues.
OOM means Out Of Memory. The system stops the container when it exceeds available memory.
Container Restarts
Run:
docker events --filter event=restart
You see when containers restart. Frequent restart events may indicate a crash loop.
Combine Filters and Time Range
Run:
docker events --since 10m --filter event=die
You see container stop events from the last 10 minutes. This helps narrow down recent failures.
Combine filters and time ranges to quickly identify patterns such as repeated crashes or memory issues.
Step 8: Check Disk Usage and Clean Up Unused Images
Docker stores images, containers, volumes, and cache on disk. Over time, unused data can consume significant space and cause issues.
Run the following command:
docker system df
You see a summary of disk usage, including:
- Images
- Containers
- Local volumes
- Build cache
Each section shows:
- Total count
- Active items
- Size
- Reclaimable space
This helps you understand how much disk space Docker is using and how much can be cleaned up.
The "Reclaimable" column shows how much space can be freed by removing unused resources.
To view unused images run:
docker images -f dangling=true
You see images that are not tagged and not used by any container. These are safe candidates for removal.
To remove unused images run:
docker image prune
You are prompted to confirm. After confirmation, unused images are deleted and disk space is freed.
To remove all unused images, not just dangling ones:
docker image prune -a
You remove all images that are not used by any container.
Important: This command removes images that may be needed later. Ensure no required containers depend on them.
Regular cleanup helps prevent disk space issues that can cause containers to fail or behave unpredictably.
Verification and Testing
- Run
docker psand confirm the container status is correct. - Run
docker logsand verify that errors are identified or resolved. - Run
docker inspectand confirm status and exit code match expectations. - Use
docker execto confirm processes are running inside the container. - If debugging is successful, the container should remain in running state without critical errors in logs.
Reverting Changes
If you made changes during debugging, you can restore a clean state.
Back up important data before removing containers.
Stop a container:
docker stop <CONTAINER_ID>
You see confirmation that the container has stopped.
Remove a container:
docker rm <CONTAINER_ID>
You see confirmation that the container has been removed.
Recreate the container:
docker run <OPTIONS> <IMAGE_NAME>
A new container is created from the image.
Important: Removing a container deletes its runtime state. Data is lost unless stored in volumes.
Troubleshooting
Container exits immediately
Check docker logs for error messages. These usually explain the issue.
Cannot access container
Ensure it is running using docker ps.
No logs available
Ensure the application writes output to stdout or stderr.
Container restarts repeatedly
Check restart policy and logs to identify crash loops.
High resource usage
Use docker stats to confirm CPU or memory spikes.
Conclusion
You learned how to debug Docker containers by checking their status, analyzing logs, inspecting configuration, and accessing the container environment. These techniques allow you to identify and resolve common issues quickly. As a next step, explore Docker Compose debugging and centralized logging systems for managing multiple containers.