SRE 每日主题:Docker 生产环境最佳实践
日期: 2026-03-20
主题序号: 8 (20 % 12 = 8)
适用环境: 生产环境 Docker 部署
一、Docker 生产环境架构概述
1.1 推荐架构
┌─────────────────────────────────────────────────────────────┐
│ 负载均衡层 (HAProxy/Nginx) │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ Docker Swarm / Kubernetes │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Node 1 │ │ Node 2 │ │ Node 3 │ │
│ │ (Manager) │ │ (Worker) │ │ (Worker) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ 共享存储 (NFS/Ceph/Portworx) │
└─────────────────────────────────────────────────────────────┘
1.2 核心组件
| 组件 |
推荐方案 |
说明 |
| 容器编排 |
Docker Swarm / Kubernetes |
根据规模选择 |
| 网络插件 |
Calico / Flannel |
跨节点通信 |
| 存储驱动 |
overlay2 |
默认且推荐 |
| 日志驱动 |
json-file + logrotate |
或 journald |
| 监控 |
Prometheus + cAdvisor |
容器指标采集 |
二、Docker 守护进程配置优化
2.1 /etc/docker/daemon.json 完整配置
{
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3",
"compress": "true"
},
"live-restore": true,
"userns-remap": "default",
"no-new-privileges": true,
"default-ulimits": {
"nofile": {
"Name": "nofile",
"Hard": 65536,
"Soft": 65536
},
"nproc": {
"Name": "nproc",
"Hard": 65536,
"Soft": 65536
}
},
"max-concurrent-downloads": 5,
"max-concurrent-uploads": 5,
"default-shm-size": "64m",
"iptables": true,
"ip-forward": true,
"ip-masq": true,
"bridge": "docker0",
"fixed-cidr": "172.17.0.0/16",
"registry-mirrors": [
"https://registry.docker-cn.com",
"https://docker.mirrors.ustc.edu.cn"
],
"insecure-registries": [],
"dns": ["8.8.8.8", "114.114.114.114"],
"dns-search": ["example.com"],
"mtu": 1500,
"default-runtime": "runc",
"runtimes": {
"runc": {
"path": "runc"
},
"kata": {
"path": "kata-runtime"
}
},
"metrics-addr": "0.0.0.0:9323",
"experimental": false
}
2.2 关键参数说明
| 参数 |
推荐值 |
说明 |
max-size |
100m |
单日志文件最大大小,防止磁盘爆满 |
max-file |
3 |
日志文件保留数量 |
live-restore |
true |
Docker 重启时容器继续运行 |
userns-remap |
default |
启用用户命名空间增强安全 |
nofile |
65536 |
文件描述符限制,避免 Too many open files |
metrics-addr |
0.0.0.0:9323 |
Prometheus 指标暴露端口 |
2.3 应用配置并重启
# 备份原配置
sudo cp /etc/docker/daemon.json /etc/docker/daemon.json.bak
# 验证配置语法
sudo dockerd --validate
# 重载配置(无需重启容器)
sudo systemctl reload docker
# 或完全重启
sudo systemctl daemon-reload
sudo systemctl restart docker
# 验证配置生效
docker info | grep -E "Storage|Logging|Live Restore"
三、Dockerfile 最佳实践
3.1 生产级 Dockerfile 模板
# ============================================
# 阶段 1: 构建阶段
# ============================================
FROM node:20-alpine AS builder
# 设置工作目录
WORKDIR /app
# 安装必要的构建依赖
RUN apk add --no-cache python3 make g++
# 复制 package 文件(利用缓存)
COPY package*.json ./
# 安装生产依赖
RUN npm ci --only=production
# 复制源代码
COPY . .
# 构建应用
RUN npm run build
# ============================================
# 阶段 2: 运行阶段(最小化镜像)
# ============================================
FROM node:20-alpine
# 添加标签信息
LABEL maintainer="sre-team@example.com"
LABEL version="1.0.0"
LABEL description="Production application"
# 创建非 root 用户
RUN addgroup -g 1001 -S appgroup && \
adduser -u 1001 -S appuser -G appgroup
# 安装运行时依赖(如有需要)
RUN apk add --no-cache curl ca-certificates tzdata && \
cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone && \
apk del curl
# 设置工作目录
WORKDIR /app
# 从构建阶段复制产物
COPY --from=builder --chown=appuser:appgroup /app/node_modules ./node_modules
COPY --from=builder --chown=appuser:appgroup /app/dist ./dist
COPY --from=builder --chown=appuser:appgroup /app/package*.json ./
# 切换到非 root 用户
USER appuser
# 暴露端口
EXPOSE 3000
# 健康检查
HEALTHCHECK --interval=30s --timeout=10s --start-period=40s --retries=3 \
CMD curl -f http://localhost:3000/health || exit 1
# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000
# 启动命令(使用 exec 形式)
CMD ["node", "dist/index.js"]
3.2 Dockerfile 最佳实践清单
| 实践 |
说明 |
示例 |
| 多阶段构建 |
减小最终镜像大小 |
FROM ... AS builder |
| 非 root 用户 |
安全隔离 |
USER appuser |
| .dockerignore |
排除不必要文件 |
见下文 |
| 层缓存优化 |
频繁变化的放后面 |
先 COPY package.json |
| 固定基础镜像版本 |
避免意外变更 |
node:20-alpine 而非 node:latest |
| 健康检查 |
容器状态监控 |
HEALTHCHECK |
| exec 形式 CMD |
正确信号处理 |
CMD ["node", "app.js"] |
3.3 .dockerignore 模板
# 依赖目录
node_modules
npm-debug.log
# 构建产物
dist
build
*.log
# 开发配置
.git
.gitignore
.dockerignore
Dockerfile
docker-compose*.yml
# 测试文件
test
tests
*.test.js
*.spec.js
coverage
# IDE 配置
.idea
.vscode
*.swp
*.swo
# 文档
README.md
docs
*.md
# 环境变量(敏感)
.env
.env.local
.env.*.local
# 其他
.DS_Store
Thumbs.db
四、Docker Compose 生产配置
4.1 生产级 docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
args:
- NODE_ENV=production
image: registry.example.com/app:latest
container_name: app-production
restart: unless-stopped
stop_grace_period: 30s
stop_signal: SIGTERM
# 资源限制
deploy:
resources:
limits:
cpus: '2.0'
memory: 2G
reservations:
cpus: '0.5'
memory: 512M
# 健康检查
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
# 网络配置
networks:
- app-network
ports:
- "3000:3000"
# 环境变量
environment:
- NODE_ENV=production
- LOG_LEVEL=info
- DB_HOST=db
- REDIS_HOST=redis
env_file:
- .env.production
# 日志配置
logging:
driver: json-file
options:
max-size: "100m"
max-file: "3"
compress: "true"
# 依赖服务
depends_on:
db:
condition: service_healthy
redis:
condition: service_healthy
# 挂载(只读)
volumes:
- ./config:/app/config:ro
- app-data:/app/data
db:
image: postgres:15-alpine
container_name: db-production
restart: unless-stopped
# 资源限制
deploy:
resources:
limits:
cpus: '2.0'
memory: 4G
# 健康检查
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
environment:
- POSTGRES_DB=appdb
- POSTGRES_USER=appuser
- POSTGRES_PASSWORD_FILE=/run/secrets/db_password
secrets:
- db_password
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init-scripts:/docker-entrypoint-initdb.d:ro
logging:
driver: json-file
options:
max-size: "100m"
max-file: "3"
redis:
image: redis:7-alpine
container_name: redis-production
restart: unless-stopped
command: redis-server --appendonly yes --maxmemory 1gb --maxmemory-policy allkeys-lru
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
volumes:
- redis-data:/data
logging:
driver: json-file
options:
max-size: "50m"
max-file: "3"
nginx:
image: nginx:alpine
container_name: nginx-production
restart: unless-stopped
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
- ./nginx/ssl:/etc/nginx/ssl:ro
- nginx-logs:/var/log/nginx
depends_on:
- app
networks:
- app-network
networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
postgres-data:
driver: local
redis-data:
driver: local
app-data:
driver: local
nginx-logs:
driver: local
secrets:
db_password:
file: ./secrets/db_password.txt
五、资源限制与性能调优
5.1 容器资源限制命令
# 运行容器时限制资源
docker run -d \
--name myapp \
--memory="2g" \
--memory-swap="4g" \
--memory-reservation="1g" \
--cpus="2.0" \
--cpu-shares="1024" \
--pids-limit="100" \
--ulimit nofile=65536:65536 \
registry.example.com/app:latest
# 更新运行中容器的资源限制
docker update \
--memory="4g" \
--cpus="4.0" \
myapp
5.2 资源参数说明
| 参数 |
说明 |
推荐值 |
--memory |
内存硬限制 |
根据应用需求 |
--memory-swap |
内存 + Swap 总限制 |
memory 的 2 倍 |
--memory-reservation |
内存软限制(回收阈值) |
memory 的 50% |
--cpus |
CPU 核心数限制 |
根据负载 |
--cpu-shares |
CPU 权重(相对值) |
默认 1024 |
--pids-limit |
进程数限制 |
100-1000 |
--ulimit nofile |
文件描述符限制 |
65536 |
5.3 监控容器资源使用
# 实时查看容器资源使用
docker stats --no-stream
# 持续监控
docker stats
# 查看特定容器
docker stats app-production db-production
# 格式化输出
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"
# 查看容器详细信息
docker inspect app-production | jq '.[0].HostConfig'
# 查看容器进程
docker top app-production
# 查看容器资源使用详情
docker exec app-production cat /sys/fs/cgroup/memory/memory.usage_in_bytes
六、网络配置与优化
6.1 Docker 网络类型对比
| 网络类型 |
适用场景 |
性能 |
隔离性 |
| bridge |
单机多容器 |
中 |
中 |
| host |
高性能需求 |
高 |
低 |
| overlay |
跨节点通信 |
中 |
高 |
| macvlan |
直接物理网络 |
高 |
高 |
| none |
完全隔离 |
- |
最高 |
6.2 创建自定义网络
# 创建自定义 bridge 网络
docker network create \
--driver bridge \
--subnet 172.20.0.0/16 \
--gateway 172.20.0.1 \
--ip-range 172.20.0.0/24 \
--opt com.docker.network.bridge.enable_icc=true \
--opt com.docker.network.bridge.enable_ip_masquerade=true \
--opt com.docker.network.bridge.host_binding_ipv4=0.0.0.0 \
--opt com.docker.network.driver.mtu=1500 \
app-network
# 创建 overlay 网络(Swarm 模式)
docker network create \
--driver overlay \
--subnet 10.0.0.0/24 \
--attachable \
swarm-network
# 创建 macvlan 网络(直接物理网络)
docker network create -d macvlan \
--subnet=192.168.1.0/24 \
--gateway=192.168.1.1 \
-o parent=eth0 \
macvlan-network
6.3 网络性能优化
# 调整 Docker 网桥 MTU
ip link set docker0 mtu 1450
# 启用 IP 转发(永久)
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
# 调整网络连接跟踪表
echo "net.netfilter.nf_conntrack_max=1048576" >> /etc/sysctl.conf
echo "net.netfilter.nf_conntrack_tcp_timeout_established=432000" >> /etc/sysctl.conf
sysctl -p
# 禁用 iptables(如使用其他防火墙)
# 在 daemon.json 中设置 "iptables": false
6.4 网络故障排查
# 查看网络列表
docker network ls
# 查看网络详情
docker network inspect app-network
# 查看容器网络配置
docker exec app-production ip addr
docker exec app-production ip route
docker exec app-production cat /etc/resolv.conf
# 测试容器间连通性
docker exec app-production ping db-production
docker exec app-production curl http://db-production:5432
# 查看端口映射
docker port app-production
# 查看网络连接
docker exec app-production netstat -tlnp
docker exec app-production ss -tlnp
# 抓包分析
docker exec app-production tcpdump -i eth0 -n port 3000
七、存储管理与数据持久化
7.1 存储驱动选择
| 存储驱动 |
适用场景 |
性能 |
推荐度 |
| overlay2 |
通用场景 |
高 |
⭐⭐⭐⭐⭐ |
| aufs |
旧系统兼容 |
中 |
⭐⭐ |
| devicemapper |
特殊需求 |
中 |
⭐⭐ |
| zfs |
ZFS 文件系统 |
高 |
⭐⭐⭐ |
| btrfs |
Btrfs 文件系统 |
高 |
⭐⭐⭐ |
7.2 查看存储信息
# 查看存储驱动
docker info | grep "Storage Driver"
# 查看磁盘使用
docker system df
# 查看详细存储信息
docker system df -v
# 查看镜像层
docker history registry.example.com/app:latest
# 查看容器存储使用
docker inspect app-production | jq '.[0].GraphDriver'
7.3 卷管理最佳实践
# 创建命名卷
docker volume create --driver local \
--opt type=none \
--opt device=/data/app-data \
--opt o=bind \
app-data
# 创建加密卷(使用 dm-crypt)
# 先加密设备,然后挂载
# 备份卷数据
docker run --rm \
-v app-data:/source:ro \
-v $(pwd):/backup \
alpine tar czf /backup/app-data-backup.tar.gz -C /source .
# 恢复卷数据
docker run --rm \
-v app-data:/destination \
-v $(pwd):/backup \
alpine tar xzf /backup/app-data-backup.tar.gz -C /destination
# 清理未使用卷
docker volume prune -f
# 查看卷详情
docker volume inspect app-data
7.4 存储性能优化
# 使用 tmpfs 挂载(内存存储)
docker run -d \
--name cache-app \
--tmpfs /cache:size=1G \
registry.example.com/cache:latest
# 调整 I/O 调度器(宿主机)
echo deadline > /sys/block/sda/queue/scheduler
# 使用 SSD 存储 Docker 数据目录
# 修改 /etc/docker/daemon.json
{
"data-root": "/mnt/ssd/docker"
}
八、安全加固
8.1 Docker 安全基线配置
# 1. 启用 TLS 认证(Docker 守护进程)
# /etc/docker/daemon.json
{
"tls": true,
"tlsverify": true,
"tlscacert": "/etc/docker/certs/ca.pem",
"tlscert": "/etc/docker/certs/server-cert.pem",
"tlskey": "/etc/docker/certs/server-key.pem",
"hosts": ["tcp://0.0.0.0:2376"]
}
# 2. 启用用户命名空间
# /etc/docker/daemon.json
{
"userns-remap": "default"
}
# 3. 启用内容信任(镜像签名验证)
export DOCKER_CONTENT_TRUST=1
# 4. 扫描镜像漏洞
docker scan registry.example.com/app:latest
# 或使用 trivy
trivy image registry.example.com/app:latest
8.2 容器安全运行参数
docker run -d \
--name secure-app \
--read-only \ # 只读文件系统
--tmpfs /tmp:rw,noexec,nosuid,size=100m \
--tmpfs /var/run:rw,noexec,nosuid,size=50m \
--security-opt no-new-privileges:true \
--security-opt seccomp=unconfined \
--cap-drop=ALL \
--cap-add=NET_BIND_SERVICE \
--user 1001:1001 \
--privileged=false \
registry.example.com/app:latest
8.3 安全参数说明
| 参数 |
说明 |
风险等级 |
--read-only |
只读根文件系统 |
高 |
--cap-drop=ALL |
删除所有能力 |
高 |
--cap-add |
按需添加能力 |
高 |
--security-opt no-new-privileges |
禁止提权 |
高 |
--user |
非 root 运行 |
高 |
--privileged |
禁止特权模式 |
极高 |
--pid=host |
禁止共享主机 PID |
高 |
--network=host |
谨慎使用主机网络 |
中 |
8.4 审计与日志
# 启用 Docker 审计日志
# /etc/docker/daemon.json
{
"log-driver": "syslog",
"log-opts": {
"syslog-address": "udp://127.0.0.1:514",
"tag": "docker"
}
}
# 查看容器安全事件
journalctl -u docker | grep -E "security|privilege|capability"
# 使用 Docker Bench for Security 检查
docker run --rm --net host --pid host --userns host --cap-add audit_control \
-e DOCKER_CONTENT_TRUST=$DOCKER_CONTENT_TRUST \
-v /etc:/etc:ro \
-v /usr/bin/containerd:/usr/bin/containerd:ro \
-v /usr/bin/runc:/usr/bin/runc:ro \
-v /usr/lib/systemd:/usr/lib/systemd:ro \
-v /var/lib:/var/lib:ro \
-v /var/run/docker.sock:/var/run/docker.sock:ro \
docker/docker-bench-security
九、监控与告警
9.1 Prometheus 配置
# prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: 'docker'
static_configs:
- targets: ['localhost:9323']
- job_name: 'cadvisor'
static_configs:
- targets: ['localhost:8080']
- job_name: 'node-exporter'
static_configs:
- targets: ['localhost:9100']
- job_name: 'docker-services'
docker_sd_configs:
- host: unix:///var/run/docker.sock
relabel_configs:
- source_labels: [__meta_docker_container_name]
regex: '/(.*)'
target_label: 'container'
9.2 关键监控指标
# 容器 CPU 使用率
rate(container_cpu_usage_seconds_total{container_label_com_docker_swarm_service_name="app"}[5m]) * 100
# 容器内存使用率
container_memory_usage_bytes{container_label_com_docker_swarm_service_name="app"} / container_spec_memory_limit_bytes{container_label_com_docker_swarm_service_name="app"} * 100
# 容器重启次数
increase(container_last_seen{container_label_com_docker_swarm_service_name="app"}[1h])
# 容器网络接收
rate(container_network_receive_bytes_total{container_label_com_docker_swarm_service_name="app"}[5m])
# 容器网络发送
rate(container_network_transmit_bytes_total{container_label_com_docker_swarm_service_name="app"}[5m])
# 容器健康状态
container_healthcheck_result{container_label_com_docker_swarm_service_name="app"}
# 磁盘使用率
node_filesystem_avail_bytes{mountpoint="/var/lib/docker"} / node_filesystem_size_bytes{mountpoint="/var/lib/docker"} * 100
9.3 告警规则
# alerting-rules.yml
groups:
- name: docker-alerts
rules:
- alert: ContainerHighCPU
expr: rate(container_cpu_usage_seconds_total[5m]) * 100 > 80
for: 5m
labels:
severity: warning
annotations:
summary: "容器 CPU 使用率过高"
description: "容器 {{ $labels.container }} CPU 使用率 {{ $value }}%"
- alert: ContainerHighMemory
expr: container_memory_usage_bytes / container_spec_memory_limit_bytes * 100 > 90
for: 5m
labels:
severity: warning
annotations:
summary: "容器内存使用率过高"
description: "容器 {{ $labels.container }} 内存使用率 {{ $value }}%"
- alert: ContainerRestarting
expr: increase(container_last_seen[5m]) > 5
labels:
severity: critical
annotations:
summary: "容器频繁重启"
description: "容器 {{ $labels.container }} 5 分钟内重启多次"
- alert: ContainerUnhealthy
expr: container_healthcheck_result == 2
for: 2m
labels:
severity: critical
annotations:
summary: "容器健康检查失败"
description: "容器 {{ $labels.container }} 健康检查失败"
- alert: DockerDiskLow
expr: node_filesystem_avail_bytes{mountpoint="/var/lib/docker"} / node_filesystem_size_bytes{mountpoint="/var/lib/docker"} * 100 < 20
for: 10m
labels:
severity: warning
annotations:
summary: "Docker 磁盘空间不足"
description: "Docker 数据目录磁盘使用率 {{ $value }}%"
9.4 监控命令
# 查看容器实时统计
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}\t{{.BlockIO}}"
# 查看容器事件
docker events --since 1h
# 查看容器日志
docker logs --tail 100 --follow app-production
# 查看容器日志(带时间戳)
docker logs --tail 100 --timestamps app-production
# 导出容器指标
curl -s http://localhost:9323/metrics | grep container
# cAdvisor 指标
curl -s http://localhost:8080/metrics | head -50
十、故障排查指南
10.1 常见问题排查流程
┌─────────────────────────────────────────────────────────────┐
│ 容器故障排查流程 │
└─────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────┐
│ 1. 容器状态检查 │
│ docker ps -a │
└───────────────────────┘
│
┌───────────────┼───────────────┐
▼ ▼ ▼
┌──────────┐ ┌──────────┐ ┌──────────┐
│ Exited │ │ Unhealthy│ │ OOMKilled│
└──────────┘ └──────────┘ └──────────┘
│ │ │
▼ ▼ ▼
查看退出码 检查健康检查 增加内存限制
docker logs docker inspect --memory
10.2 容器退出码含义
| 退出码 |
含义 |
排查方向 |
| 0 |
正常退出 |
无需排查 |
| 1 |
应用程序错误 |
查看日志 |
| 125 |
Docker 启动失败 |
检查镜像/参数 |
| 126 |
命令不可执行 |
检查 ENTRYPOINT |
| 127 |
命令未找到 |
检查 PATH/依赖 |
| 137 |
OOMKilled (SIGKILL) |
增加内存 |
| 143 |
SIGTERM |
优雅关闭超时 |
| 139 |
段错误 |
代码/库问题 |
10.3 排查命令集合
# ==================== 状态检查 ====================
# 查看所有容器(包括已停止)
docker ps -a
# 查看最近创建的容器
docker ps -a --last 5
# 查看容器详情
docker inspect app-production
# 查看容器状态变化历史
docker events --since 1h --filter container=app-production
# ==================== 日志分析 ====================
# 查看容器日志
docker logs --tail 200 app-production
# 查看日志(带时间戳和跟随)
docker logs --timestamps --follow --tail 100 app-production
# 查看日志大小
du -sh /var/lib/docker/containers/*/
# 搜索日志中的错误
docker logs app-production 2>&1 | grep -i "error\|exception\|fatal"
# ==================== 资源检查 ====================
# 查看容器资源使用
docker stats --no-stream app-production
# 查看容器 OOM 记录
dmesg | grep -i "killed process"
journalctl -k | grep -i "oom"
# 查看容器进程
docker top app-production
# ==================== 网络检查 ====================
# 测试容器网络
docker exec app-production ping -c 4 8.8.8.8
docker exec app-production curl -v http://localhost:3000/health
# 查看容器网络配置
docker exec app-production ip addr
docker exec app-production ip route
docker exec app-production cat /etc/resolv.conf
# 查看端口监听
docker exec app-production netstat -tlnp
# ==================== 存储检查 ====================
# 查看磁盘使用
df -h /var/lib/docker
# 查看 Docker 系统使用
docker system df
# 查看容器存储
docker inspect app-production | jq '.[0].GraphDriver'
# ==================== 深入调试 ====================
# 进入容器调试
docker exec -it app-production /bin/sh
# 以 root 身份进入(如有权限问题)
docker exec -it --user root app-production /bin/sh
# 使用 nsenter 进入容器命名空间
PID=$(docker inspect --format '{{.State.Pid}}' app-production)
nsenter -t $PID -n ip addr
# 导出容器文件系统
docker export app-production > container.tar
10.4 典型故障场景
场景 1: 容器启动后立即退出
# 1. 查看退出码
docker ps -a | grep app-production
# 2. 查看日志
docker logs app-production
# 3. 检查命令/入口点
docker inspect app-production | jq '.[0].Config.Cmd'
docker inspect app-production | jq '.[0].Config.Entrypoint'
# 4. 前台运行调试
docker run -it --entrypoint /bin/sh registry.example.com/app:latest
# 5. 检查依赖服务
docker network inspect app-network
场景 2: 内存溢出 (OOMKilled)
# 1. 确认 OOM
docker inspect app-production | jq '.[0].State.OOMKilled'
# 2. 查看内核日志
dmesg | grep -i "killed process.*$(docker inspect --format '{{.State.Pid}}' app-production)"
# 3. 增加内存限制
docker update --memory="4g" --memory-swap="8g" app-production
# 4. 优化应用内存使用
# 检查应用内存泄漏
docker exec app-production cat /sys/fs/cgroup/memory/memory.usage_in_bytes
场景 3: 容器无法访问外部网络
# 1. 检查 DNS
docker exec app-production cat /etc/resolv.conf
docker exec app-production nslookup google.com
# 2. 测试连通性
docker exec app-production ping -c 4 8.8.8.8
# 3. 检查 iptables
iptables -t nat -L -n | grep docker
# 4. 检查 IP 转发
sysctl net.ipv4.ip_forward
# 5. 重启 Docker 网络
systemctl restart docker
场景 4: 磁盘空间不足
# 1. 检查磁盘使用
df -h
docker system df
# 2. 清理未使用资源
docker system prune -a -f --volumes
# 3. 清理悬空镜像
docker image prune -a -f
# 4. 清理日志
find /var/lib/docker/containers -name "*.log" -exec truncate -s 0 {} \;
# 5. 配置日志轮转
# 确保 daemon.json 中有 log-opts 配置
十一、CI/CD 集成
11.1 GitLab CI 示例
# .gitlab-ci.yml
stages:
- build
- test
- security
- push
- deploy
variables:
DOCKER_HOST: tcp://docker:2375
DOCKER_TLS_CERTDIR: ""
IMAGE_NAME: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA
services:
- docker:24-dind
build:
stage: build
script:
- docker build -t $IMAGE_NAME .
- docker save $IMAGE_NAME > image.tar
artifacts:
paths:
- image.tar
expire_in: 1 hour
test:
stage: test
script:
- docker load < image.tar
- docker run --rm $IMAGE_NAME npm test
security-scan:
stage: security
script:
- docker load < image.tar
- trivy image --exit-code 1 --severity HIGH,CRITICAL $IMAGE_NAME
allow_failure: true
push:
stage: push
script:
- docker load < image.tar
- echo $CI_REGISTRY_PASSWORD | docker login -u $CI_REGISTRY_USER --password-stdin $CI_REGISTRY
- docker push $IMAGE_NAME
- docker tag $IMAGE_NAME $CI_REGISTRY_IMAGE:latest
- docker push $CI_REGISTRY_IMAGE:latest
only:
- main
deploy:
stage: deploy
script:
- docker stack deploy -c docker-compose.yml app
only:
- main
11.2 GitHub Actions 示例
# .github/workflows/docker-build.yml
name: Docker Build and Push
on:
push:
branches: [main]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_DATE=${{ github.event.head_commit.timestamp }}
VERSION=${{ github.sha }}
- name: Run Trivy vulnerability scanner
uses: aquasecurity/trivy-action@master
with:
image-ref: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }}
format: 'sarif'
output: 'trivy-results.sarif'
severity: 'HIGH,CRITICAL'
- name: Upload Trivy scan results
uses: github/codeql-action/upload-sarif@v2
with:
sarif_file: 'trivy-results.sarif'
十二、性能基准与调优
12.1 性能基准测试
# 使用 docker-bench 测试
docker run --rm \
-v /var/run/docker.sock:/var/run/docker.sock \
--name docker-bench \
docker/docker-bench-security
# 使用 sysbench 测试容器 I/O
docker run --rm \
--name io-test \
ubuntu:latest \
bash -c "apt-get update && apt-get install -y sysbench && sysbench fileio --file-total-size=1G --file-test-mode=rndrw run"
# 网络性能测试
docker run --rm \
--name net-test \
networkstatic/iperf3 \
iperf3 -c <server-ip> -t 30
12.2 性能调优参数
# /etc/sysctl.conf 优化
# 网络连接
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 65535
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.ip_local_port_range = 1024 65535
# TCP 优化
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 1200
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
# 内存优化
vm.swappiness = 1
vm.overcommit_memory = 1
vm.dirty_ratio = 40
vm.dirty_background_ratio = 10
# 文件描述符
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
# 应用优化
sysctl -p
12.3 容器启动优化
# 优化启动速度
# 1. 使用多阶段构建减小镜像大小
# 2. 使用 .dockerignore 排除不必要文件
# 3. 合并 RUN 指令减少层数
# 4. 使用 Alpine 基础镜像
# 示例:优化前后对比
# 优化前:镜像大小 1.2GB,启动时间 30s
# 优化后:镜像大小 150MB,启动时间 5s
十三、备份与恢复
13.1 容器备份策略
# 备份容器配置
docker inspect app-production > app-production-inspect.json
# 备份卷数据
docker run --rm \
-v app-data:/source:ro \
-v $(pwd):/backup \
alpine \
tar czf /backup/app-data-$(date +%Y%m%d).tar.gz -C /source .
# 备份镜像
docker save -o app-image-$(date +%Y%m%d).tar registry.example.com/app:latest
# 备份 Docker 配置
tar czf docker-config-$(date +%Y%m%d).tar.gz /etc/docker/
# 创建备份脚本
cat > /usr/local/bin/docker-backup.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/backup/docker/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# 备份所有卷
for vol in $(docker volume ls -q); do
docker run --rm -v $vol:/source:ro -v $BACKUP_DIR:/backup alpine \
tar czf /backup/$vol.tar.gz -C /source .
done
# 备份镜像列表
docker images --format "{{.Repository}}:{{.Tag}}" > $BACKUP_DIR/images.txt
# 备份容器配置
for container in $(docker ps -q); do
docker inspect $container > $BACKUP_DIR/$(docker inspect --format '{{.Name}}' $container).json
done
echo "Backup completed: $BACKUP_DIR"
EOF
chmod +x /usr/local/bin/docker-backup.sh
13.2 灾难恢复
# 恢复卷数据
docker run --rm \
-v app-data:/destination \
-v $(pwd):/backup \
alpine \
tar xzf /backup/app-data-20260320.tar.gz -C /destination
# 恢复镜像
docker load -i app-image-20260320.tar
# 恢复 Docker 配置
systemctl stop docker
tar xzf docker-config-20260320.tar.gz -C /
systemctl start docker
# 从备份重建容器
docker run -d \
--name app-production \
--restart unless-stopped \
-v app-data:/app/data \
registry.example.com/app:latest
十四、检查清单
14.1 部署前检查
14.2 运维检查
14.3 安全检查
附录:常用命令速查
# 容器管理
docker ps -a # 查看所有容器
docker stop/start/restart <container> # 停止/启动/重启
docker rm <container> # 删除容器
docker exec -it <container> /bin/sh # 进入容器
# 镜像管理
docker images # 列出镜像
docker pull/push <image> # 拉取/推送镜像
docker rmi <image> # 删除镜像
docker build -t <name> . # 构建镜像
# 系统清理
docker system prune -a # 清理所有未使用资源
docker image prune -a # 清理悬空镜像
docker volume prune # 清理未使用卷
docker container prune # 清理停止的容器
# 监控调试
docker stats # 实时资源统计
docker logs -f <container> # 跟随日志
docker inspect <container> # 详细信息
docker events # 实时事件
# 网络
docker network ls # 列出网络
docker network inspect <network> # 网络详情
docker port <container> # 端口映射
文档版本: 1.0
最后更新: 2026-03-20
维护团队: SRE Team