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. 生产环境部署策略
相关推荐
MMME~2 小时前
SELinux
linux·rhce
cccccc语言我来了2 小时前
深入理解 Linux(7) 命令与动态库:从文件操作到程序链接的实践指南
android·linux·运维
Lynnxiaowen2 小时前
今天我们开始学习Linux自动化运维Ansible基础
linux·运维·学习·自动化·云计算·ansible
NiKo_W2 小时前
Linux 传输层协议
linux·运维·网络·tcp协议·传输层·udp协议
夜月yeyue2 小时前
Linux 中断处理机制详解:上下半部、内核线程与中断线程化
linux·运维·单片机·嵌入式硬件·uboot·bootloard
浪漫血液&2 小时前
Linux基础指令(简易版)
linux·服务器
云计算老刘3 小时前
1. Cockpit 管理服务器;2. Linux 软件包管理
linux·运维·服务器·云原生·云计算
小苏兮4 小时前
【把Linux“聊”明白】进程的概念与状态
linux·运维·服务器·学习
wsad05324 小时前
Ubuntu 24.04 更换国内软件源(以阿里云为例)
linux·ubuntu·阿里云