Day 5 - Debug a Broken Container
Troubleshoot and fix a container that fails to start. Learn essential debugging techniques for containerized applications.
Description
Your application container keeps crashing immediately after startup. The logs show cryptic errors, and you need to figure out what's wrong. This is a common scenario in production environments where containers fail due to configuration issues, missing dependencies, or runtime errors.
Task
Debug and fix a broken Docker container that crashes on startup.
Requirements:
- Identify why the container is crashing
- Fix the underlying issue
- Verify the container runs successfully
- Document the root cause
Target
- ✅ Container starts and stays running
- ✅ Application responds to health checks
- ✅ No errors in container logs
- ✅ Root cause identified and documented
Sample App
Broken Dockerfile
FROM node:18-alpine
WORKDIR /app
# Missing package.json copy!
RUN npm install
COPY . .
# Wrong port exposed
EXPOSE 8080
# Incorrect startup command
CMD ["node", "server.js"]
Application Code (server.js)
const express = require('express');
const app = express();
// Port from environment variable
const PORT = process.env.PORT || 3000;
app.get('/health', (req, res) => {
res.json({ status: 'healthy' });
});
app.get('/', (req, res) => {
res.send('Hello from fixed container!');
});
app.listen(PORT, () => {
console.log(`Server running on port ${PORT}`);
});
package.json
{
"name": "broken-app",
"version": "1.0.0",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.18.0"
}
}
View Solution
Solution
Debugging Steps
1. Check Container Status
# List all containers including stopped ones
docker ps -a
# Expected output shows container exited
# CONTAINER ID IMAGE STATUS
# abc123def456 broken-app Exited (1) 2 seconds ago
2. View Container Logs
# Check logs for errors
docker logs <container-id>
# Or with follow mode
docker logs -f <container-id>
# Common errors you might see:
# - Cannot find module 'express'
# - ENOENT: no such file or directory
# - Port already in use
3. Inspect the Image
# Check image layers
docker history broken-app:latest
# Inspect container configuration
docker inspect <container-id>
4. Interactive Debugging
# Override entrypoint to explore container
docker run -it --entrypoint /bin/sh broken-app:latest
# Inside container, check:
ls -la /app # Check files
cat package.json # Verify dependencies
npm list # Check installed packages
Fixed Dockerfile
FROM node:18-alpine
WORKDIR /app
# Copy package files first (better layer caching)
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Correct port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {process.exit(r.statusCode === 200 ? 0 : 1)})"
# Use npm start for better signal handling
CMD ["npm", "start"]
docker-compose.yml (for easier testing)
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- PORT=3000
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/health"]
interval: 30s
timeout: 3s
retries: 3
start_period: 5s
Explanation
Common Container Issues
1. Missing Dependencies
Problem:
RUN npm install # Before copying package.json
Solution:
COPY package*.json ./
RUN npm ci --only=production
Why it matters: Layer ordering is crucial. Dependencies must be defined before installation.
2. Port Mismatch
Problem:
EXPOSE 8080 # But app listens on 3000
Solution:
EXPOSE 3000
# And ensure environment variable matches
ENV PORT=3000
3. Improper Signal Handling
Problem:
CMD ["node", "server.js"] # Doesn't handle SIGTERM
Solution:
CMD ["npm", "start"] # Better signal propagation
Or use tini:
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "server.js"]
Debugging Toolkit
Essential Commands
# View real-time logs
docker logs -f --tail 100 <container>
# Execute command in running container
docker exec -it <container> /bin/sh
# View resource usage
docker stats <container>
# Inspect container details
docker inspect <container> | jq '.[0].State'
# View processes in container
docker top <container>
Common Error Patterns
| Error | Likely Cause | Solution |
|---|---|---|
Cannot find module |
Missing npm install | Copy package.json before RUN |
EADDRINUSE |
Port conflict | Change port or stop conflicting service |
ENOENT |
File not found | Verify COPY commands |
Permission denied |
Wrong user/permissions | Use correct USER or fix permissions |
Exit code 137 |
Out of memory | Increase memory limit |
Health Checks
# HTTP health check
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget --quiet --tries=1 --spider http://localhost:3000/health || exit 1
# TCP health check
HEALTHCHECK --interval=30s --timeout=3s \
CMD nc -z localhost 3000 || exit 1
# Custom script
HEALTHCHECK --interval=30s --timeout=3s \
CMD /app/healthcheck.sh || exit 1
Try to solve the challenge yourself first!
Click "Reveal Solution" when you're ready to see the answer.
Result
After fixing the issues:
# Build the fixed image
docker build -t fixed-app:latest .
# Run the container
docker run -d -p 3000:3000 --name my-app fixed-app:latest
# Verify it's running
docker ps
# CONTAINER ID IMAGE STATUS PORTS
# xyz789abc123 fixed-app:latest Up 30 seconds (healthy) 0.0.0.0:3000->3000/tcp
# Test the application
curl http://localhost:3000
# Hello from fixed container!
curl http://localhost:3000/health
# {"status":"healthy"}
# Check logs
docker logs my-app
# Server running on port 3000
Validation
Test Checklist
# 1. Container starts successfully
docker ps | grep my-app
# Should show "Up" status
# 2. Health check passes
docker inspect my-app | jq '.[0].State.Health.Status'
# Should return "healthy"
# 3. Application responds
curl -f http://localhost:3000/health
# Should return 200 OK
# 4. No errors in logs
docker logs my-app --tail 50
# Should show normal startup messages
# 5. Container handles restart
docker restart my-app && sleep 5 && curl http://localhost:3000
# Should respond after restart
Advanced Debugging
Use Multi-Stage Builds for Debugging
# Debug stage
FROM node:18-alpine AS debug
WORKDIR /app
COPY package*.json ./
RUN npm install # Include dev dependencies
COPY . .
CMD ["npm", "run", "dev"]
# Production stage
FROM node:18-alpine AS production
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
CMD ["npm", "start"]
Build debug version:
docker build --target debug -t app:debug .
Docker Events Monitoring
# Monitor container events
docker events --filter container=my-app
# Monitor all events
docker events --since '2023-12-05T00:00:00' --until '2023-12-05T23:59:59'
Performance Debugging
# Limit resources for testing
docker run -d \
--memory="256m" \
--cpus="0.5" \
--name resource-limited \
fixed-app:latest
# Monitor resource usage
docker stats resource-limited
Best Practices
✅ Do's
- Use health checks: Detect issues early
- Check logs first: Most issues are logged
- Use .dockerignore: Prevent unnecessary files
- Layer caching: Order Dockerfile for optimal caching
- Run as non-root: Security best practice
❌ Don'ts
- Don't ignore exit codes: They indicate failure types
- Don't use
:latestin prod: Pin versions - Don't run as root: Security risk
- Don't store secrets in images: Use secrets management
- Don't use
ADDwhenCOPYworks: Less confusion
Links
- Docker Debugging Guide
- Dockerfile Best Practices
- Docker Health Checks
- Container Troubleshooting
- Docker CLI Reference
Share Your Success
Fixed your broken container? Share your debugging journey!
Tag @thedevopsdaily on X with:
- What was broken
- How you debugged it
- The fix you applied
- Screenshot of healthy container
Use hashtags: #AdventOfDevOps #Docker #Debugging #Day5
Ready to complete this challenge?
Mark this challenge as complete once you've finished the task. We'll track your progress!
Completed this challenge? Share your success!
Tag @thedevopsdaily on X (Twitter) and share your learning journey with the community!
These amazing companies help us create free, high-quality DevOps content for the community
DigitalOcean
Cloud infrastructure for developers
Simple, reliable cloud computing designed for developers
DevDojo
Developer community & tools
Join a community of developers sharing knowledge and tools
Want to support DevOps Daily and reach thousands of developers?
Become a SponsorFound an issue?