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 部署前检查

  • Docker 版本为 LTS 稳定版
  • daemon.json 配置已优化
  • 存储驱动为 overlay2
  • 日志轮转已配置
  • 资源限制已设置
  • 非 root 用户运行
  • 健康检查已配置
  • 网络隔离已配置
  • 卷持久化已配置
  • 镜像已扫描漏洞

14.2 运维检查

  • 监控告警已配置
  • 日志收集已配置
  • 备份策略已实施
  • 安全更新计划已制定
  • 灾难恢复流程已测试
  • 性能基线已建立
  • 容量规划已完成

14.3 安全检查

  • TLS 认证已启用
  • 用户命名空间已启用
  • 特权容器已禁止
  • 能力限制已配置
  • 镜像签名已验证
  • 安全扫描已集成 CI/CD
  • 审计日志已启用

附录:常用命令速查

# 容器管理
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

results matching ""

    No results matching ""