Docker 入门实战:用10个案例带你玩转容器化

1. Docker 环境安装与配置

1.1 在 Ubuntu 系统上安装 Docker

创建安装脚本文件:install_docker.sh

bash 复制代码
#!/bin/bash

# 更新系统包列表
sudo apt-get update

# 安装必要的依赖包
sudo apt-get install -y \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg \
    lsb-release

# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

# 添加 Docker 稳定版仓库
echo \
  "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 更新包列表(包含 Docker 仓库)
sudo apt-get update

# 安装 Docker Engine
sudo apt-get install -y docker-ce docker-ce-cli containerd.io

# 将当前用户添加到 docker 组(避免每次使用 sudo)
sudo usermod -aG docker $USER

# 启动 Docker 服务
sudo systemctl start docker
sudo systemctl enable docker

# 验证安装
docker --version
echo "Docker 安装完成!请重新登录以使组权限生效。"

1.2 Docker 基础配置

创建配置文件:docker_daemon.json

json 复制代码
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "data-root": "/var/lib/docker",
  "storage-driver": "overlay2"
}

应用配置:

bash 复制代码
# 创建 docker 配置目录
sudo mkdir -p /etc/docker

# 复制配置文件
sudo cp docker_daemon.json /etc/docker/daemon.json

# 重启 docker 服务
sudo systemctl daemon-reload
sudo systemctl restart docker

# 验证配置
docker info

2. Docker 基础概念与命令

2.1 Docker 核心组件理解

创建学习文档:docker_concepts.md

markdown 复制代码
# Docker 核心概念

## 镜像 (Image)
- 只读模板,用于创建容器
- 分层存储结构
- 包含运行应用所需的所有内容

## 容器 (Container)
- 镜像的运行实例
- 具有独立的文件系统、网络和进程空间
- 可写层在只读镜像层之上

## 仓库 (Registry)
- 存储和分发镜像的地方
- Docker Hub 是官方公共仓库
- 可以搭建私有仓库

2.2 基础命令练习

创建练习脚本:basic_commands.sh

bash 复制代码
#!/bin/bash

# 查看 Docker 版本信息
docker version

# 查看系统信息
docker info

# 搜索镜像
docker search nginx

# 拉取镜像
docker pull nginx:latest

# 查看本地镜像
docker images

# 运行容器(前台运行)
docker run -it --name my-nginx nginx:latest

# 运行容器(后台运行)
docker run -d --name my-nginx-background -p 8080:80 nginx:latest

# 查看运行中的容器
docker ps

# 查看所有容器(包括停止的)
docker ps -a

# 停止容器
docker stop my-nginx-background

# 启动已停止的容器
docker start my-nginx-background

# 重启容器
docker restart my-nginx-background

# 进入容器内部
docker exec -it my-nginx-background bash

# 查看容器日志
docker logs my-nginx-background

# 查看容器详细信息
docker inspect my-nginx-background

# 删除容器
docker rm my-nginx-background

# 删除镜像
docker rmi nginx:latest

3. 第一个 Docker 应用:Hello World

3.1 创建简单的 Web 应用

创建应用文件:app.py

python 复制代码
from flask import Flask
import os
import socket

app = Flask(__name__)

@app.route('/')
def hello():
    container_id = socket.gethostname()
    return f'''
    <!DOCTYPE html>
    <html>
    <head>
        <title>Docker Hello World</title>
        <style>
            body {{
                font-family: Arial, sans-serif;
                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                margin: 0;
                padding: 0;
                display: flex;
                justify-content: center;
                align-items: center;
                height: 100vh;
                color: white;
            }}
            .container {{
                text-align: center;
                background: rgba(255, 255, 255, 0.1);
                padding: 40px;
                border-radius: 15px;
                backdrop-filter: blur(10px);
            }}
            h1 {{
                font-size: 2.5em;
                margin-bottom: 20px;
            }}
            p {{
                font-size: 1.2em;
                margin: 10px 0;
            }}
        </style>
    </head>
    <body>
        <div class="container">
            <h1>🚀 Docker Hello World!</h1>
            <p><strong>容器ID:</strong> {container_id}</p>
            <p><strong>环境:</strong> Python Flask in Docker</p>
            <p>🎉 恭喜!你的第一个Docker应用运行成功!</p>
        </div>
    </body>
    </html>
    '''

@app.route('/health')
def health():
    return {'status': 'healthy', 'service': 'hello-world'}

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

3.2 创建 Dockerfile

创建 Dockerfile 文件:Dockerfile

dockerfile 复制代码
# 使用官方 Python 运行时作为基础镜像
FROM python:3.9-slim

# 设置工作目录
WORKDIR /app

# 复制当前目录内容到容器的 /app 目录
COPY . /app

# 安装依赖
RUN pip install --no-cache-dir flask

# 暴露端口
EXPOSE 5000

# 定义环境变量
ENV NAME World

# 容器启动时运行应用
CMD ["python", "app.py"]

3.3 构建和运行应用

创建构建脚本:build_and_run.sh

bash 复制代码
#!/bin/bash

# 构建 Docker 镜像
docker build -t hello-world-app .

# 运行容器
docker run -d -p 5000:5000 --name hello-container hello-world-app

# 检查容器状态
docker ps

# 查看日志
docker logs hello-container

echo "应用已启动!访问 http://localhost:5000 查看结果"

4. Docker 容器网络配置

4.1 网络基础操作

创建网络操作脚本:network_demo.sh

bash 复制代码
#!/bin/bash

# 查看网络列表
docker network ls

# 创建自定义网络
docker network create --driver bridge my-custom-network

# 查看网络详情
docker network inspect my-custom-network

# 在自定义网络中运行容器
docker run -d --name web1 --network my-custom-network nginx:alpine
docker run -d --name web2 --network my-custom-network nginx:alpine

# 测试容器间通信
docker exec web1 ping web2

# 创建另一个网络
docker network create --driver bridge another-network

# 将容器连接到多个网络
docker network connect another-network web1

# 查看容器的网络配置
docker inspect web1 | grep -A 10 "Networks"

# 断开网络连接
docker network disconnect another-network web1

# 清理
docker stop web1 web2
docker rm web1 web2
docker network rm my-custom-network another-network

4.2 多容器应用网络配置

创建多容器应用文件:docker-compose-network.yml

yaml 复制代码
version: '3.8'

services:
  web:
    image: nginx:alpine
    container_name: nginx-web
    ports:
      - "8080:80"
    networks:
      - frontend
    depends_on:
      - api

  api:
    image: python:3.9-alpine
    container_name: python-api
    command: python -m http.server 8000
    networks:
      - frontend
      - backend
    working_dir: /app

  database:
    image: postgres:13-alpine
    container_name: postgres-db
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    networks:
      - backend
    volumes:
      - db_data:/var/lib/postgresql/data

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge

volumes:
  db_data:

运行多容器应用:

bash 复制代码
docker-compose -f docker-compose-network.yml up -d
docker network ls
docker-compose -f docker-compose-network.yml down

5. Docker 数据持久化

5.1 数据卷操作

创建数据卷管理脚本:volume_management.sh

bash 复制代码
#!/bin/bash

# 创建数据卷
docker volume create my-data

# 查看数据卷列表
docker volume ls

# 查看数据卷详情
docker volume inspect my-data

# 使用数据卷运行容器
docker run -d \
  --name mysql-container \
  -e MYSQL_ROOT_PASSWORD=password \
  -e MYSQL_DATABASE=testdb \
  -v my-data:/var/lib/mysql \
  mysql:8.0

# 查看数据卷使用情况
docker exec mysql-container df -h

# 创建备份卷
docker volume create backup-data

# 使用临时容器备份数据
docker run --rm \
  -v my-data:/source \
  -v backup-data:/backup \
  alpine tar czf /backup/mysql-backup.tar.gz -C /source .

# 查看备份文件
docker run --rm -v backup-data:/backup alpine ls -lh /backup

# 清理
docker stop mysql-container
docker rm mysql-container
docker volume rm my-data backup-data

5.2 绑定挂载实战

创建绑定挂载示例:bind_mount_demo.sh

bash 复制代码
#!/bin/bash

# 创建本地目录
mkdir -p /home/$USER/docker-data/website
mkdir -p /home/$USER/docker-data/config

# 创建示例网站文件
cat > /home/$USER/docker-data/website/index.html << 'EOF'
<!DOCTYPE html>
<html>
<head>
    <title>Bind Mount Demo</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            background: linear-gradient(45deg, #ff6b6b, #4ecdc4);
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            color: white;
        }
        .container {
            text-align: center;
            background: rgba(255, 255, 255, 0.2);
            padding: 40px;
            border-radius: 15px;
            backdrop-filter: blur(10px);
        }
    </style>
</head>
<body>
    <div class="container">
        <h1>🎯 Bind Mount 演示</h1>
        <p>这个页面来自宿主机的目录!</p>
        <p>实时修改 host 的文件会立即反映在容器中</p>
    </div>
</body>
</html>
EOF

# 使用绑定挂载运行 Nginx
docker run -d \
  --name nginx-bind-mount \
  -p 8081:80 \
  -v /home/$USER/docker-data/website:/usr/share/nginx/html \
  nginx:alpine

echo "访问 http://localhost:8081 查看绑定挂载的网站"

# 实时修改测试
echo "<p>🚀 实时更新测试成功!</p>" >> /home/$USER/docker-data/website/index.html

# 查看容器中的文件变化
docker exec nginx-bind-mount cat /usr/share/nginx/html/index.html

# 清理
docker stop nginx-bind-mount
docker rm nginx-bind-mount

6. Dockerfile 最佳实践

6.1 优化 Dockerfile

创建优化后的 Dockerfile:optimized.Dockerfile

dockerfile 复制代码
# 多阶段构建示例
# 阶段1: 构建阶段
FROM python:3.9-slim as builder

WORKDIR /app

# 复制 requirements 文件
COPY requirements.txt .

# 安装构建依赖和 Python 包
RUN apt-get update && apt-get install -y \
    gcc \
    g++ \
    && pip install --user -r requirements.txt \
    && apt-get remove -y gcc g++ \
    && apt-get autoremove -y \
    && rm -rf /var/lib/apt/lists/*

# 阶段2: 运行阶段
FROM python:3.9-slim

# 设置环境变量
ENV PYTHONUNBUFFERED=1 \
    PYTHONDONTWRITEBYTECODE=1 \
    PIP_NO_CACHE_DIR=1

WORKDIR /app

# 创建非root用户
RUN groupadd -r appuser && useradd -r -g appuser appuser

# 从构建阶段复制已安装的包
COPY --from=builder /root/.local /home/appuser/.local
COPY --chown=appuser:appuser . .

# 设置路径和非root用户
ENV PATH=/home/appuser/.local/bin:$PATH
USER appuser

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:5000/health || exit 1

# 暴露端口
EXPOSE 5000

# 启动命令
CMD ["python", "app.py"]

创建 requirements 文件:requirements.txt

txt 复制代码
Flask==2.3.3
requests==2.31.0
gunicorn==21.2.0

6.2 多阶段构建实战

创建多阶段构建示例:multi-stage.Dockerfile

dockerfile 复制代码
# 多阶段构建:Go 应用示例

# 阶段1: 构建阶段
FROM golang:1.19-alpine as builder

WORKDIR /app

# 下载依赖
COPY go.mod go.sum ./
RUN go mod download

# 复制源代码
COPY . .

# 构建应用
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main .

# 阶段2: 运行阶段
FROM alpine:latest

RUN apk --no-cache add ca-certificates

WORKDIR /root/

# 从构建阶段复制二进制文件
COPY --from=builder /app/main .

# 创建非root用户
RUN adduser -D -g '' appuser
USER appuser

# 暴露端口
EXPOSE 8080

# 启动应用
CMD ["./main"]

创建 Go 应用示例:main.go

go 复制代码
package main

import (
    "fmt"
    "log"
    "net/http"
    "os"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        hostname, _ := os.Hostname()
        fmt.Fprintf(w, `
        <!DOCTYPE html>
        <html>
        <head>
            <title>Go Docker App</title>
            <style>
                body {
                    font-family: Arial, sans-serif;
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    margin: 0;
                    padding: 0;
                    display: flex;
                    justify-content: center;
                    align-items: center;
                    height: 100vh;
                    color: white;
                }
                .container {
                    text-align: center;
                    background: rgba(255, 255, 255, 0.1);
                    padding: 40px;
                    border-radius: 15px;
                    backdrop-filter: blur(10px);
                }
            </style>
        </head>
        <body>
            <div class="container">
                <h1>🐹 Go + Docker</h1>
                <p><strong>容器ID:</strong> %s</p>
                <p>多阶段构建成功!</p>
            </div>
        </body>
        </html>
        `, hostname)
    })

    log.Println("Server starting on :8080...")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

创建 Go 模块文件:go.mod

go 复制代码
module docker-go-app

go 1.19

7. Docker Compose 实战

7.1 完整的 Web 应用栈

创建 Docker Compose 文件:docker-compose-fullstack.yml

yaml 复制代码
version: '3.8'

services:
  # 前端服务
  frontend:
    build:
      context: .
      dockerfile: frontend.Dockerfile
    container_name: vue-frontend
    ports:
      - "3000:80"
    networks:
      - app-network
    depends_on:
      - backend
    environment:
      - API_URL=http://backend:8000
    restart: unless-stopped

  # 后端 API 服务
  backend:
    build:
      context: .
      dockerfile: backend.Dockerfile
    container_name: flask-backend
    ports:
      - "8000:8000"
    networks:
      - app-network
    depends_on:
      - database
    environment:
      - DATABASE_URL=postgresql://user:password@database:5432/myapp
      - REDIS_URL=redis://redis:6379
    volumes:
      - backend-logs:/app/logs
    restart: unless-stopped

  # 数据库服务
  database:
    image: postgres:13-alpine
    container_name: postgres-db
    networks:
      - app-network
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    restart: unless-stopped

  # Redis 缓存服务
  redis:
    image: redis:6.2-alpine
    container_name: redis-cache
    networks:
      - app-network
    command: redis-server --appendonly yes
    volumes:
      - redis-data:/data
    restart: unless-stopped

  # Nginx 反向代理
  nginx:
    image: nginx:alpine
    container_name: nginx-proxy
    ports:
      - "80:80"
      - "443:443"
    networks:
      - app-network
    depends_on:
      - frontend
      - backend
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf
      - ./ssl:/etc/nginx/ssl
    restart: unless-stopped

  # 监控服务
  monitor:
    image: portainer/portainer-ce:latest
    container_name: portainer
    ports:
      - "9000:9000"
    networks:
      - app-network
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer-data:/data
    restart: unless-stopped

networks:
  app-network:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

volumes:
  postgres-data:
    driver: local
  redis-data:
    driver: local
  backend-logs:
    driver: local
  portainer-data:
    driver: local

7.2 创建相关配置文件

创建 Nginx 配置:nginx.conf

nginx 复制代码
events {
    worker_connections 1024;
}

http {
    upstream backend {
        server backend:8000;
    }

    upstream frontend {
        server frontend:80;
    }

    server {
        listen 80;
        server_name localhost;

        # 前端静态文件
        location / {
            proxy_pass http://frontend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }

        # 后端 API 代理
        location /api/ {
            proxy_pass http://backend;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
            
            # CORS 头
            add_header Access-Control-Allow-Origin *;
            add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, DELETE";
            add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept, Authorization";
        }

        # 健康检查端点
        location /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }
    }
}

创建数据库初始化脚本:init.sql

sql 复制代码
-- 创建示例表
CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) UNIQUE NOT NULL,
    email VARCHAR(100) UNIQUE NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE IF NOT EXISTS products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100) NOT NULL,
    price DECIMAL(10,2) NOT NULL,
    description TEXT,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 插入示例数据
INSERT INTO users (username, email) VALUES 
('admin', 'admin@example.com'),
('user1', 'user1@example.com')
ON CONFLICT (username) DO NOTHING;

INSERT INTO products (name, price, description) VALUES 
('Docker Book', 39.99, 'Learn Docker from scratch'),
('Kubernetes Guide', 49.99, 'Master container orchestration')
ON CONFLICT (id) DO NOTHING;

8. Docker 安全实践

8.1 安全扫描与最佳实践

创建安全扫描脚本:security_scan.sh

bash 复制代码
#!/bin/bash

# 安装 Docker 安全扫描工具
sudo apt-get update
sudo apt-get install -y trivy

# 扫描本地镜像
echo "扫描 nginx 镜像的安全漏洞..."
trivy image nginx:latest

# 使用非 root 用户运行容器
docker run -d \
  --name security-demo \
  --user 1000:1000 \
  -p 8082:80 \
  nginx:alpine

# 检查容器运行用户
docker exec security-demo whoami

# 只读文件系统示例
docker run -d \
  --name read-only-demo \
  --read-only \
  --tmpfs /tmp \
  -p 8083:80 \
  nginx:alpine

# 安全选项示例
docker run -d \
  --name secure-container \
  --security-opt=no-new-privileges:true \
  --cap-drop=ALL \
  --cap-add=NET_BIND_SERVICE \
  -p 8084:80 \
  nginx:alpine

# 检查容器安全性
docker inspect secure-container | grep -A 5 SecurityOpt

echo "安全演示完成!"

8.2 创建安全加固的 Dockerfile

创建安全加固的 Dockerfile:secure.Dockerfile

dockerfile 复制代码
# 使用特定版本的基础镜像
FROM nginx:1.23-alpine

# 设置用户和组
RUN addgroup -g 1000 -S www-group && \
    adduser -S -D -H -u 1000 -h /var/cache/nginx -s /sbin/nologin -G www-group -g www-user www-user

# 移除不必要的文件
RUN rm -rf /etc/nginx/conf.d/* && \
    rm -rf /usr/share/nginx/html/*

# 复制自定义配置
COPY nginx-secure.conf /etc/nginx/nginx.conf
COPY html/ /usr/share/nginx/html/

# 设置正确的权限
RUN chown -R www-user:www-group /var/cache/nginx && \
    chown -R www-user:www-group /var/log/nginx && \
    chown -R www-user:www-group /etc/nginx/nginx.conf && \
    chmod -R 755 /usr/share/nginx/html && \
    chmod 644 /etc/nginx/nginx.conf

# 切换到非root用户
USER www-user

# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:80/ || exit 1

# 暴露端口
EXPOSE 80

# 启动命令
CMD ["nginx", "-g", "daemon off;"]

创建安全 Nginx 配置:nginx-secure.conf

nginx 复制代码
worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
    worker_connections 1024;
}

http {
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # 安全头
    add_header X-Frame-Options DENY;
    add_header X-Content-Type-Options nosniff;
    add_header X-XSS-Protection "1; mode=block";
    add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
    add_header Referrer-Policy "strict-origin-when-cross-origin";

    # 隐藏服务器版本
    server_tokens off;

    # 限制请求大小
    client_max_body_size 1m;

    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

    access_log /var/log/nginx/access.log main;

    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    server {
        listen 80;
        server_name _;

        # 根目录配置
        location / {
            root /usr/share/nginx/html;
            index index.html index.htm;
            
            # 安全限制
            limit_except GET {
                deny all;
            }
        }

        # 禁止访问隐藏文件
        location ~ /\. {
            deny all;
            access_log off;
            log_not_found off;
        }

        # 健康检查
        location /health {
            access_log off;
            return 200 "healthy\n";
            add_header Content-Type text/plain;
        }
    }
}

9. Docker 监控与日志管理

9.1 容器监控实战

创建监控脚本:monitoring_setup.sh

bash 复制代码
#!/bin/bash

# 使用 Docker Stats 监控
echo "实时容器资源使用情况:"
docker stats --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"

# 设置容器资源限制
docker run -d \
  --name limited-container \
  --memory=512m \
  --cpus=1.0 \
  --memory-reservation=256m \
  --blkio-weight=500 \
  nginx:alpine

# 检查资源限制
docker inspect limited-container | grep -A 10 "HostConfig"

# 安装 cAdvisor 进行详细监控
docker run -d \
  --name=cadvisor \
  --volume=/:/rootfs:ro \
  --volume=/var/run:/var/run:ro \
  --volume=/sys:/sys:ro \
  --volume=/var/lib/docker/:/var/lib/docker:ro \
  --volume=/dev/disk/:/dev/disk:ro \
  --publish=8080:8080 \
  --detach=true \
  --privileged \
  --device=/dev/kmsg \
  gcr.io/cadvisor/cadvisor:v0.47.0

echo "cAdvisor 监控面板: http://localhost:8080"

# 日志管理示例
docker run -d \
  --name logging-demo \
  --log-driver=json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  -p 8085:80 \
  nginx:alpine

# 查看日志
docker logs logging-demo

# 日志导出
docker logs logging-demo > nginx.log

# 清理
docker stop cadvisor limited-container logging-demo
docker rm cadvisor limited-container logging-demo

9.2 使用 Prometheus 和 Grafana

创建监控栈配置:docker-compose-monitoring.yml

yaml 复制代码
version: '3.8'

services:
  # Node Exporter - 系统指标收集
  node-exporter:
    image: prom/node-exporter:latest
    container_name: node-exporter
    command:
      - '--path.rootfs=/host'
    network_mode: host
    pid: host
    restart: unless-stopped
    volumes:
      - '/:/host:ro,rslave'
    user: root

  # cAdvisor - 容器指标收集
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    devices:
      - /dev/kmsg
    network_mode: host
    restart: unless-stopped
    privileged: true

  # Prometheus - 指标存储和查询
  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
      - '--storage.tsdb.retention.time=200h'
      - '--web.enable-lifecycle'
    restart: unless-stopped
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"
    networks:
      - monitoring

  # Grafana - 数据可视化
  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    restart: unless-stopped
    volumes:
      - grafana-data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin123
      - GF_USERS_ALLOW_SIGN_UP=false
    ports:
      - "3000:3000"
    networks:
      - monitoring
    depends_on:
      - prometheus

  # Alertmanager - 告警管理
  alertmanager:
    image: prom/alertmanager:latest
    container_name: alertmanager
    restart: unless-stopped
    volumes:
      - ./alertmanager.yml:/etc/alertmanager/alertmanager.yml:ro
      - alertmanager-data:/alertmanager
    command:
      - '--config.file=/etc/alertmanager/alertmanager.yml'
      - '--storage.path=/alertmanager'
      - '--web.external-url=http://localhost:9093'
    ports:
      - "9093:9093"
    networks:
      - monitoring

networks:
  monitoring:
    driver: bridge

volumes:
  prometheus-data:
    driver: local
  grafana-data:
    driver: local
  alertmanager-data:
    driver: local

创建 Prometheus 配置:prometheus.yml

yaml 复制代码
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alert_rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

  - job_name: 'docker-containers'
    static_configs:
      - targets: ['localhost:9323']

10. 生产环境部署实战

10.1 完整的生产级配置

创建生产环境部署脚本:production_deploy.sh

bash 复制代码
#!/bin/bash

set -e

# 环境变量配置
export COMPOSE_PROJECT_NAME="myapp"
export DEPLOY_ENV="production"
export DOCKER_REGISTRY="registry.mycompany.com"
export APP_VERSION="1.0.0"

# 创建必要的目录
mkdir -p {logs,data,config,backups}

# 拉取最新镜像
docker-compose -f docker-compose-prod.yml pull

# 停止现有服务
docker-compose -f docker-compose-prod.yml down

# 备份数据库
docker run --rm \
  -v ${COMPOSE_PROJECT_NAME}_db_data:/source \
  -v $(pwd)/backups:/backup \
  alpine tar czf /backup/db-backup-$(date +%Y%m%d-%H%M%S).tar.gz -C /source .

# 启动服务
docker-compose -f docker-compose-prod.yml up -d

# 健康检查
echo "进行健康检查..."
sleep 30

# 检查所有服务状态
docker-compose -f docker-compose-prod.yml ps

# 检查服务健康状态
for service in $(docker-compose -f docker-compose-prod.yml ps --services); do
    container_id=$(docker-compose -f docker-compose-prod.yml ps -q $service)
    health_status=$(docker inspect --format='{{.State.Health.Status}}' $container_id 2>/dev/null || echo "no health check")
    echo "服务 $service: $health_status"
done

# 日志检查
docker-compose -f docker-compose-prod.yml logs --tail=50

echo "部署完成!"

创建生产环境 Docker Compose:docker-compose-prod.yml

yaml 复制代码
version: '3.8'

x-common-variables: &common-vars
  DEPLOY_ENV: production
  LOG_LEVEL: info
  TZ: Asia/Shanghai

services:
  # 应用服务
  app:
    image: ${DOCKER_REGISTRY}/myapp:${APP_VERSION}
    container_name: ${COMPOSE_PROJECT_NAME}-app
    restart: unless-stopped
    environment:
      <<: *common-vars
      DATABASE_URL: postgresql://${DB_USER}:${DB_PASSWORD}@database:5432/${DB_NAME}
      REDIS_URL: redis://redis:6379
    depends_on:
      database:
        condition: service_healthy
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
    networks:
      - backend
      - frontend

  # 数据库
  database:
    image: postgres:13-alpine
    container_name: ${COMPOSE_PROJECT_NAME}-database
    restart: unless-stopped
    environment:
      <<: *common-vars
      POSTGRES_DB: ${DB_NAME}
      POSTGRES_USER: ${DB_USER}
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - db_data:/var/lib/postgresql/data
      - ./config/postgres.conf:/etc/postgresql/postgresql.conf
    command: postgres -c config_file=/etc/postgresql/postgresql.conf
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${DB_USER} -d ${DB_NAME}"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 40s
    networks:
      - backend

  # Redis
  redis:
    image: redis:6.2-alpine
    container_name: ${COMPOSE_PROJECT_NAME}-redis
    restart: unless-stopped
    command: redis-server /usr/local/etc/redis/redis.conf
    volumes:
      - redis_data:/data
      - ./config/redis.conf:/usr/local/etc/redis/redis.conf
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 30s
      timeout: 10s
      retries: 5
    networks:
      - backend

  # Nginx
  nginx:
    image: nginx:1.23-alpine
    container_name: ${COMPOSE_PROJECT_NAME}-nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./config/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./ssl:/etc/nginx/ssl:ro
      - ./logs/nginx:/var/log/nginx
    depends_on:
      - app
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3
    networks:
      - frontend

networks:
  frontend:
    driver: bridge
    driver_opts:
      com.docker.network.driver.mtu: 1500
  backend:
    driver: bridge
    internal: false

volumes:
  db_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ${PWD}/data/db
  redis_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: ${PWD}/data/redis

创建环境配置文件:.env.production

bash 复制代码
# 应用配置
COMPOSE_PROJECT_NAME=myapp-production
APP_VERSION=1.0.0
DOCKER_REGISTRY=registry.mycompany.com

# 数据库配置
DB_NAME=myapp
DB_USER=app_user
DB_PASSWORD=secure_password_123

# 网络配置
DOMAIN=myapp.com
SSL_EMAIL=admin@myapp.com

# 资源限制
APP_MEMORY_LIMIT=1g
DB_MEMORY_LIMIT=2g
REDIS_MEMORY_LIMIT=512m

Docker 学习流程图

graph TD A[Docker 学习路径] --> B[环境安装] A --> C[基础概念] A --> D[实战案例] B --> B1[系统安装] B --> B2[环境配置] B --> B3[权限设置] C --> C1[镜像管理] C --> C2[容器操作] C --> C3[网络配置] C --> C4[数据持久化] D --> D1[Hello World] D --> D2[Web 应用] D --> D3[多容器应用] D --> D4[生产部署] B1 --> E[完成安装] B2 --> E B3 --> E C1 --> F[掌握基础] C2 --> F C3 --> F C4 --> F D1 --> G[实战能力] D2 --> G D3 --> G D4 --> G E --> H[Docker 精通] F --> H G --> H style A fill:#4CAF50,color:white style B fill:#2196F3,color:white style C fill:#2196F3,color:white style D fill:#2196F3,color:white style H fill:#FF9800,color:white style E fill:#9C27B0,color:white style F fill:#9C27B0,color:white style G fill:#9C27B0,color:white

总结

通过这10个详细的实战案例,您已经全面掌握了 Docker 的核心概念和实际应用技能。从基础的环境安装到生产级部署,每个案例都提供了完整的代码和配置,确保您可以立即在实践中应用这些知识。

关键学习要点:

  1. Docker 基础命令和概念理解
  2. 容器网络和数据管理
  3. Dockerfile 最佳实践和多阶段构建
  4. Docker Compose 编排复杂应用
  5. 容器安全加固和监控
  6. 生产环境部署策略
相关推荐
屿行屿行1 天前
【Linux】Socket编程(基于实际工程分析)
linux·服务器·网络
天才程序YUAN1 天前
从零开始、保留 Windows 数据、安装Ubuntu 22.04 LTS双系统
linux·windows·ubuntu
Evan芙1 天前
Rocky Linux 9 网卡改名及静态IP地址配置完整步骤
linux·网络·智能路由器
Zeku1 天前
20251125 - 韦东山Linux第三篇笔记【上】
linux·笔记·单片机
企鹅侠客1 天前
Linux性能调优 详解磁盘工作流程及性能指标
linux·运维·服务器·性能调优
icy、泡芙1 天前
TF卡---热插拔
linux·驱动开发
企鹅侠客1 天前
Linux性能调优 再谈磁盘性能指标和进程级IO
linux·运维·服务器·性能调优
wdfk_prog1 天前
[Linux]学习笔记系列 -- [block][mq-deadline]
linux·笔记·学习
不过普通话一乙不改名1 天前
Linux 网络收包的进阶之路:从普通 socket 到 AF_XDP 零拷贝
linux·运维·网络
Zeku1 天前
20251125 - 韦东山Linux第三篇笔记【中】
linux·驱动开发