Docker Logs & Debugging

Debugging Docker containers is an essential skill. This guide covers docker logs, docker events, docker inspect, and various troubleshooting techniques to diagnose and fix container issues.

docker logs docker events docker inspect Troubleshooting
docker logs: Viewing Container Output

The `docker logs` command retrieves logs from a container. It captures stdout (standard output) and stderr (standard error) from the container's main process. Logs are essential for debugging application errors, checking startup issues, and monitoring runtime behavior.

# View all logs docker logs container_name # Follow logs in real-time (like tail -f) docker logs -f container_name # Show last N lines docker logs --tail 50 container_name # Show logs since timestamp docker logs --since 2024-01-01T10:00:00 container_name # Show logs for last 10 minutes docker logs --since 10m container_name # Show logs with timestamps docker logs -t container_name # Show logs from a specific container ID docker logs abc123def456 # Combine flags docker logs -f --tail 100 --timestamps container_name
Logs are stored on disk. Without log rotation, they can consume significant disk space. Configure log rotation in `/etc/docker/daemon.json` to manage size.
docker inspect: Detailed Container Information

The `docker inspect` command returns detailed JSON information about containers, images, networks, or volumes. It's invaluable for debugging configuration issues, checking mount points, examining network settings, and understanding container state.

# Inspect container docker inspect container_name # Get specific fields using Go templating docker inspect --format='{{.State.Status}}' container_name docker inspect --format='{{.NetworkSettings.IPAddress}}' container_name # Get multiple fields docker inspect --format='{{.Name}} - {{.State.Status}}' container_name # Get full state information docker inspect --format='{{json .State}}' container_name | jq # Get mount points docker inspect --format='{{json .Mounts}}' container_name | jq # Get environment variables docker inspect --format='{{json .Config.Env}}' container_name | jq # Get container exit code docker inspect --format='{{.State.ExitCode}}' container_name # Inspect image docker inspect nginx:alpine # Inspect network docker inspect bridge
docker events: Real-time Container Events

The `docker events` command streams real-time events from the Docker daemon. It shows container lifecycle events (start, stop, kill, die, pause, unpause), image events (pull, push, delete), and network events. This is useful for monitoring and debugging cluster behavior.

# Stream all events docker events # Filter by event type docker events --filter event=start docker events --filter event=stop docker events --filter event=die # Filter by container docker events --filter container=container_name # Filter by image docker events --filter image=nginx # Filter by time docker events --since 10m docker events --since 2024-01-01 --until 2024-01-02 # Filter by type docker events --filter type=container docker events --filter type=image docker events --filter type=network # Combine filters docker events --filter event=die --filter container=web
docker diff: Checking Container Filesystem Changes

The `docker diff` command shows changes to the container's filesystem since it started. It displays added (A), changed (C), or deleted (D) files. This is useful for understanding what files your container modifies and for debugging permission issues.

# Show filesystem changes docker diff container_name # Output format: # C /etc/nginx/nginx.conf (changed) # A /var/log/nginx/access.log (added) # D /tmp/tempfile (deleted) # Find which files were written docker diff container_name | grep -E "^A" # Check for configuration changes docker diff container_name | grep -E "^C"
docker top: View Container Processes

The `docker top` command displays running processes inside a container. It's similar to `top` on Linux and helps identify which processes are consuming CPU and memory.

# Show processes in container docker top container_name # Show with custom ps options docker top container_name aux # Check CPU usage of container processes docker top container_name -o pid,pcpu,pmem,comm # Monitor process list watch -n 1 "docker top container_name"
docker stats: Resource Usage Monitoring

The `docker stats` command shows real-time resource usage statistics for containers, including CPU, memory, network I/O, and block I/O. It's essential for performance debugging and capacity planning.

# Show stats for all running containers docker stats # Show stats for specific containers docker stats container1 container2 # Show stats without streaming (one shot) docker stats --no-stream # Show stats with custom format docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" # Show all containers including stopped docker stats --all
Debugging a Failing Container

When a container fails to start or exits immediately, use these debugging steps:

# Step 1: Check container status and exit code docker ps -a docker inspect container_name --format='{{.State}}' # Step 2: View logs (even for stopped containers) docker logs container_name # Step 3: Check container exit code docker inspect container_name --format='{{.State.ExitCode}}' # Step 4: Run an interactive shell to investigate docker run -it --rm image_name sh # Step 5: Override entrypoint for debugging docker run -it --rm --entrypoint /bin/sh image_name # Step 6: Check resource limits docker inspect container_name --format='{{.HostConfig.Memory}}' docker inspect container_name --format='{{.HostConfig.NanoCpus}}' # Step 7: Check volume mounts docker inspect container_name --format='{{json .Mounts}}' | jq
Logging Drivers: Configuring Log Storage

Docker supports multiple logging drivers to send container logs to different destinations. The default is `json-file` (local disk). For production, consider using `fluentd`, `splunk`, `awslogs`, or `gelf`.

# Configure logging driver for a container docker run --log-driver=json-file --log-opt max-size=10m --log-opt max-file=3 nginx # Use syslog driver docker run --log-driver=syslog --log-opt syslog-address=udp://localhost:514 nginx # Use fluentd driver docker run --log-driver=fluentd --log-opt fluentd-address=localhost:24224 nginx # Set default logging in daemon.json { "log-driver": "json-file", "log-opts": { "max-size": "10m", "max-file": "3" } } # Check container's logging driver docker inspect container_name --format='{{.HostConfig.LogConfig}}'
Common Debugging Scenarios
# Scenario 1: Container exits immediately docker logs container_name # Look for error messages # Scenario 2: Container runs but no network access docker exec container_name curl localhost:8080 docker exec container_name nslookup google.com # Scenario 3: Permission denied errors docker exec container_name ls -la /data docker inspect container_name --format='{{json .Config.User}}' # Scenario 4: Container is slow docker stats container_name docker top container_name # Scenario 5: Disk space full docker system df docker system prune -a # Scenario 6: Port already in use docker ps --filter "publish=8080" lsof -i :8080 # on Linux/macOS
Debugging with docker exec

The `docker exec` command allows you to run commands inside a running container. This is the most powerful debugging tool for inspecting the container's filesystem, checking processes, and testing network connectivity.

# Get interactive shell docker exec -it container_name bash docker exec -it container_name sh # Run a single command docker exec container_name ls -la /app docker exec container_name cat /etc/nginx/nginx.conf # Check environment variables docker exec container_name env # Check network connectivity docker exec container_name curl http://google.com docker exec container_name ping database # Check DNS resolution docker exec container_name nslookup database docker exec container_name cat /etc/resolv.conf # Check open ports docker exec container_name netstat -tulpn docker exec container_name ss -tulpn
Debugging Best Practices
  • Use structured logging - Log in JSON format for easier parsing.
  • Set log rotation limits - Prevent disk space exhaustion with `max-size` and `max-file`.
  • Use container names - Easy to reference in commands.
  • Label your containers - Add labels like `project`, `environment` for filtering.
  • Enable debug mode - Set `"debug": true` in daemon.json for verbose daemon logs.
  • Use docker system events - Monitor cluster-wide events for anomalies.
  • Keep images minimal - Smaller images have fewer moving parts and are easier to debug.
  • Implement health checks - Let Docker detect unhealthy containers.
Frequently Asked Questions
Why can't I see logs for my container?
The container may have stopped or is using a logging driver that doesn't store logs locally (like syslog or none). Check `docker ps -a` to see if the container exists, and verify the logging driver with `docker inspect container_name`.
How do I clear container logs?
You can truncate the log file: `truncate -s 0 $(docker inspect container_name --format='{{.LogPath}}')`. Or simply remove and recreate the container (if stateless).
Why does my container exit immediately with exit code 1?
Exit code 1 means the main process failed. Check `docker logs container_name` to see the error. Common causes: missing config files, port conflicts, or command errors.
How do I debug a container that won't start at all?
Override the entrypoint to run a shell: `docker run -it --entrypoint /bin/sh image_name`. Then manually run the application command to see errors.
What's the difference between docker events and docker logs?
`docker logs` shows application stdout/stderr. `docker events` shows Docker daemon events (container start/stop, image pull, network create). They serve different debugging purposes.
How do I view logs for a container that was deleted?
Once a container is removed (`docker rm`), its logs are gone. Use a centralized logging system (ELK, Loki, Datadog) for persistent logs.
Why is docker stats showing high memory usage?
Containers use memory as they run. Use `docker inspect container_name | grep -A 5 Memory` to check memory limits. Consider setting `--memory` limits to prevent excessive usage.
How do I get more verbose Docker daemon logs?
Edit `/etc/docker/daemon.json` and add `"debug": true`. Restart Docker: `sudo systemctl restart docker`. Then check `journalctl -u docker -f` for logs.
Previous: Container Runtimes in K8s Next: Container Performance

Mastering Docker logs and debugging commands will save you hours of troubleshooting. Practice these commands to become proficient in container debugging.