How to Debug Crashing Docker Containers?
Debugging crashing Docker containers means identifying why a container starts, fails, exits, restarts, or enters a crash loop in development, staging, or production environments.
Why Docker Containers Crash
A Docker container stays alive only while its main process is running. If the main process exits, the container exits.
Container Starts
|
Main Process Starts
|
Main Process Fails
|
Container Exits
|
Restart Policy May Restart It
In production, this may appear as:
- Container restarting continuously
- Application unavailable
- 502 Bad Gateway from Nginx
- API gateway unable to route traffic
- Database connection failures
Real-Time Production Example
Consider a Docker Compose-based microservices platform:
Nginx
API Gateway
Portfolio Service
Interview Service
Payment Service
MySQL
Redis
Prometheus
Grafana
If payment-service keeps crashing, user payments fail. If
api-gateway keeps restarting, the whole platform becomes unavailable.
Common Reasons Containers Crash
| Reason | Example |
|---|---|
| Application exception | Spring Boot startup failure |
| Missing environment variable | DB_URL not configured |
| Wrong command | Invalid CMD or ENTRYPOINT |
| Dependency unavailable | MySQL not ready |
| Permission issue | Cannot write to mounted volume |
| Out of memory | OOMKilled |
| Port conflict | Host port already in use |
Step 1: Check Container Status
docker ps -a
Look at the STATUS column.
Example
payment-service Restarting (1) 10 seconds ago
api-gateway Exited (1) 2 minutes ago
mysql Up 5 minutes
Status Meaning
| Status | Meaning |
|---|---|
| Exited (0) | Process completed successfully |
| Exited (1) | Application or command failed |
| Restarting | Container is in crash loop |
| OOMKilled | Container killed due to memory limit |
Step 2: Check Container Logs
docker logs container-name
Follow Logs
docker logs -f container-name
Show Last 100 Lines
docker logs --tail=100 container-name
Logs usually reveal the actual error.
Spring Boot Crash Example
Failed to configure a DataSource:
'url' attribute is not specified
Root Cause
DB_URL missing
Fix
environment:
DB_URL: jdbc:mysql://mysql:3306/payment_db
DB_USERNAME: ${DB_USERNAME}
DB_PASSWORD: ${DB_PASSWORD}
Debugging Flow
Container Crashing
|
docker ps -a
|
docker logs
|
Find Error Message
|
Fix Config / Code / Dependency
|
Restart Container
Step 3: Inspect Exit Code
docker inspect container-name --format='{{.State.ExitCode}}'
Common Exit Codes
| Exit Code | Meaning |
|---|---|
| 0 | Success |
| 1 | General application error |
| 126 | Command cannot execute |
| 127 | Command not found |
| 137 | Killed, often memory issue |
| 143 | Terminated gracefully |
Check OOMKilled Status
docker inspect container-name --format='{{.State.OOMKilled}}'
If output is true, the container was killed because of memory pressure.
Step 4: Inspect Full Container Details
docker inspect container-name
Check:
- Environment variables
- Mount paths
- Network settings
- Restart policy
- Memory limits
- Command and entrypoint
Step 5: Check Environment Variables
docker inspect container-name --format='{{json .Config.Env}}'
Missing or incorrect environment variables are a very common production issue.
Common Spring Boot Variables
SPRING_PROFILES_ACTIVE
DB_URL
DB_USERNAME
DB_PASSWORD
JWT_SECRET
GOOGLE_CLIENT_ID
GOOGLE_CLIENT_SECRET
RAZORPAY_KEY_ID
RAZORPAY_KEY_SECRET
Step 6: Debug Docker Compose Services
docker compose ps
docker compose logs -f service-name
docker compose config
docker compose config is very useful because it shows the final resolved
Compose configuration after applying environment variables.
Step 7: Check Dependency Readiness
Many containers crash because dependencies are not ready.
Example
API starts before MySQL is ready
Error
Communications link failure
Connection refused
Fix Using Health Checks
mysql:
image: mysql:8.0
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
Important Note About depends_on
depends_on controls startup order only. It does not always guarantee
application readiness.
Production applications should also have retry logic.
Step 8: Test Networking
If container starts but crashes after dependency calls, test internal networking.
docker exec -it api-gateway sh
ping mysql
curl http://portfolio-service:8080/actuator/health
nslookup mysql
Common Networking Issues
- Containers are on different networks
- Wrong service name used
- Application listens on localhost instead of 0.0.0.0
- Firewall blocks traffic
Correct Application Binding
Bad
server.address=localhost
Good
server.address=0.0.0.0
Step 9: Check Volume and Permission Issues
Containers may crash when they cannot read/write mounted paths.
Error Example
Permission denied: /uploads
Check Mounts
docker inspect container-name --format='{{json .Mounts}}'
Fix Ownership
sudo chown -R 1001:1001 /host/uploads
Match host path permissions with the container user UID/GID.
Step 10: Check Memory and CPU
docker stats
If memory keeps increasing, container may be killed by OOM.
Java Container Memory Example
ENTRYPOINT ["java", "-XX:+UseContainerSupport", "-XX:MaxRAMPercentage=75.0", "-jar", "app.jar"]
Compose Memory Limit Example
deploy:
resources:
limits:
memory: 768M
cpus: "1.0"
Step 11: Debug CMD and ENTRYPOINT
A wrong startup command can immediately crash the container.
Command Not Found Example
exec: "java": executable file not found in $PATH
Check Image Command
docker inspect image-name --format='{{json .Config.Entrypoint}} {{json .Config.Cmd}}'
Step 12: Start Container with Shell for Debugging
Override entrypoint and enter the container.
docker run --rm -it --entrypoint sh image-name
For bash-based images:
docker run --rm -it --entrypoint bash image-name
Debug Inside Container
ls -la
env
pwd
whoami
java -version
cat /etc/resolv.conf
Step 13: Check Image Build Problems
Sometimes the image does not contain the expected JAR, config file, or binary.
Check Files
docker run --rm -it --entrypoint sh image-name
ls -la /app
Common Issue
COPY --from=build /app/target/*.jar app.jar
If build output path is wrong, final image may miss the application artifact.
Step 14: Check Port Configuration
Wrong port configuration can make the app look down even if the container is running.
docker port container-name
Spring Boot Example
server.port=8080
Compose Mapping
ports:
- "9090:8080"
Step 15: Check Host-Level Problems
Sometimes the container is fine, but the host has problems.
Check Disk
df -h
docker system df
Check Inodes
df -i
Check Docker Daemon
sudo systemctl status docker
Step 16: Check Restart Policy
docker inspect container-name --format='{{json .HostConfig.RestartPolicy}}'
Recommended Production Policy
restart: unless-stopped
Restart policy helps availability, but it should not hide real application bugs.
Production Debugging Workflow
Container Down
|
docker ps -a
|
docker logs
|
docker inspect
|
Check Exit Code
|
Check Env / Network / Volume / Memory
|
Fix Root Cause
|
Redeploy
|
Monitor Logs and Metrics
Real Production Case Study
Problem
API Gateway container restarted continuously after deployment.
Investigation
docker compose logs -f api-gateway
Error Found
Could not resolve placeholder 'PAYMENT_SERVICE_URL'
Root Cause
Missing environment variable in production Compose file.
Fix
environment:
PAYMENT_SERVICE_URL: http://payment-service:8084
Prevention
- Use
docker compose configbefore deployment - Add application startup validation
- Add CI/CD deployment checks
Production Best Practices to Prevent Crashes
- Use health checks
- Validate environment variables
- Add retry logic for databases
- Use restart policies
- Set memory and CPU limits
- Use persistent volumes correctly
- Centralize logs
- Monitor with Prometheus and Grafana
- Use fixed image tags
- Run smoke tests after deployment
Useful Commands Summary
| Command | Purpose |
|---|---|
| docker ps -a | Check container status |
| docker logs | Read crash logs |
| docker inspect | Check full container config |
| docker stats | Check CPU/memory |
| docker compose logs | Read service logs |
| docker compose config | Validate resolved Compose config |
Interview Answer
To debug a crashing Docker container, I first check the container status using
docker ps -a, then inspect logs using docker logs
or docker compose logs. After that, I check the exit code,
OOMKilled status, environment variables, mounted volumes, network configuration,
resource limits, and startup command using docker inspect.
Most crashing containers fail due to application exceptions, missing environment variables, database connectivity issues, wrong CMD/ENTRYPOINT, permission problems, or memory limits. In production, I also verify health checks, restart policies, logs, metrics, and host disk space.
Quick Summary Table
| Problem | Debug Step |
|---|---|
| App error | docker logs |
| Missing env | docker inspect / docker compose config |
| OOMKilled | docker inspect + docker stats |
| Network issue | ping/curl/nslookup inside container |
| Permission issue | inspect mounts and UID/GID |
| Wrong entrypoint | override entrypoint with shell |
Useful Internal Links
- Docker Interview Questions
- Docker Compose Interview Questions
- DevOps Interview Questions
- Microservices Interview Questions
- Kubernetes Interview Questions
- Linux Interview Questions
Final Conclusion
Debugging crashing Docker containers requires a systematic approach: status, logs, exit code, environment variables, networking, volumes, resource limits, entrypoint, and host health.
In production, the best long-term solution is prevention through health checks, validated configuration, observability, restart policies, resource limits, persistent storage, and safe CI/CD deployment practices.