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
- 下载 Docker Desktop:https://www.docker.com/products/docker-desktop/
- 运行安装程序,务必勾选 WSL2 后端(推荐)
- 安装完成后重启电脑
- 打开 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
- 下载 Docker Desktop for Mac:https://www.docker.com/products/docker-desktop/
- 双击下载的
.dmg文件 - 将 Docker Desktop 图标拖入应用程序文件夹
- 打开 Docker Desktop,等待初始化完成
- 检查菜单栏是否出现 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 镜像:优先使用支持
arm64或arm/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核 | 2GB | 20GB |
| 推荐配置 | 4核 | 4GB | 50GB |
| 高性能配置 | 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 特有命令(如
find、stat)不适用于 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+应用 |
| 数据持久化 | 命名卷、绑定挂载、备份恢复 |
| 健康检查 | 配置与依赖管理 |
| 日志管理 | 日志配置与清理 |
| 安全加固 | 网络隔离、权限控制 |
| 自动化脚本 | 备份、清理、健康检查 |
| 常见问题 | 故障排查与解决 |
| 性能优化 | 镜像、资源、日志优化 |
推荐学习路径:
- 先理解 Docker 基础概念
- 动手实践基本操作命令
- 深入学习 Docker Compose
- 理解数据持久化和网络安全
- 实践自动化维护
延伸阅读:
本文档由人工智能协会整理
2026 年 3 月
评论交流
欢迎留下你的想法