Chapter 3: Container Lifecycle Management
9/1/25About 8 min
Chapter 3: Container Lifecycle Management
Learning Objectives
- Master the creation, starting, stopping, and deletion of containers
- Learn container port mapping and data mounting
- Understand the state transitions of the container lifecycle
- Become proficient in container monitoring and log viewing
Knowledge Points
Container Lifecycle States
A Docker container goes through several states from creation to destruction. Understanding these states helps in better container management.
Container State Transition Diagram:
┌─────────┐ docker create ┌─────────┐ docker start ┌─────────┐
│ None │ ──────────────────→ │ Created │ ──────────────────→ │ Running │
└─────────┘ └─────────┘ └─────────┘
│ │
│ docker run (create + start) │
└──────────────────────────────┘
│
▼
┌─────────┐ docker rm ┌─────────┐ docker stop/kill ┌─────────┐
│ Removed │ ◄───────────────── │ Exited │ ◄─────────────────── │ Paused │
└─────────┘ └─────────┘ └─────────┘
▲ │
│ docker pause │
│◄─────────────────────────────┘
│ docker unpause
└──────────────────────────────►
Detailed Container States
State | Description | Related Command |
---|---|---|
Created | Created but not started | docker create |
Running | Currently running | docker start, docker run |
Paused | Paused | docker pause |
Restarting | Currently restarting | docker restart |
Exited | Exited | docker stop, docker kill |
Dead | Dead (abnormal state) | System anomaly |
Removing | Being deleted | docker rm |
Container Run Modes
Docker containers support multiple run modes:
Foreground Mode
- The container runs in the foreground, and the console displays the container's output.
- Use Ctrl+C to stop the container.
- Suitable for development and debugging.
Detached Mode
- The container runs in the background and does not occupy the current terminal.
- Use the
-d
parameter to start. - Suitable for production environments.
Interactive Mode
- Keeps STDIN open and allocates a pseudo-TTY.
- Use the
-it
parameters to start. - Suitable for scenarios requiring user interaction.
Basic Container Operations
Creating and Running Containers
# Create a container (without starting it)
docker create --name my-nginx nginx:latest
# Start a created container
docker start my-nginx
# One-step: create and start a container
docker run nginx:latest
# Run a container in the background
docker run -d --name web-server nginx:latest
# Run a container interactively
docker run -it ubuntu:20.04 /bin/bash
# Specify a container name
docker run -d --name my-web-server nginx:latest
# Run and remove the container upon exit
docker run --rm hello-world
# Set a restart policy
docker run -d --restart=always --name persistent-nginx nginx:latest
docker run -d --restart=on-failure:3 --name retry-nginx nginx:latest
# Limit resource usage
docker run -d --name limited-nginx \
--memory=512m \
--cpus=0.5 \
nginx:latest
Container State Management
# View container status
docker ps # View running containers
docker ps -a # View all containers
docker ps --filter "status=running" # Filter running containers
docker ps --filter "name=nginx" # Filter containers with names containing nginx
# Start and stop containers
docker start my-nginx # Start a container
docker stop my-nginx # Gracefully stop a container (sends SIGTERM)
docker kill my-nginx # Force stop a container (sends SIGKILL)
# Restart a container
docker restart my-nginx # Restart a container
# Pause and resume containers
docker pause my-nginx # Pause all processes in a container
docker unpause my-nginx # Resume all processes in a container
# Wait for a container to exit
docker wait my-nginx # Block and wait for a container to exit, returns the exit code
Viewing Container Information
# View detailed container information
docker inspect my-nginx
# View container resource usage
docker stats my-nginx # Display resource usage in real-time
docker stats --no-stream my-nginx # Display resource usage once
# View container processes
docker top my-nginx # View processes inside a container
# View container port mappings
docker port my-nginx # Show a container's port mappings
# View container filesystem changes
docker diff my-nginx # Show changes to a container's filesystem
Interactive Container Operations
# Enter a running container
docker exec -it my-nginx /bin/bash # Recommended way, creates a new process
docker attach my-nginx # Attach to the container's main process (not recommended)
# Execute a single command in a container
docker exec my-nginx ls -la /etc/nginx
docker exec my-nginx cat /etc/nginx/nginx.conf
docker exec my-nginx nginx -t # Test nginx configuration
# Execute a command as a specific user
docker exec -u root my-nginx whoami # Execute as root
docker exec -u 1000:1000 my-nginx id # Execute with a specific UID:GID
# Set the working directory
docker exec -w /etc/nginx my-nginx pwd
Port Mapping
Basic Port Mapping
# Map to a random port
docker run -d -P nginx:latest # Automatically map all EXPOSEd ports to random ports
# Map to a specific port
docker run -d -p 8080:80 nginx:latest # Host port 8080 -> Container port 80
docker run -d -p 127.0.0.1:8080:80 nginx # Bind only to the local interface
# Map multiple ports
docker run -d \
-p 8080:80 \
-p 8443:443 \
nginx:latest
# Map a UDP port
docker run -d -p 53:53/udp alpine:latest # Map a UDP port
Port Mapping Management
# View port mappings
docker port my-nginx # View a container's port mappings
docker ps # View ports in the container list
# Dynamically add port mappings (requires recreating the container)
# 1. Commit the current container as an image
docker commit my-nginx my-nginx:backup
# 2. Stop and remove the original container
docker stop my-nginx
docker rm my-nginx
# 3. Recreate the container with new port mappings
docker run -d --name my-nginx -p 8080:80 -p 8443:443 my-nginx:backup
# Dynamically add port mappings using iptables (advanced technique)
# Find the container's IP address
CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-nginx)
# Add an iptables rule
sudo iptables -t nat -A DOCKER -p tcp --dport 9090 -j DNAT --to-destination $CONTAINER_IP:80
Port Mapping Examples
# Web server example
docker run -d --name web-server \
-p 80:80 \
-p 443:443 \
nginx:latest
# Database service example
docker run -d --name mysql-server \
-p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=mypassword \
mysql:8.0
# Development environment example (Node.js app)
docker run -d --name nodejs-app \
-p 3000:3000 \
-v $(pwd):/app \
-w /app \
node:16 npm start
Data Mounting
Comparison of Mount Types
Mount Type | Syntax | Use Case | Persistence |
---|---|---|---|
Bind Mount | -v /host/path:/container/path | Mount host directory | High |
Named Volume | -v volume-name:/container/path | Docker-managed volume | High |
Anonymous Volume | -v /container/path | Anonymous volume | Medium |
tmpfs Mount | --tmpfs /container/path | In-memory filesystem | Low |
Directory Bind Mounts
# Bind mount a host directory
docker run -d --name nginx-with-content \
-p 8080:80 \
-v /home/user/html:/usr/share/nginx/html \
nginx:latest
# Read-only mount
docker run -d --name nginx-readonly \
-p 8080:80 \
-v /home/user/html:/usr/share/nginx/html:ro \
nginx:latest
# Mount multiple directories
docker run -d --name nginx-multi-mount \
-p 8080:80 \
-v /home/user/html:/usr/share/nginx/html \
-v /home/user/conf:/etc/nginx/conf.d \
-v /home/user/logs:/var/log/nginx \
nginx:latest
# Use a relative path
docker run -d --name app-dev \
-p 3000:3000 \
-v $(pwd):/app \
-w /app \
node:16 npm start
Volume Management
# Create a named volume
docker volume create my-data-volume
docker volume create --driver local web-data
# View volumes
docker volume ls
docker volume inspect my-data-volume
# Use a named volume
docker run -d --name mysql-with-volume \
-v my-data-volume:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=password \
mysql:8.0
# Backup a volume
# 1. Create a backup container
docker run --rm \
-v my-data-volume:/source \
-v $(pwd):/backup \
ubuntu tar czf /backup/backup.tar.gz -C /source .
# 2. Restore a volume
docker run --rm \
-v my-data-volume:/target \
-v $(pwd):/backup \
ubuntu tar xzf /backup/backup.tar.gz -C /target
# Clean up unused volumes
docker volume prune
tmpfs Mounts
# Create an in-memory filesystem mount
docker run -d --name app-with-tmpfs \
--tmpfs /tmp:rw,size=100m,mode=1777 \
nginx:latest
# View tmpfs mounts
docker inspect app-with-tmpfs | grep -A 5 "Tmpfs"
Container Monitoring and Logging
Container Log Management
# View container logs
docker logs my-nginx # View all logs
docker logs -f my-nginx # Follow logs in real-time
docker logs --tail 50 my-nginx # Show the last 50 lines
docker logs --since="2023-01-01" my-nginx # Show logs since a specific time
docker logs --until="2023-01-02" my-nginx # Show logs until a specific time
# Show timestamps
docker logs -t my-nginx # Show timestamps
# Formatted logs
docker logs --details my-nginx # Show extra details
# Limit log output
docker logs --tail 100 -f my-nginx | head -20
Log Driver Configuration
# Configure the log driver (in daemon.json)
sudo tee /etc/docker/daemon.json <<EOF
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
}
}
EOF
# Restart the Docker service
sudo systemctl restart docker
# Set the log driver for a specific container
docker run -d --name nginx-custom-log \
--log-driver json-file \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx:latest
# Disable logging
docker run -d --name nginx-no-logs \
--log-driver none \
nginx:latest
# Use the syslog driver
docker run -d --name nginx-syslog \
--log-driver syslog \
--log-opt syslog-address=tcp://192.168.1.100:514 \
nginx:latest
Container Performance Monitoring
# Monitor container resource usage in real-time
docker stats # Monitor all running containers
docker stats my-nginx # Monitor a specific container
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" # Formatted output
# View resource usage once
docker stats --no-stream my-nginx
# Monitor container events
docker events # Display Docker events in real-time
docker events --filter container=my-nginx # Filter events for a specific container
docker events --since="1h" # Show events from the last hour
Advanced Monitoring Tools
# Monitor containers with ctop (requires ctop installation)
sudo wget https://github.com/bcicen/ctop/releases/download/v0.7.7/ctop-0.7.7-linux-amd64 -O /usr/local/bin/ctop
sudo chmod +x /usr/local/bin/ctop
ctop
# Use the docker system command
docker system df # View Docker disk usage
docker system events # View system events
docker system prune # Clean up the system
# Export container performance data
docker stats --format "{{.Container}},{{.CPUPerc}},{{.MemUsage}}" --no-stream > stats.csv
Practical Exercises
Complete Web App Deployment
# 1. Create project directory structure
mkdir -p ~/docker-webapp/{html,conf,logs}
# 2. Create web content
cat > ~/docker-webapp/html/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
<title>Docker Web App</title>
<style>
body { font-family: Arial; margin: 40px; background: #f5f5f5; }
.container { max-width: 800px; margin: 0 auto; background: white; padding: 30px; border-radius: 10px; box-shadow: 0 0 20px rgba(0,0,0,0.1); }
.status { background: #e8f5e8; padding: 15px; border-left: 4px solid #4CAF50; margin: 20px 0; }
</style>
</head>
<body>
<div class="container">
<h1>🐳 Dockerized Web App</h1>
<div class="status">
<h3>✅ App Status: Running</h3>
<p>Server Time: <span id="time"></span></p>
</div>
<h2>Features:</h2>
<ul>
<li>✨ Containerized Deployment</li>
<li>🔄 Data Persistence</li>
<li>📊 Real-time Monitoring</li>
<li>📝 Log Management</li>
</ul>
</div>
<script>
document.getElementById('time').textContent = new Date().toLocaleString();
setInterval(() => {
document.getElementById('time').textContent = new Date().toLocaleString();
}, 1000);
</script>
</body>
</html>
EOF
# 3. Create nginx configuration
cat > ~/docker-webapp/conf/default.conf << 'EOF'
server {
listen 80;
server_name localhost;
# Access log
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ =404;
}
# API endpoint example
location /api/status {
add_header Content-Type application/json;
return 200 '{"status":"running","timestamp":"$time_iso8601","server":"$hostname"}';
}
# Health check endpoint
location /health {
access_log off;
add_header Content-Type text/plain;
return 200 "OK";
}
}
EOF
# 4. Start the web app container
docker run -d --name webapp \
--restart=unless-stopped \
-p 8080:80 \
-v ~/docker-webapp/html:/usr/share/nginx/html:ro \
-v ~/docker-webapp/conf:/etc/nginx/conf.d:ro \
-v ~/docker-webapp/logs:/var/log/nginx \
--log-opt max-size=10m \
--log-opt max-file=3 \
nginx:alpine
# 5. Verify deployment
echo "Waiting for container to start..."
sleep 3
# Check container status
docker ps | grep webapp
# Test the web service
curl -s http://localhost:8080 | grep -o '<title>[^<]*'
curl -s http://localhost:8080/api/status | jq .
curl -s http://localhost:8080/health
# 6. Monitor and manage
echo "=== Container Info ==="
docker inspect webapp | jq '.[0].State'
echo "=== Resource Usage ==="
docker stats --no-stream webapp
echo "=== Port Mappings ==="
docker port webapp
echo "=== Recent Logs ==="
docker logs --tail 10 webapp
Development Environment Setup
# 1. Node.js development environment
mkdir ~/my-node-app
cd ~/my-node-app
# Create package.json
cat > package.json << 'EOF'
{
"name": "docker-node-app",
"version": "1.0.0",
"main": "server.js",
"scripts": {
"start": "node server.js",
"dev": "nodemon server.js"
},
"dependencies": {
"express": "^4.18.0"
},
"devDependencies": {
"nodemon": "^2.0.0"
}
}
EOF
# Create application code
cat > server.js << 'EOF'
const express = require('express');
const app = express();
const PORT = process.env.PORT || 3000;
app.get('/', (req, res) => {
res.json({
message: 'Hello from Dockerized Node.js App!',
timestamp: new Date().toISOString(),
env: process.env.NODE_ENV || 'development'
});
});
app.get('/health', (req, res) => {
res.json({ status: 'healthy' });
});
app.listen(PORT, '0.0.0.0', () => {
console.log(`Server running on port ${PORT}`);
});
EOF
# 2. Run the development container
docker run -it --rm \
--name node-dev \
-p 3000:3000 \
-v $(pwd):/app \
-w /app \
-e NODE_ENV=development \
node:16-alpine \
sh -c "npm install && npm run dev"
# Test in another terminal
curl http://localhost:3000
curl http://localhost:3000/health
Container Management Best Practices
- Naming Conventions: Use meaningful names for containers for easy management and identification.
- Restart Policies: Use appropriate restart policies in production, such as
--restart=unless-stopped
. - Resource Limits: Set reasonable CPU and memory limits for containers.
- Log Management: Configure log rotation to prevent log files from becoming too large.
- Monitoring and Alerting: Establish container monitoring and alerting mechanisms.
- Security Configuration: Avoid running applications as root, use read-only mounts to protect configuration files.
Important Notes
- Data not persisted will be lost when a container is deleted.
- Port mapping conflicts can cause container startup to fail.
- Too many containers can consume system resources; regularly clean up stopped containers.
- In a production environment, it is recommended to use orchestration tools rather than managing containers individually.
Summary
By completing this chapter, you should have mastered:
- Container State Management: Understood the container lifecycle and state transitions.
- Container Operations: Proficient use of container creation, startup, stopping, deletion, etc.
- Port Mapping: Mastered the configuration of port mappings between containers and the host.
- Data Mounting: Learned to use various mounting methods for data persistence.
- Monitoring and Logging: Able to effectively monitor container performance and manage logs.
In the next chapter, we will learn about Dockerfile build techniques to automate the building of customized Docker images.