Chapter 3: Container Lifecycle Management

Haiyue
18min

Chapter 3: Container Lifecycle Management

Learning Objectives
  • Master container creation, starting, stopping, and deletion
  • Learn container port mapping and data mounting
  • Understand container lifecycle state transitions
  • Become proficient in container monitoring and log viewing

Key Concepts

Container Lifecycle States

Docker containers go through multiple states from creation to destruction. Understanding these states helps better manage containers.

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
                                      └──────────────────────────────►

Container State Details

StateDescriptionRelated Commands
CreatedCreated but not starteddocker create
RunningCurrently runningdocker start, docker run
PausedPauseddocker pause
RestartingRestartingdocker restart
ExitedExiteddocker stop, docker kill
DeadDead (abnormal state)System exception
RemovingBeing removeddocker rm

Container Running Modes

Docker containers support multiple running modes:

Foreground Mode

  • Container runs in foreground, console displays container output
  • Can stop container with Ctrl+C
  • Suitable for development and debugging

Detached Mode (Background)

  • Container runs in background, doesn’t occupy current terminal
  • Started with -d parameter
  • Suitable for production environment services

Interactive Mode

  • Keeps STDIN open, allocates pseudo-TTY
  • Started with -it parameter
  • Suitable for scenarios requiring user interaction

Basic Container Operations

Creating and Running Containers

# Create container (without starting)
docker create --name my-nginx nginx:latest

# Start created container
docker start my-nginx

# One-step: create and start container
docker run nginx:latest

# Run container in background
docker run -d --name web-server nginx:latest

# Run container interactively
docker run -it ubuntu:20.04 /bin/bash

# Specify container name
docker run -d --name my-web-server nginx:latest

# Remove container after running
docker run --rm hello-world

# Set 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 nginx in name

# Start and stop containers
docker start my-nginx              # Start container
docker stop my-nginx               # Graceful stop (send SIGTERM signal)
docker kill my-nginx               # Force stop (send SIGKILL signal)

# Restart container
docker restart my-nginx            # Restart container

# Pause and resume container
docker pause my-nginx              # Pause all processes in container
docker unpause my-nginx            # Resume all processes in container

# Wait for container to exit
docker wait my-nginx               # Block until container exits, return exit code

Viewing Container Information

# View detailed container information
docker inspect my-nginx

# View container resource usage
docker stats my-nginx              # Real-time resource usage
docker stats --no-stream my-nginx  # Show resource usage once

# View container processes
docker top my-nginx                # View processes inside container

# View container port mapping
docker port my-nginx               # Show container port mapping

# View container filesystem changes
docker diff my-nginx               # Show filesystem changes

Container Interaction Operations

# Enter running container
docker exec -it my-nginx /bin/bash    # Recommended, creates new process
docker attach my-nginx                # Connect to container's main process (not recommended)

# Execute single command in 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 as specific user
docker exec -u root my-nginx whoami   # Execute as root user
docker exec -u 1000:1000 my-nginx id  # Execute as specified UID:GID

# Set working directory
docker exec -w /etc/nginx my-nginx pwd

Port Mapping

Basic Port Mapping

# Map to random port
docker run -d -P nginx:latest         # Auto-map all EXPOSE ports to random ports

# Map to specified 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 to local interface only

# Map multiple ports
docker run -d \
    -p 8080:80 \
    -p 8443:443 \
    nginx:latest

# Map UDP port
docker run -d -p 53:53/udp alpine:latest    # Map UDP port

Port Mapping Management

# View port mapping
docker port my-nginx                   # View container port mapping
docker ps                             # View ports in container list

# Dynamically add port mapping (requires recreating container)
# 1. Commit current container as image
docker commit my-nginx my-nginx:backup

# 2. Stop and delete original container
docker stop my-nginx
docker rm my-nginx

# 3. Recreate container with new port mapping
docker run -d --name my-nginx -p 8080:80 -p 8443:443 my-nginx:backup

# Dynamically add port mapping using iptables (advanced)
# Find container IP address
CONTAINER_IP=$(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' my-nginx)

# Add 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

Mount Type Comparison

Mount TypeSyntaxUse CasePersistence
Bind Mount-v /host/path:/container/pathMount host directoryHigh
Named Volume-v volume-name:/container/pathDocker-managed volumeHigh
Anonymous Volume-v /container/pathAnonymous volumeMedium
tmpfs Mount--tmpfs /container/pathMemory filesystemLow

Directory Bind Mounting

# Bind mount 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 relative path
docker run -d --name app-dev \
    -p 3000:3000 \
    -v $(pwd):/app \
    -w /app \
    node:16 npm start

Volume Management

# Create 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 named volume
docker run -d --name mysql-with-volume \
    -v my-data-volume:/var/lib/mysql \
    -e MYSQL_ROOT_PASSWORD=password \
    mysql:8.0

# Volume backup
# 1. Create backup container
docker run --rm \
    -v my-data-volume:/source:ro \
    -v $(pwd):/backup \
    ubuntu tar czf /backup/backup.tar.gz -C /source .

# 2. Restore volume
docker run --rm \
    -v my-data-volume:/target \
    -v $(pwd):/backup \
    ubuntu tar xzf /backup/backup.tar.gz -C /target

# Clean unused volumes
docker volume prune

tmpfs Mounting

# Create memory filesystem mount
docker run -d --name app-with-tmpfs \
    --tmpfs /tmp:rw,size=100m,mode=1777 \
    nginx:latest

# View tmpfs mount
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                # Real-time log tracking
docker logs --tail 50 my-nginx         # Show last 50 lines
docker logs --since="2023-01-01" my-nginx  # Show logs after specified time
docker logs --until="2023-01-02" my-nginx  # Show logs before specified time

# Show timestamps
docker logs -t my-nginx                # Show timestamps

# Format logs
docker logs --details my-nginx         # Show additional details

# Limit log output
docker logs --tail 100 -f my-nginx | head -20

Log Driver Configuration

# Configure 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 Docker service
sudo systemctl restart docker

# Set log driver for 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 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

# Real-time monitoring of container resources
docker stats                          # Monitor all running containers
docker stats my-nginx                  # Monitor specific container
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" # Formatted output

# One-time resource usage view
docker stats --no-stream my-nginx

# Monitor container events
docker events                         # Real-time Docker events
docker events --filter container=my-nginx  # Filter specific container events
docker events --since="1h"            # Show events from last hour

Advanced Monitoring Tools

# Use ctop to monitor containers (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 docker system commands
docker system df                      # View Docker disk usage
docker system events                  # View system events
docker system prune                   # Clean system

# Export container performance data
docker stats --format "{{.Container}},{{.CPUPerc}},{{.MemUsage}}" --no-stream > stats.csv

Practical Exercise

Complete Web Application Deployment

# 1. Create project directory structure
mkdir -p ~/docker-webapp/{html,conf,logs}

# 2. Create web page 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>Docker Containerized Web Application</h1>
        <div class="status">
            <h3>Application 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 logs
    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 web application 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 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. Monitoring and management
echo "=== Container Information ==="
docker inspect webapp | jq '.[0].State'

echo "=== Resource Usage ==="
docker stats --no-stream webapp

echo "=== Port Mapping ==="
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 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
  1. Naming Convention: Use meaningful names for containers for easier management and identification
  2. Restart Policy: Use appropriate restart policies in production, such as --restart=unless-stopped
  3. Resource Limits: Set reasonable CPU and memory limits for containers
  4. Log Management: Configure log rotation to prevent log files from becoming too large
  5. Monitoring and Alerts: Establish container monitoring and alerting mechanisms
  6. Security Configuration: Avoid running applications as root user, use read-only mounts to protect configuration files
Important Notes
  • Data not persisted will be lost when container is deleted
  • Port mapping conflicts will cause container startup failures
  • Too many containers consume system resources, regularly clean stopped containers
  • Production environments should use orchestration tools rather than managing containers individually

Summary

Through this chapter, you should have mastered:

  • Container State Management: Understanding container lifecycle and state transitions
  • Container Operations: Proficiency in container creation, starting, stopping, and deletion
  • Port Mapping: Mastering container-to-host port mapping configuration
  • Data Mounting: Learning various mounting methods for data persistence
  • Monitoring and Logging: Effectively monitoring container performance and managing logs

In the next chapter, we’ll learn Dockerfile build technology and how to automate the building of customized Docker images.