Docker 部署完全指南:从入门到实战

本文档从基础概念讲起,逐步深入到 Docker Compose 实战配置,涵盖环境准备、镜像管理、数据持久化、网络配置等核心内容。无论你是初学者还是有一定基础的开发者,都能从中获得实用的部署知识。

1. Docker 基础概念

在开始部署之前,让我们先了解 Docker 的核心概念:

1.1 什么是 Docker

Docker 是一个开源的容器化平台,允许开发者将应用程序及其依赖打包成一个独立的容器,确保应用在任何环境中都能一致运行。

核心优势

  • 一致性:开发、测试、生产环境保持一致
  • 隔离性:每个容器相互隔离,互不影响
  • 轻量化:相比虚拟机,容器启动更快、资源占用更少
  • 可移植性:一次构建,随处运行

1.2 核心概念解析

概念说明
镜像(Image)应用程序的模板,包含代码、运行时、环境变量等
容器(Container)镜像的运行实例,可以启动、停止、删除
仓库(Repository)存储和分发镜像的地方,如 Docker Hub
Dockerfile定义镜像构建步骤的脚本文件

1.3 Docker 与 Docker Compose 的区别

工具用途使用场景
Docker管理单个容器快速测试、简单部署
Docker Compose管理多容器应用复杂应用、服务编排

容器编排工具对比

工具适用场景规模学习曲线主要特点
Docker Compose单主机多容器小规模(<10容器)简单易用,基于 YAML 配置
Docker Swarm多主机集群中等规模中等原生集成,零额外依赖
Kubernetes生产级大规模部署大规模(数百+容器)功能全面,社区活跃,生态丰富

选择建议

  • 开发/测试环境:使用 Docker Compose,简单快捷
  • 小型生产环境:Docker Swarm 足够,无需额外学习成本
  • 大型生产环境:Kubernetes,功能强大但学习成本高

📝 注意:如果你是初学者,建议从 Docker Compose 开始,掌握基础后再学习 Kubernetes。


2. 环境准备

2.1 Windows 系统

安装 Docker Desktop

  1. 下载 Docker Desktop:https://www.docker.com/products/docker-desktop/
  2. 运行安装程序,务必勾选 WSL2 后端(推荐)
  3. 安装完成后重启电脑
  4. 打开 Docker Desktop,检查是否正常运行

验证安装

打开 PowerShell 或命令提示符,执行以下命令:

# 检查 Docker 版本
docker --version

# 检查 Docker Compose 版本(V2)
docker compose version

# 如果是旧版 V1(需要单独安装)
docker-compose --version

📝 注意:Docker Desktop for Windows 已默认集成 Docker Compose V2,推荐使用 docker compose 命令。

WSL2 配置(如未自动配置)

# 打开 PowerShell(管理员)
wsl --install

# 设置 WSL2 为默认版本
wsl --set-default-version 2

# 查看已安装的发行版
wsl --list -v

2.2 Linux 系统

Ubuntu/Debian

# 更新软件包
sudo apt update

# 安装依赖
sudo apt install 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=$(dpkg --print-architecture) 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 update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin

# 将当前用户加入 docker 组(无需 sudo)
sudo usermod -aG docker $USER

# 重新登录后生效

CentOS/RHEL

# 删除旧版本
sudo yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-engine

# 安装依赖
sudo yum install -y yum-utils

# 添加 Docker 仓库
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo

# 安装 Docker
sudo yum install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 启动并设置开机自启
sudo systemctl start docker
sudo systemctl enable docker

# 将当前用户加入 docker 组
sudo usermod -aG docker $USER

2.3 macOS 系统

macOS 安装 Docker Desktop

  1. 下载 Docker Desktop for Mac:https://www.docker.com/products/docker-desktop/
  2. 双击下载的 .dmg 文件
  3. 将 Docker Desktop 图标拖入应用程序文件夹
  4. 打开 Docker Desktop,等待初始化完成
  5. 检查菜单栏是否出现 Docker 图标,确认运行正常

macOS 验证安装

打开终端(Terminal),执行以下命令:

# 检查 Docker 版本
docker --version

# 检查 Docker Compose 版本(V2)
docker compose version

# 运行测试容器
docker run hello-world

Homebrew 安装方式

如果你已安装 Homebrew,可以使用以下命令安装 Docker:

# 安装 Docker Desktop
brew install --cask docker

# 启动 Docker Desktop(如果未自动启动)
open -a Docker

📝 注意:首次启动 Docker Desktop 时,可能需要在 "系统偏好设置"→"安全性与隐私" 中允许 Docker 运行。

Apple Silicon 注意事项

如果你的 Mac 使用 Apple Silicon(M1/M2/M3/M4 芯片):

  • ARM64 镜像:优先使用支持 arm64arm/v8 架构的镜像,性能更佳
  • x86 镜像兼容:默认情况下 Docker 会使用 Rosetta 2 自动转译 x86_64 镜像
  • 建议:尽量使用官方提供的 linux/arm64/v8 镜像,避免性能损失

检查你的 Mac 架构:

# 查看 CPU 架构
uname -m
# Apple Silicon 显示:arm64
# Intel Mac 显示:x86_64

# 查看 Apple Silicon 型号
sysctl -n machdep.cpu.brand_string

2.4 硬件资源建议

配置级别CPU内存存储
最低配置2核2GB20GB
推荐配置4核4GB50GB
高性能配置8核8GB+100GB+

3. Docker 核心操作

3.1 镜像操作

# 搜索镜像
docker search nginx

# 拉取镜像
docker pull nginx:latest

# 查看本地镜像
docker images

# 删除镜像
docker rmi nginx:latest

# 清理未使用的镜像
docker image prune

3.2 容器操作

# 运行容器(后台模式)
docker run -d --name my-nginx nginx:latest

# 运行容器(交互模式)
docker run -it ubuntu:latest /bin/bash

# 映射端口:宿主机:容器
docker run -d -p 8080:80 --name my-nginx nginx:latest

# 映射目录:宿主机路径:容器路径
docker run -d -p 8080:80 -v /host/data:/container/data --name my-nginx nginx:latest

# 查看运行中的容器
docker ps

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

# 停止容器
docker stop my-nginx

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

# 重启容器
docker restart my-nginx

# 删除容器(必须先停止)
docker rm my-nginx

# 强制删除运行中的容器
docker rm -f my-nginx

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

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

# 查看容器资源使用
docker stats my-nginx

3.3 容器网络操作

# 查看网络列表
docker network ls

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

# 将容器连接到网络
docker network connect my-network my-nginx

# 从网络断开
docker network disconnect my-network my-nginx

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

4. Docker Compose 详解

4.1 docker-compose.yaml 基础结构

Docker Compose 使用 YAML 格式定义多容器应用的服务、网络、数据卷等。

基础模板

version: "3.8"  # Docker Compose 文件版本

services:  # 定义所有服务(容器)
  web:  # 服务名称
    image: nginx:latest  # 使用的镜像
    container_name: my-web  # 容器名称
    restart: unless-stopped  # 重启策略
    ports:  # 端口映射
      - "80:80"
    volumes:  # 数据卷映射
      - ./html:/usr/share/nginx/html:ro
    networks:  # 所属网络
      - frontend

  db:  # 数据库服务
    image: postgres:16
    container_name: my-db
    restart: unless-stopped
    environment:  # 环境变量
      POSTGRES_DB: myapp
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: secret
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - frontend
      - backend

networks:  # 定义网络
  frontend:
    driver: bridge
  backend:
    driver: bridge

volumes:  # 定义数据卷
  postgres-data:

4.2 常用配置项详解

服务配置(services)

services:
  app:
    # 镜像配置
    image: nginx:alpine  # 镜像:标签
    build: ./  # 从 Dockerfile 构建
    container_name: my-app  # 容器名称

    # 启动策略
    restart: "no"           # 不自动重启
    restart: on-failure     # 失败时重启
    restart: always         # 始终重启
    restart: unless-stopped  # 除非手动停止,否则重启

    # 端口映射
    ports:
      - "80:80"           # 宿主机端口:容器端口
      - "443:443"
      - "8080-8090:8080"   # 端口范围映射

    # 目录映射
    volumes:
      - /host/path:/container/path       # 绝对路径
      - ./relative/path:/container/path  # 相对路径
      - volume-name:/container/path      # 命名卷
      - /host/path:/container/path:ro   # 只读挂载

    # 环境变量
    environment:
      - DB_HOST=localhost
      - DB_PORT=5432
      # 或使用键值对格式
      DB_NAME: myapp

    # 依赖关系(等待其他服务启动)
    depends_on:
      - db
      - redis

    # 健康检查
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 3s
      retries: 3
      start_period: 10s

    # 资源限制
    mem_limit: 512m  # 最大内存
    cpus: 1.0        # CPU 核心数
    cpu_shares: 512   # CPU 权重

    # 网络配置
    networks:
      - frontend
      - backend

    # 命令覆盖
    command: ["python", "app.py", "--debug"]

    # 备用命令(Shell 格式)
    entrypoint: /bin/sh -c "python app.py"

资源限制配置(ulimits)

services:
  app:
    image: postgres:16
    ulimits:
      nofile:
        soft: 65536  # 软限制
        hard: 65536  # 硬限制
      nproc:
        soft: 4096
        hard: 4096

共享内存配置

services:
  app:
    image: postgres:16
    shm_size: '2gb'  # 设置 /dev/shm 大小

init 进程配置

services:
  app:
    image: nginx:latest
    init: true  # 启用 init 进程,处理僵尸进程和信号传递

4.3 网络配置(networks)

networks:
  # 桥接网络(默认)
  frontend:
    driver: bridge

  # 自定义网段
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16

  # 外部网络(已存在的网络)
  external-network:
    external: true

4.4 数据卷配置(volumes)

volumes:
  # 命名卷(自动创建)
  db-data:
    driver: local

  # 自定义数据卷配置
  persistent-data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /mnt/data

  # 使用已有数据卷
  existing-volume:
    external: true

5. 实战配置示例

5.1 Nginx + PHP-FPM 组合

version: "3.8"

services:
  nginx:
    image: nginx:alpine
    container_name: web-server
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/nginx.conf:ro
      - ./html:/usr/share/nginx/html:ro
      - ./logs:/var/log/nginx
    depends_on:
      php:
        condition: service_healthy
    networks:
      - app-network
    healthcheck:
      test: ["CMD-SHELL", "nginx -t"]
      interval: 10s
      timeout: 5s
      retries: 3

  php:
    image: php:8.2-fpm-alpine
    container_name: php-fpm
    restart: unless-stopped
    volumes:
      - ./html:/var/www/html
      - ./php.ini:/usr/local/etc/php/php.ini:ro
    networks:
      - app-network
    healthcheck:
      test: ["CMD-SHELL", "php-fpm -t"]
      interval: 10s
      timeout: 5s
      retries: 3
    environment:
      - PHP_MEMORY_LIMIT=256M

networks:
  app-network:
    driver: bridge

5.2 PostgreSQL + 应用组合

version: "3.8"

services:
  app:
    image: node:18-alpine
    container_name: node-app
    restart: unless-stopped
    working_dir: /app
    volumes:
      - ./app:/app
      - ./data:/app/data
    ports:
      - "3000:3000"
    depends_on:
      db:
        condition: service_healthy
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_PORT=5432
      - DB_USER=admin
      - DB_PASSWORD=secret
      - DB_NAME=myapp
    networks:
      - app-network
    healthcheck:
      test: ["CMD-SHELL", "wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1"]
      interval: 30s
      timeout: 5s
      retries: 3
      start_period: 20s
    mem_limit: 512m
    cpus: 0.5

  db:
    image: postgres:16-alpine
    container_name: postgres-db
    restart: unless-stopped
    volumes:
      - postgres-data:/var/lib/postgresql/data
      - ./backup:/backup
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=admin
      - POSTGRES_PASSWORD=secret
    networks:
      - app-network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h localhost -U admin"]
      interval: 10s
      timeout: 5s
      retries: 5
    mem_limit: 384m
    cpus: 0.5
    shm_size: 256m
    ulimits:
      nofile:
        soft: 65536
        hard: 65536

networks:
  app-network:
    driver: bridge

volumes:
  postgres-data:

5.3 多阶段构建 Dockerfile 示例

# 阶段1:构建
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build

# 阶段2:运行
FROM node:18-alpine AS runtime
WORKDIR /app
ENV NODE_ENV=production

# 复制构建产物
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules

# 创建非 root 用户
RUN addgroup -g 1001 -S nodejs && \
    adduser -S nextjs -u 1001
USER nextjs

EXPOSE 3000
CMD ["node", "dist/server.js"]

6. Docker Compose 常用命令

6.1 服务管理

# 启动所有服务(后台运行)
docker compose up -d

# 启动并重新构建镜像
docker compose up -d --build

# 停止所有服务
docker compose down

# 停止并删除容器、网络
docker compose down --volumes  # 同时删除数据卷

# 重启所有服务
docker compose restart

# 重建特定服务
docker compose up -d --force-recreate service-name

6.2 查看与调试

# 查看服务状态
docker compose ps

# 查看服务日志
docker compose logs -f          # 跟踪所有服务日志
docker compose logs -f web     # 跟踪特定服务日志
docker compose logs --tail=100 web  # 查看最近 100 行

# 查看资源使用
docker compose top

# 进入服务容器
docker compose exec web bash
docker compose exec db psql -U admin -d myapp

# 查看网络详情
docker compose network inspect app_network

6.3 镜像管理

# 拉取最新镜像
docker compose pull

# 拉取并更新服务
docker compose pull && docker compose up -d

# 清理未使用的镜像
docker compose images
docker image prune

7. 数据持久化详解

7.1 为什么要数据持久化

Docker 容器默认是临时的:删除容器后,所有数据都会丢失。因此,重要数据必须通过数据卷(Volumes)持久化到宿主机。

7.2 三种数据卷类型

1. 命名卷(推荐)

services:
  db:
    image: postgres:16
    volumes:
      - db-data:/var/lib/postgresql/data

volumes:
  db-data:  # 自动创建命名卷

2. 绑定挂载(开发环境)

services:
  app:
    image: nginx:latest
    volumes:
      - ./html:/usr/share/nginx/html:ro  # 只读
      - /host/path:/container/path        # 读写

3. tmpfs 挂载(内存存储)

services:
  app:
    image: redis:alpine
    tmpfs:
      - /data:size=100M,mode=0755  # 存储在内存中

7.3 数据备份与恢复

备份命名卷

# 创建临时容器挂载卷进行备份
docker run --rm \
  -v volume-name:/source \
  -v $(pwd):/backup \
  alpine \
  tar czf /backup/backup.tar.gz -C /source .

恢复数据

# 从备份恢复
docker run --rm \
  -v volume-name:/target \
  -v $(pwd):/backup \
  alpine \
  tar xzf /backup/backup.tar.gz -C /target

8. 健康检查配置

8.1 为什么需要健康检查

健康检查(Health Check)用于:

  • 确认容器是否正常运行
  • depends_on 提供真正的就绪状态
  • 负载均衡器判断容器是否可用
  • 自动恢复故障服务

8.2 常用健康检查示例

services:
  # HTTP 健康检查
  web:
    image: nginx:alpine
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 10s

  # TCP 端口检查
  redis:
    image: redis:alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 3

  # 执行脚本检查
  postgres:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -h localhost -U $$POSTGRES_USER"]
      interval: 10s
      timeout: 5s
      retries: 3

8.3 depends_on 的 condition

services:
  app:
    image: node:18-alpine
    depends_on:
      db:
        condition: service_healthy  # 等待健康检查通过
      redis:
        condition: service_started   # 仅等待启动

9. 日志管理

9.1 日志驱动配置

services:
  app:
    image: nginx:latest
    logging:
      driver: "json-file"  # 默认驱动
      options:
        max-size: "10m"     # 单个日志文件最大 10MB
        max-file: "3"       # 保留 3 个日志文件

9.2 查看日志

# 查看所有日志
docker compose logs

# 跟踪日志
docker compose logs -f

# 查看最近 N 行
docker compose logs --tail=100

# 按时间过滤
docker compose logs --since="30m"

# 搜索特定内容
docker compose logs | grep "error"

9.3 日志清理

# 清理所有容器的日志
truncate -s 0 /var/lib/docker/containers/*/*-json.log

# 或使用 docker system df
docker system df
docker system prune

10. 安全加固

10.1 容器安全最佳实践

services:
  app:
    image: nginx:latest

    # 不使用特权模式
    # privileged: true  # 禁止!

    # 使用只读根文件系统
    read_only: true

    # 限制资源
    mem_limit: 512m
    cpus: 1.0

    # 不使用 root 用户运行
    user: "1000:1000"

    # 安全选项
    security_opt:
      - no-new-privileges:true

    # 网络隔离
    networks:
      - internal-network

10.2 网络安全

services:
  web:
    image: nginx:latest
    networks:
      - frontend
    ports:
      - "80:80"

  app:
    image: node:18-alpine
    networks:
      - backend
    # 不暴露端口,仅内部访问

  db:
    image: postgres:16
    networks:
      - backend
    # 不暴露端口,仅内部访问

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

10.3 敏感信息管理

使用 .env 文件

# 创建 .env 文件
cat > .env << EOF
DB_PASSWORD=secret123
API_KEY=your-api-key
EOF

# 在 docker-compose.yaml 中引用
services:
  app:
    image: node:18-alpine
    env_file:
      - .env
    environment:
      - DB_PASSWORD  # 从 .env 读取

使用 Docker Secrets(Swarm 模式)

services:
  db:
    image: postgres:16
    secrets:
      - db_password

secrets:
  db_password:
    file: ./db_password.txt

11. 自动化维护脚本

11.1 自动备份脚本

#!/bin/bash
# 文件名:backup.sh
# 用途:备份 Docker Compose 项目的所有数据

# 配置
PROJECT_NAME="myapp"
BACKUP_DIR="/opt/backups/$PROJECT_NAME"
DATE=$(date +%Y%m%d_%H%M%S)
KEEP_DAYS=7

# 创建备份目录
mkdir -p "$BACKUP_DIR"

# 获取项目路径
COMPOSE_DIR=$(dirname "$(find /opt -name "docker-compose.yaml" -path "*$PROJECT_NAME*" 2>/dev/null | head -1)")
cd "$COMPOSE_DIR" || exit 1

# 备份数据卷
for volume in $(docker compose config --volumes 2>/dev/null | grep -v "^volume-"); do
    echo "正在备份卷: $volume"
    docker run --rm \
      -v ${PROJECT_NAME}_${volume}:/source \
      -v "$BACKUP_DIR":/backup \
      alpine \
      tar czf "/backup/${volume}_${DATE}.tar.gz" -C /source .
done

# 备份配置文件
cp docker-compose.yaml "$BACKUP_DIR/docker-compose_${DATE}.yaml"
cp -r .env "$BACKUP_DIR/.env_${DATE}" 2>/dev/null

# 清理旧备份
find "$BACKUP_DIR" -name "*_${DATE}.tar.gz" -mtime +$KEEP_DAYS -delete

echo "✓ 备份完成: $DATE"

备份脚本 PowerShell 版本

# 文件名:backup.ps1
# 用途:备份 Docker Compose 项目的所有数据(Windows 版本)
# 使用方法:在 PowerShell 中运行 .\\backup.ps1

# 配置
$PROJECT_NAME = "myapp"
$BACKUP_DIR = "C:\\backups\\$PROJECT_NAME"
$DATE = Get-Date -Format "yyyyMMdd_HHmmss"
$KEEP_DAYS = 7

# 创建备份目录
if (-not (Test-Path $BACKUP_DIR)) {
    New-Item -ItemType Directory -Path $BACKUP_DIR -Force | Out-Null
}

# 获取项目路径(当前目录或指定路径)
$COMPOSE_DIR = $PWD.Path

# 备份数据卷
$volumes = docker compose config --volumes 2>$null | Where-Object { $_ -notmatch "^volume-" }
foreach ($volume in $volumes) {
    Write-Host "正在备份卷: $volume"
    $volumeName = "${PROJECT_NAME}_${volume}"
    $backupFile = "$BACKUP_DIR\\${volume}_${DATE}.tar.gz"

    # 使用临时容器备份卷
    docker run --rm `
        -v ${volumeName}:/source `
        -v "${BACKUP_DIR}:/backup" `
        alpine `
        tar czf "/backup/${volume}_${DATE}.tar.gz" -C /source .
}

# 备份配置文件
Copy-Item "docker-compose.yaml" "$BACKUP_DIR\\docker-compose_$DATE.yaml" -ErrorAction SilentlyContinue
Copy-Item ".env" "$BACKUP_DIR\\.env_$DATE" -ErrorAction SilentlyContinue

# 清理旧备份
$cutoffDate = (Get-Date).AddDays(-$KEEP_DAYS)
Get-ChildItem $BACKUP_DIR -Filter "*_$DATE.tar.gz" |
    Where-Object { $_.LastWriteTime -lt $cutoffDate } |
    Remove-Item -Force

Write-Host "✓ 备份完成: $DATE"

📝 注意:PowerShell 脚本在 Windows 上运行,需要确保 Docker Desktop 已启动。

11.2 定时清理脚本

#!/bin/bash
# 文件名:clean.sh
# 用途:清理未使用的 Docker 资源

# 清理停止的容器
docker container prune -f

# 清理未使用的镜像
docker image prune -f

# 清理未使用的网络
docker network prune -f

# 清理构建缓存
docker builder prune -f

# 清理所有未使用的资源
docker system prune -f

# 设置日志大小限制
LOG_DIR="/var/lib/docker/containers"
MAX_SIZE="10M"

for log in $(find $LOG_DIR -name "*-json.log"); do
    size=$(stat -f%z "$log" 2>/dev/null || stat -c%s "$log" 2>/dev/null)
    if [ "$size" -gt 10485760 ]; then
        echo "截断日志文件: $log"
        truncate -s "$MAX_SIZE" "$log"
    fi
done

echo "✓ 清理完成"

清理脚本 PowerShell 版本

# 文件名:clean.ps1
# 用途:清理未使用的 Docker 资源(Windows 版本)
# 使用方法:在 PowerShell 中运行 .\\clean.ps1

# 清理停止的容器
docker container prune -f

# 清理未使用的镜像
docker image prune -f

# 清理未使用的网络
docker network prune -f

# 清理构建缓存
docker builder prune -f

# 清理所有未使用的资源
docker system prune -f

# Windows 日志清理(PowerShell 7+)
$LOG_DIR = "$env:USERPROFILE\\.docker"
if (Test-Path $LOG_DIR) {
    $MAX_SIZE = 10MB
    Get-ChildItem $LOG_DIR -Recurse -Filter "*.log" |
        Where-Object { $_.Length -gt $MAX_SIZE } |
        ForEach-Object {
            Write-Host "截断日志文件: $($_.FullName)"
            Set-Content -Path $_.FullName -Value "" -NoNewline
        }
}

Write-Host "✓ 清理完成"

📝 注意

  • 日志清理部分仅适用于 PowerShell 7+,Windows PowerShell 5.1 可能不完全支持
  • Linux 特有命令(如 findstat)不适用于 Windows

11.3 健康检查脚本

#!/bin/bash
# 文件名:health_check.sh
# 用途:检查所有服务健康状态

COMPOSE_DIR="/opt/myapp"  # 修改为你的项目路径
cd "$COMPOSE_DIR" || exit 1

echo "=== 服务状态检查 ==="
docker compose ps

echo ""
echo "=== 健康检查 ==="

# 检查每个服务
for service in $(docker compose config --services); do
    status=$(docker compose ps $service | tail -1 | awk '{print $4}')

    if [ "$status" = "Up" ]; then
        # 检查健康状态
        health=$(docker inspect --format='{{if .State.Health}}{{.State.Health.Status}}{{else}}no-healthcheck{{end}}' $service)

        if [ "$health" = "healthy" ] || [ "$health" = "no-healthcheck" ]; then
            echo "✓ $service 运行正常"
        else
            echo "✗ $service 健康检查失败: $health"
            docker compose logs --tail=20 $service
        fi
    else
        echo "✗ $service 已停止: $status"
        echo "  尝试重启..."
        docker compose restart $service
    fi
done

echo ""
echo "=== 资源使用 ==="
docker stats --no-stream

健康检查 PowerShell 版本

# 文件名:health_check.ps1
# 用途:检查所有服务健康状态(Windows 版本)
# 使用方法:在 PowerShell 中运行 .\\health_check.ps1

# 配置(修改为你的项目路径)
$COMPOSE_DIR = "C:\\projects\\myapp"

# 切换到项目目录
Set-Location $COMPOSE_DIR

Write-Host "=== 服务状态检查 ==="
docker compose ps

Write-Host ""
Write-Host "=== 健康检查 ==="

# 检查每个服务
$services = docker compose config --services 2>$null
foreach ($service in $services) {
    $statusLine = docker compose ps $service | Select-Object -Last 1
    $status = ($statusLine -split '\s+')[3]

    if ($status -eq "Up") {
        # 检查健康状态
        $health = docker inspect --format='{{if .State.Health}}{{.State.Health.Status}}{{else}}no-healthcheck{{end}}' $service 2>$null

        if ($health -eq "healthy" -or $health -eq "no-healthcheck") {
            Write-Host "✓ $service 运行正常"
        } else {
            Write-Host "✗ $service 健康检查失败: $health"
            docker compose logs --tail=20 $service
        }
    } else {
        Write-Host "✗ $service 已停止: $status"
        Write-Host "  尝试重启..."
        docker compose restart $service
    }
}

Write-Host ""
Write-Host "=== 资源使用 ==="
docker stats --no-stream

11.4 定时任务配置(crontab)

# 编辑 crontab
crontab -e

# 添加以下任务(每天凌晨 2 点备份)
0 2 * * * /opt/scripts/backup.sh >> /opt/logs/backup.log 2>&1

# 每周日凌晨 3 点清理
0 3 * * 0 /opt/scripts/clean.sh >> /opt/logs/clean.log 2>&1

# 每小时健康检查
0 * * * * /opt/scripts/health_check.sh >> /opt/logs/health.log 2>&1

12. 常见问题与排查

12.1 容器启动失败

错误信息Cannot start service xxx: network not found

可能原因

  • 网络被删除
  • 网络配置错误

解决步骤

# 1. 检查网络状态
docker network ls

# 2. 重新创建网络
docker network create app-network

# 3. 重新启动服务
docker compose down
docker compose up -d

12.2 端口冲突

错误信息Bind for 0.0.0.0:80: unexpected address (error during binding)

可能原因

  • 端口已被其他程序占用

解决步骤

# Windows: 查看端口占用
netstat -ano | findstr :80

# Linux: 查看端口占用
sudo lsof -i :80

# 杀死占用进程或更换端口

12.3 权限问题

错误信息Permission denied

可能原因

  • 宿主机目录权限不足
  • SELinux 或 AppArmor 限制

解决步骤

# Linux: 修改目录权限
sudo chown -R $(id -u):$(id -g) ./data

# 添加 SELinux 策略(如果启用)
chcon -R -t svirt_sandbox_file_t ./data

# 或者在 docker-compose.yaml 中禁用
security_opt:
  - apparmor:unconfined

12.4 内存溢出(OOM)

错误信息Killed 或容器被 OOM

解决步骤

# 在 docker-compose.yaml 中添加资源限制
services:
  app:
    mem_limit: 512m
    memswap_limit: 512m
    # 调整 JVM 堆内存(Java 应用)
    environment:
      - JVM_OPTS=-Xmx256m

12.5 网络通信问题

问题:容器之间无法通信

排查步骤

# 1. 检查网络
docker network inspect app-network

# 2. 测试网络连通性
docker compose exec app ping db

# 3. 检查 DNS 解析
docker compose exec app nslookup db

# 4. 查看日志
docker compose logs app

13. 性能优化建议

13.1 镜像优化

# 使用多阶段构建减小镜像大小
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY . .
CMD ["node", "app.js"]

# 使用 alpine 变体减小基础镜像大小
FROM nginx:alpine
FROM python:3.12-alpine
FROM node:18-alpine

13.2 资源限制调优

services:
  app:
    # 根据实际需求设置合理的资源限制
    mem_limit: "512m"  # 留出足够余量给系统和 Docker
    cpus: "1.0"
    # 对于 Java 应用,堆内存不应超过容器内存的 75%
    environment:
      - JVM_OPTS=-Xmx384m

13.3 日志优化

services:
  app:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"
        compress: "true"

14. 监控与日志聚合

14.1 使用 Portainer 管理容器

version: "3.8"

services:
  portainer:
    image: portainer/portainer-ce:latest
    container_name: portainer
    restart: unless-stopped
    ports:
      - "9000:9000"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer-data:/data

volumes:
  portainer-data:

访问 http://your-server:9000 即可通过 Web UI 管理 Docker。

14.2 使用 GRAYLOG 日志聚合

(详见专门的日志聚合指南)

14.3 Docker Scout 容器漏洞扫描

Docker Scout 是 Docker 官方提供的容器安全扫描工具,可以分析镜像中的漏洞并提供修复建议。

安装与启用

Docker Scout 已集成在 Docker Desktop 中,无需单独安装。对于 CLI 用户:

# 检查 Docker Scout 版本
docker scout version

# 在 Docker Desktop 中启用 Scout
# 设置 → Docker Scout → 启用分析

扫描镜像漏洞

# 扫描本地镜像
docker scout cves nginx:latest

# 扫描并显示所有漏洞(包括低风险)
docker scout cves --env-var SPRING_KAFKA_BOOTSTRAPSERVERS=localhost:9092 postgres:16

# 扫描特定镜像并生成报告
docker scout cves --format generic --output scout-report.json myapp:latest

查看镜像推荐

# 查看镜像推荐(优化建议)
docker scout recommend nginx:latest

# 查看推荐的基础镜像
docker scout compare nginx:latest --to postgres:16

CI/CD 集成

在 GitHub Actions 中使用 Docker Scout:

# .github/workflows/security.yml
name: Security Scan

on: [push, pull_request]

jobs:
  scout:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run Docker Scout
        uses: docker/scout-action@v1
        with:
          image: myapp:latest
          only-fixed: true  # 只显示已修复的漏洞
          only-severity: high,critical  # 只显示高危和严重漏洞

📝 提示:Docker Scout 会显示 CVE 漏洞评分,建议优先修复 Critical 和 High 级别的漏洞。

14.4 docker init 快速初始化

docker init 是 Docker Desktop 2.x 引入的快速初始化工具,可以自动生成 Dockerfile、docker-compose.yaml 等文件。

基本用法

# 进入项目目录
cd my-project

# 初始化 Docker 配置
docker init

# 查看生成的文件
ls -la
# .dockerignore
# Dockerfile
# docker-compose.yaml
# docker-entrypoint.sh(如果需要)

生成文件说明

docker init 会根据项目类型生成相应的配置文件:

文件说明
Dockerfile应用的构建指令
docker-compose.yaml多容器服务定义
.dockerignore构建时忽略的文件
entrypoint容器启动脚本(可选)

支持的项目类型

# 查看支持的语言/框架
docker init --help

# 示例输出:
# 1. Python
# 2. Node
# 3. Go
# 4. Java
# 5. Rust
# 6. ASP.NET Core
# 7. PHP
# 8. Ruby

实际示例(Node.js 项目)

# 创建示例项目
mkdir my-node-app && cd my-node-app
npm init -y

# 添加示例代码
echo 'console.log("Hello from Docker!");' > index.js

# 初始化 Docker 配置
docker init

# 查看生成的文件内容
cat Dockerfile
cat docker-compose.yaml

# 构建和运行
docker compose up --build

📝 注意docker init 生成的是基础配置,实际项目中可能需要根据需求进行调整。

14.5 Watchtower 自动更新容器

Watchtower 是一个自动更新运行中容器的工具,会定期检查镜像更新并自动重启容器。

快速启动 Watchtower

# docker-compose.yaml
version: "3.8"

services:
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ~/.docker/config.json:/config.json:ro  # Docker Hub 认证(可选)
    environment:
      - WATCHTOWER_CLEANUP=true        # 更新后清理旧镜像
      - WATCHTOWER_POLL_INTERVAL=3600  # 每小时检查一次(3600 秒)
      - WATCHTOWER_INCLUDE_STOPPED=true  # 包含已停止的容器
    restart: unless-stopped

启动 Watchtower

# 后台运行
docker compose up -d

# 查看日志
docker compose logs -f watchtower

# 停止 Watchtower
docker compose down

常用配置选项

环境变量说明默认值
WATCHTOWER_POLL_INTERVAL检查间隔(秒)300(5分钟)
WATCHTOWER_CLEANUP更新后清理旧镜像false
WATCHTOWER_INCLUDE_STOPPED包含已停止容器false
WATCHTOWER_REMOVE_IMAGES更新后删除旧镜像false
WATCHTOWER_DEBUG启用调试日志false

更新特定容器

如果只想监控特定容器,使用容器名称:

services:
  watchtower:
    image: containrrr/watchtower
    container_name: watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    command: --interval 30 nginx redis postgres  # 只监控这些容器
    restart: unless-stopped

单次更新模式

# 运行一次 Watchtower(立即检查并更新)
docker run --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  containrrr/watchtower \
  --run-once

📝 注意:生产环境中使用 Watchtower 需要谨慎,建议先在测试环境中验证,并设置合理的检查间隔,避免频繁重启。


15. 总结

本文档涵盖了 Docker 部署的核心知识点:

章节核心内容
基础概念镜像、容器、仓库的原理
环境准备Windows/Linux/macOS 安装配置
核心操作镜像、容器、网络的常用命令
Compose 详解YAML 配置语法详解
实战示例Nginx+PHP、PostgreSQL+应用
数据持久化命名卷、绑定挂载、备份恢复
健康检查配置与依赖管理
日志管理日志配置与清理
安全加固网络隔离、权限控制
自动化脚本备份、清理、健康检查
常见问题故障排查与解决
性能优化镜像、资源、日志优化

推荐学习路径

  1. 先理解 Docker 基础概念
  2. 动手实践基本操作命令
  3. 深入学习 Docker Compose
  4. 理解数据持久化和网络安全
  5. 实践自动化维护

延伸阅读


本文档由人工智能协会整理

2026 年 3 月