39. Docker 容器化技术指南

目录

点击展开目录

Docker 概述 - 什么是 Docker - 核心概念 - Docker 架构 - 与虚拟机对比

Docker 安装与配置 - 系统要求 - 安装方式 - macOS:Colima(Docker CLI / Compose) - 配置优化 - 镜像加速

Docker 镜像管理 - 镜像基础 - 镜像操作 - Dockerfile 编写 - 镜像优化

Docker 容器管理 - 容器生命周期 - 容器操作 - 数据卷管理 - 网络配置

Docker Compose - Compose 概述 - 编排文件 - 服务管理 - 实战案例

Docker 网络 - 网络模式 - 自定义网络 - 跨主机网络 - 网络故障排查

Docker 存储 - 存储驱动 - 数据持久化 - 存储优化 - 备份恢复

Docker 安全 - 安全基础 - 镜像安全 - 容器安全 - 最佳实践

Docker 监控与日志 - 监控方案 - 日志管理 - 性能调优 - 故障排查

生产环境实践 - 部署策略 - CI/CD 集成 - 集群管理 - 运维经验

Docker 概述

什么是 Docker

Docker 是一个开源的容器化平台,用于开发、交付和运行应用程序。它通过容器技术实现应用程序及其依赖的轻量级虚拟化

核心价值

  • 一致性环境:确保应用在不同环境中的一致性运行
  • 快速部署:秒级启动,提升开发和部署效率
  • 资源高效:相比虚拟机,占用更少的系统资源
  • 微服务支持:天然适合微服务架构

主要解决的问题

  • 环境一致性:解决"在我机器上能跑"的问题
  • 依赖管理:简化复杂的依赖关系管理
  • 部署复杂性:标准化应用部署流程
  • 资源利用率:提高服务器资源利用效率

核心概念

Docker 三大核心组件

组件作用特点类比
镜像 (Image)应用程序模板只读、分层存储程序安装包
容器 (Container)运行实例可读写、隔离运行运行中的程序
仓库 (Repository)镜像存储集中管理、版本控制应用商店

关键概念解析

graph TB subgraph "Docker 核心概念" A["Dockerfile
构建脚本"] B["Image
镜像"] C["Container
容器"] D["Registry
镜像仓库"] end subgraph "构建流程" E["编写 Dockerfile"] F["构建镜像"] G["推送仓库"] H["拉取运行"] end A --> B B --> C B --> D E --> F F --> G G --> H style B fill:#e1f5fe style C fill:#e8f5e8 style D fill:#fff3e0

容器 vs 进程

  • 容器:拥有独立的文件系统、网络、进程空间
  • 进程:共享宿主机的系统资源
  • 隔离性:容器提供更强的隔离和安全性
  • 可移植性:容器可以在任何支持 Docker 的环境运行

Docker 架构

Docker 采用客户端-服务器架构,包含多个核心组件:

graph TB subgraph "客户端" A["Docker CLI"] B["Docker Compose"] C["Docker Desktop"] end subgraph "Docker Engine" D["Docker Daemon"] E["containerd"] F["runc"] end subgraph "存储" G["镜像存储"] H["容器存储"] I["数据卷"] end subgraph "网络" J["Bridge 网络"] K["Host 网络"] L["Overlay 网络"] end A --> D B --> D C --> D D --> E E --> F D --> G D --> H D --> I D --> J D --> K D --> L style D fill:#e1f5fe style E fill:#e8f5e8 style F fill:#fff3e0

架构组件说明

  1. Docker Client

    • 用户与 Docker 交互的主要方式
    • 通过 REST API 与 Docker Daemon 通信
    • 支持本地和远程连接
  2. Docker Daemon

    • Docker 的核心服务进程
    • 管理镜像、容器、网络、存储
    • 监听 Docker API 请求
  3. containerd

    • 容器运行时管理器
    • 负责容器生命周期管理
    • 镜像管理和存储
  4. runc

    • 底层容器运行时
    • 基于 OCI 标准
    • 实际创建和运行容器

与虚拟机对比

Docker 容器 vs 传统虚拟机

对比维度Docker 容器传统虚拟机
启动时间秒级分钟级
资源占用MB级别GB级别
性能开销接近原生10-20% 损耗
隔离级别进程级隔离硬件级隔离
可移植性跨平台平台相关
管理复杂度简单复杂
安全性较好更好

技术实现对比

graph TB subgraph "传统虚拟机架构" A1["应用A"] A2["应用B"] A3["应用C"] B1["Guest OS"] B2["Guest OS"] B3["Guest OS"] C["Hypervisor"] D["Host OS"] E["物理硬件"] end subgraph "Docker 容器架构" F1["应用A"] F2["应用B"] F3["应用C"] G["Docker Engine"] H["Host OS"] I["物理硬件"] end A1 --> B1 A2 --> B2 A3 --> B3 B1 --> C B2 --> C B3 --> C C --> D D --> E F1 --> G F2 --> G F3 --> G G --> H H --> I style C fill:#ffebee style G fill:#e8f5e8

使用场景选择

  • 选择 Docker 容器

    • 微服务架构
    • 快速部署和扩缩容
    • CI/CD 流水线
    • 开发环境标准化
  • 选择虚拟机

    • 需要完全隔离的环境
    • 运行不同操作系统
    • 传统单体应用
    • 高安全要求场景

Docker 安装与配置

系统要求

支持的操作系统

操作系统版本要求架构支持特殊说明
Ubuntu18.04+x86_64, arm64推荐 LTS 版本
CentOS7+x86_64, arm64需要 kernel 3.10+
RHEL7+x86_64, arm64企业级支持
Debian9+x86_64, arm64稳定性好
macOS10.14+Intel, Apple SiliconDocker DesktopColima + Docker CLI(见 macOS:Colima
Windows10/11x86_64WSL2 或 Hyper-V

硬件要求

  • CPU:64位处理器,支持虚拟化
  • 内存:最小 2GB,推荐 4GB+
  • 存储:至少 10GB 可用空间
  • 网络:互联网连接(下载镜像)

安装方式

Linux 系统安装

# Ubuntu/Debian 安装
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# 或者使用官方仓库
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg lsb-release
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
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
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

# CentOS/RHEL 安装
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
sudo yum install docker-ce docker-ce-cli containerd.io
sudo systemctl start docker
sudo systemctl enable docker

macOS 安装

# 方式 A:Docker Desktop(带 GUI,官方集成环境)
brew install --cask docker
# 或下载安装包:https://www.docker.com/products/docker-desktop

# 方式 B:Colima + Docker CLI / Compose(无 Desktop,引擎跑在 Lima 虚拟机内)
brew install colima docker docker-compose
# 详细用法、Apple Silicon 跑 amd64 镜像、与 Desktop 并存等见下文「macOS:Colima」

Windows 安装

# 使用 Chocolatey
choco install docker-desktop

# 或使用 winget
winget install Docker.DockerDesktop

安装验证

# 检查 Docker 版本
docker --version
docker version

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

# 查看系统信息
docker system info

macOS:Colima

Colima 基于 Lima,在 macOS 上提供 Linux 虚拟机 + 容器运行时,与 Docker CLI / Docker Compose 配合使用,无需安装 Docker Desktop 即可在本机构建与运行容器。CLI 通过 docker context 指向 Colima 内的 Docker daemon。

适用场景

  • 希望 命令行驱动、资源占用相对可控,或 不依赖 Docker Desktop 许可/分发
  • Apple Silicon(arm64) 上需要稳定运行 仅提供 linux/amd64 清单的镜像:用 Colima --arch x86_64 启动虚拟机,在 x86_64 Linux 内跑 Docker,避免在 arm64 宿主机上对单容器做 QEMU 用户态模拟带来的 不稳定或 SIGSEGV(如部分分析型数据库镜像)。完整实践与排障(含 Doris Compose、镜像 save/load、JVM 堆与内存)可参考同工作区外文档:data-warehouse/docs/202604131800-mac-Colima-Doris本地安装总结.md

安装(Homebrew)

brew install colima docker docker-compose
# Colima x86_64 虚拟机若报 guest agent 缺失,可安装并链接(见下节)
brew install lima-additional-guestagents

Lima Guest Agent(arch: x86_64 常见前置)

启动若出现类似 guest agent binary could not be found for Linux-x86_64

  • 原因lima-additional-guestagents 提供的 lima-guestagent.Linux-x86_64.gz不会自动合并进 Lima 的 share/lima
  • 处理:将 $(brew --prefix lima-additional-guestagents)/share/lima/lima-guestagent.* 符号链接$(brew --prefix lima)/share/lima/(或维护可重复执行的脚本;brew upgrade lima若复发可再执行一次)。

创建 / 切换 Colima

# 按需清理旧实例后重建(修改 arch 必须 delete 后重建)
colima delete -f
colima start --arch x86_64 --cpu 4 --memory 8 --disk 60   # 资源按机器调整;Apple Silicon 跑 amd64 镜像用 x86_64
# 默认 aarch64 虚拟机(多数 arm64/多架构镜像足够):
# colima start --cpu 4 --memory 4 --disk 60

docker context use colima
docker info | grep -i Architecture   # x86_64 或 aarch64,应与目标镜像架构策略一致

注意--arch 在 VM 创建后不可改;要从 aarch64 换成 x86_64(或反之)需 colima deletecolima start 重新创建。跑 JVM 堆较大 的多个容器时,VM 内存 需大于各进程堆与系统开销之和,否则易出现 Not enough space(errno 12)

与 Docker Desktop 并存

  • 镜像与数据在 各 context 的 daemon隔离;同一时间建议 docker context use 只指向一个(如 colimadesktop-linux,以 docker context ls 为准)。
  • 已在 Desktop 拉取的镜像要迁到 Colima:docker save / docker load 跨 context,不要对另一 context 做无意义 push 指望「同步」。
docker --context desktop-linux save my/image:tag -o /tmp/image.tar
docker --context colima load -i /tmp/image.tar

配置:~/.colima/default/colima.yaml

可配置 Docker Hub 镜像加速代理 等;修改后通常需 colima restart

docker pull / compose pullEOFfailed to do request(访问 registry-1.docker.io 或 CDN)时

  1. 配置 docker.registry-mirrors(多填几个备用;具体地址以你网络环境可用为准)。
  2. 若宿主机 HTTP(S) 代理 被注入 Colima VM,代理不稳定时大层拉取易失败;可尝试在配置中 清空或改为 VM 可达的代理,或换网络/云厂商个人加速地址。
  3. 仍失败时:换网络缩小并发拉取,或优先在稳定环境 docker pullsave 到本机再 load

示例片段(仅作结构示意,镜像站域名请自行替换为当前可用):

docker:
  registry-mirrors:
    - https://docker.1ms.run
    - https://docker.m.daocloud.io
# 若需临时去掉代理(示例):
# env:
#   HTTP_PROXY: ""
#   HTTPS_PROXY: ""

常用命令

命令说明
colima start / stop / status启停、查看状态
colima restartcolima.yaml 后重启 VM
colima ssh进入虚拟机 Shell(排障)
docker context use colimaCLI 指向 Colima

参考Colima · lima-additional-guestagents · Docker daemon registry-mirrors

配置优化

Docker Daemon 配置

# /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com"
  ],
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "data-root": "/var/lib/docker",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true,
  "userland-proxy": false,
  "experimental": false,
  "debug": false
}

用户权限配置

# 将用户添加到 docker 组
sudo usermod -aG docker $USER

# 重新登录或执行
newgrp docker

# 验证权限
docker run hello-world

系统服务配置

# 启动 Docker 服务
sudo systemctl start docker

# 设置开机自启
sudo systemctl enable docker

# 查看服务状态
sudo systemctl status docker

# 重启 Docker 服务
sudo systemctl restart docker

镜像加速

国内镜像源配置

镜像源地址特点
阿里云https://xxx.mirror.aliyuncs.com需要注册获取专属地址
腾讯云https://mirror.ccs.tencentyun.com免费使用
网易https://hub-mirror.c.163.com稳定可靠
中科大https://docker.mirrors.ustc.edu.cn教育网友好
Docker 中国https://registry.docker-cn.com官方中国镜像

配置镜像加速器

# 方法1:修改 daemon.json
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": [
    "https://docker.mirrors.ustc.edu.cn",
    "https://hub-mirror.c.163.com",
    "https://registry.docker-cn.com"
  ]
}
EOF

# 重启 Docker 服务
sudo systemctl daemon-reload
sudo systemctl restart docker

# 验证配置
docker info | grep -A 10 "Registry Mirrors"

阿里云镜像加速器

# 1. 登录阿里云容器镜像服务
# 2. 获取专属加速器地址
# 3. 配置加速器
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://your-id.mirror.aliyuncs.com"]
}
EOF

sudo systemctl daemon-reload
sudo systemctl restart docker

测试加速效果

# 清理本地镜像
docker rmi nginx:latest

# 测试拉取速度
time docker pull nginx:latest

# 查看镜像信息
docker images nginx

Docker 镜像管理

镜像基础

镜像的本质

  • 分层文件系统:基于 Union FS 技术
  • 只读模板:用于创建容器的静态模板
  • 版本控制:支持标签和版本管理
  • 共享存储:相同层可以被多个镜像共享

镜像分层结构

graph TB subgraph "镜像分层示例" A["应用层
nginx:latest"] B["运行时层
ubuntu:20.04"] C["基础层
scratch"] end subgraph "容器运行时" D["可写层
Container Layer"] E["镜像层
Read-Only Layers"] end A --> B B --> C D --> E E --> A style A fill:#e1f5fe style B fill:#e8f5e8 style C fill:#fff3e0 style D fill:#ffebee

镜像命名规范

[registry]/[namespace]/[repository]:[tag]

示例:
docker.io/library/nginx:1.21.6
registry.cn-hangzhou.aliyuncs.com/my-namespace/my-app:v1.0.0

镜像操作

基础镜像操作

# 搜索镜像
docker search nginx
docker search --limit 5 --filter stars=100 nginx

# 拉取镜像
docker pull nginx
docker pull nginx:1.21.6
docker pull ubuntu:20.04

# 查看镜像
docker images
docker images nginx
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"

# 查看镜像详细信息
docker inspect nginx:latest
docker history nginx:latest

# 删除镜像
docker rmi nginx:latest
docker rmi $(docker images -q)  # 删除所有镜像
docker image prune  # 删除悬空镜像

镜像标签管理

# 给镜像打标签
docker tag nginx:latest my-nginx:v1.0
docker tag nginx:latest localhost:5000/nginx:latest

# 重命名镜像
docker tag old-name:tag new-name:tag
docker rmi old-name:tag

# 查看镜像标签
docker images --format "table {{.Repository}}:{{.Tag}}\t{{.Size}}"

镜像导入导出

# 导出镜像
docker save nginx:latest > nginx.tar
docker save -o nginx.tar nginx:latest
docker save nginx:latest | gzip > nginx.tar.gz

# 导入镜像
docker load < nginx.tar
docker load -i nginx.tar

# 容器导出导入
docker export container_name > container.tar
docker import container.tar new-image:tag

Dockerfile 编写

Dockerfile 基础语法

# 基础镜像
FROM ubuntu:20.04

# 维护者信息
LABEL maintainer="[email protected]"
LABEL version="1.0"
LABEL description="My application"

# 设置环境变量
ENV APP_HOME=/app
ENV PATH=$PATH:$APP_HOME/bin

# 设置工作目录
WORKDIR $APP_HOME

# 复制文件
COPY . .
ADD https://example.com/file.tar.gz /tmp/

# 安装软件包
RUN apt-get update && \
    apt-get install -y nginx && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 暴露端口
EXPOSE 80 443

# 创建数据卷
VOLUME ["/data", "/logs"]

# 设置用户
USER nginx

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/ || exit 1

# 启动命令
CMD ["nginx", "-g", "daemon off;"]

Dockerfile 指令详解

指令作用示例注意事项
FROM指定基础镜像FROM ubuntu:20.04必须是第一条指令
RUN执行命令RUN apt-get update每个RUN会创建新层
COPY复制文件COPY . /app只能复制本地文件
ADD添加文件ADD file.tar.gz /tmp支持URL和自动解压
WORKDIR设置工作目录WORKDIR /app影响后续指令
ENV设置环境变量ENV PATH=/usr/bin容器运行时可用
EXPOSE声明端口EXPOSE 80仅声明,不自动映射
CMD默认命令CMD ["nginx"]可被覆盖
ENTRYPOINT入口点ENTRYPOINT ["./app"]不可被覆盖

多阶段构建

# 构建阶段
FROM golang:1.19 AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .

# 运行阶段
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/main .
CMD ["./main"]

镜像优化

镜像大小优化策略

  1. 选择合适的基础镜像
# 不推荐:使用完整 Ubuntu
FROM ubuntu:20.04  # ~72MB

# 推荐:使用 Alpine
FROM alpine:3.16   # ~5MB

# 更推荐:使用 distroless
FROM gcr.io/distroless/static  # ~2MB
  1. 合并 RUN 指令
# 不推荐:多个 RUN 指令
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get clean

# 推荐:合并为一个 RUN 指令
RUN apt-get update && \
    apt-get install -y nginx && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*
  1. 使用 .dockerignore
# .dockerignore 文件
.git
.gitignore
README.md
Dockerfile
.dockerignore
node_modules
npm-debug.log
coverage/
.nyc_output
  1. 清理缓存和临时文件
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        nginx \
        curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

安全优化

# 创建非 root 用户
RUN groupadd -r appuser && useradd -r -g appuser appuser

# 设置文件权限
COPY --chown=appuser:appuser . /app

# 切换到非 root 用户
USER appuser

# 只暴露必要端口
EXPOSE 8080

# 使用 HEALTHCHECK
HEALTHCHECK --interval=30s --timeout=3s \
    CMD curl -f http://localhost:8080/health || exit 1

构建优化技巧

# 使用构建缓存
docker build --cache-from my-app:latest -t my-app:new .

# 并行构建
docker build --build-arg BUILDKIT_INLINE_CACHE=1 .

# 指定构建上下文
docker build -f Dockerfile.prod .

# 使用 BuildKit
export DOCKER_BUILDKIT=1
docker build .

Docker 容器管理

容器生命周期

容器状态转换

graph TB A["Created
已创建"] --> B["Running
运行中"] B --> C["Paused
暂停"] C --> B B --> D["Stopped
已停止"] D --> B B --> E["Exited
已退出"] E --> B A --> F["Dead
死亡"] D --> F E --> F style B fill:#e8f5e8 style D fill:#fff3e0 style E fill:#ffebee style F fill:#f3e5f5

生命周期管理命令

状态命令说明
创建docker create创建容器但不启动
启动docker start启动已创建的容器
运行docker run创建并启动容器
暂停docker pause暂停容器进程
恢复docker unpause恢复暂停的容器
停止docker stop优雅停止容器
强杀docker kill强制终止容器
重启docker restart重启容器
删除docker rm删除容器

容器操作

基础容器操作

# 运行容器
docker run nginx
docker run -d nginx  # 后台运行
docker run -it ubuntu bash  # 交互式运行
docker run --name my-nginx nginx  # 指定容器名称

# 查看容器
docker ps  # 查看运行中的容器
docker ps -a  # 查看所有容器
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# 容器操作
docker start container_name
docker stop container_name
docker restart container_name
docker pause container_name
docker unpause container_name

# 删除容器
docker rm container_name
docker rm -f container_name  # 强制删除运行中的容器
docker container prune  # 删除所有停止的容器

容器交互

# 进入容器
docker exec -it container_name bash
docker exec -it container_name sh
docker exec container_name ls /app

# 查看容器日志
docker logs container_name
docker logs -f container_name  # 实时查看
docker logs --tail 100 container_name  # 查看最后100行
docker logs --since "2023-01-01" container_name

# 查看容器信息
docker inspect container_name
docker stats container_name  # 查看资源使用情况
docker top container_name  # 查看容器进程

端口映射

# 端口映射
docker run -p 8080:80 nginx  # 映射到宿主机8080端口
docker run -p 127.0.0.1:8080:80 nginx  # 绑定到特定IP
docker run -P nginx  # 随机映射所有暴露端口

# 查看端口映射
docker port container_name

数据卷管理

数据卷类型

类型特点使用场景示例
匿名卷系统自动管理临时数据存储docker run -v /data nginx
具名卷用户命名管理持久化数据docker run -v mydata:/data nginx
绑定挂载挂载宿主机目录开发调试docker run -v /host/path:/container/path nginx
tmpfs 挂载内存文件系统临时敏感数据docker run --tmpfs /tmp nginx

数据卷操作

# 创建数据卷
docker volume create mydata
docker volume create --driver local mydata

# 查看数据卷
docker volume ls
docker volume inspect mydata

# 使用数据卷
docker run -v mydata:/data nginx
docker run --mount source=mydata,target=/data nginx

# 绑定挂载
docker run -v /host/data:/container/data nginx
docker run --mount type=bind,source=/host/data,target=/container/data nginx

# 只读挂载
docker run -v /host/data:/container/data:ro nginx

# 删除数据卷
docker volume rm mydata
docker volume prune  # 删除未使用的数据卷

数据卷最佳实践

# 备份数据卷
docker run --rm -v mydata:/data -v $(pwd):/backup ubuntu tar czf /backup/backup.tar.gz -C /data .

# 恢复数据卷
docker run --rm -v mydata:/data -v $(pwd):/backup ubuntu tar xzf /backup/backup.tar.gz -C /data

# 数据卷迁移
docker run --rm -v old_volume:/from -v new_volume:/to alpine sh -c "cd /from && cp -av . /to"

网络配置

Docker 网络模式

graph TB subgraph "Bridge 网络" A["容器A
172.17.0.2"] B["容器B
172.17.0.3"] C["Docker Bridge
docker0"] end subgraph "Host 网络" D["容器C
使用宿主机网络"] end subgraph "None 网络" E["容器D
无网络接口"] end A --> C B --> C C --> F["宿主机
eth0"] D --> F style C fill:#e1f5fe style F fill:#e8f5e8

网络模式对比

网络模式特点性能隔离性使用场景
bridge默认模式,NAT网络中等一般应用
host使用宿主机网络最佳高性能应用
none无网络接口最好安全要求高
container共享其他容器网络中等容器间通信
自定义用户自定义网络微服务架构

网络操作命令

# 查看网络
docker network ls
docker network inspect bridge

# 创建自定义网络
docker network create mynetwork
docker network create --driver bridge --subnet=172.20.0.0/16 mynetwork

# 容器连接网络
docker run --network mynetwork nginx
docker network connect mynetwork container_name
docker network disconnect mynetwork container_name

# 删除网络
docker network rm mynetwork
docker network prune  # 删除未使用的网络

容器间通信

# 使用容器名通信(自定义网络)
docker network create app-network
docker run -d --name db --network app-network mysql
docker run -d --name web --network app-network nginx

# 在 web 容器中可以通过 'db' 访问数据库容器

# 使用 link(已废弃,不推荐)
docker run --link db:database nginx

网络故障排查

# 查看容器网络配置
docker exec container_name ip addr
docker exec container_name netstat -tlnp

# 测试网络连通性
docker exec container_name ping google.com
docker exec container_name telnet db 3306

# 查看网络详细信息
docker network inspect bridge
docker inspect container_name | grep -i network

Docker Compose

Compose 概述

Docker Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 YAML 文件配置应用服务,然后使用单个命令创建并启动所有服务。

核心优势

  • 简化部署:一个命令启动整个应用栈
  • 环境一致性:开发、测试、生产环境配置统一
  • 服务编排:自动处理服务依赖关系
  • 网络管理:自动创建服务间网络

Compose 工作流程

graph TB A["编写 docker-compose.yml"] --> B["定义服务配置"] B --> C["docker-compose up"] C --> D["创建网络"] D --> E["创建数据卷"] E --> F["启动服务"] F --> G["服务间通信"] style C fill:#e1f5fe style F fill:#e8f5e8

安装 Docker Compose

# Linux 安装
sudo curl -L "https://github.com/docker/compose/releases/download/v2.12.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose

# 或使用 pip 安装
pip install docker-compose

# 验证安装
docker-compose --version

编排文件

docker-compose.yml 基础结构

version: '3.8'

services:
  web:
    build: .
    ports:
      - "8000:8000"
    volumes:
      - .:/app
    environment:
      - DEBUG=1
    depends_on:
      - db
      - redis
    networks:
      - app-network

  db:
    image: postgres:13
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD: password
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - app-network

  redis:
    image: redis:6-alpine
    networks:
      - app-network

volumes:
  postgres_data:

networks:
  app-network:
    driver: bridge

Compose 文件版本对比

版本Docker Engine特性
3.819.03.0+最新特性支持
3.718.06.0+外部网络支持
3.618.02.0+tmpfs 支持
3.517.12.0+隔离模式支持
3.417.09.0+平台指定支持

服务配置详解

services:
  app:
    # 镜像配置
    image: nginx:latest
    # 或构建配置
    build:
      context: .
      dockerfile: Dockerfile.prod
      args:
        - BUILD_ENV=production
    
    # 容器名称
    container_name: my-app
    
    # 重启策略
    restart: unless-stopped
    
    # 端口映射
    ports:
      - "80:80"
      - "443:443"
    
    # 环境变量
    environment:
      - NODE_ENV=production
      - API_URL=http://api:3000
    env_file:
      - .env
    
    # 数据卷
    volumes:
      - ./app:/usr/share/nginx/html:ro
      - nginx_logs:/var/log/nginx
    
    # 网络配置
    networks:
      - frontend
      - backend
    
    # 依赖关系
    depends_on:
      - api
      - db
    
    # 健康检查
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    
    # 资源限制
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 512M
        reservations:
          cpus: '0.25'
          memory: 256M

服务管理

基础 Compose 命令

# 启动服务
docker-compose up
docker-compose up -d  # 后台运行
docker-compose up --build  # 重新构建镜像

# 停止服务
docker-compose down
docker-compose down -v  # 同时删除数据卷
docker-compose down --rmi all  # 同时删除镜像

# 查看服务状态
docker-compose ps
docker-compose top
docker-compose logs
docker-compose logs -f web  # 实时查看特定服务日志

# 服务操作
docker-compose start
docker-compose stop
docker-compose restart
docker-compose pause
docker-compose unpause

# 扩缩容
docker-compose up --scale web=3
docker-compose up --scale web=3 --scale worker=2

服务管理命令

# 执行命令
docker-compose exec web bash
docker-compose exec db psql -U user myapp

# 运行一次性命令
docker-compose run web python manage.py migrate
docker-compose run --rm web npm test

# 查看配置
docker-compose config
docker-compose config --services
docker-compose config --volumes

# 拉取镜像
docker-compose pull
docker-compose pull web

# 构建镜像
docker-compose build
docker-compose build --no-cache web

实战案例

LNMP 架构示例

# docker-compose.yml
version: '3.8'

services:
  nginx:
    image: nginx:alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - ./www:/var/www/html:ro
      - ./nginx/logs:/var/log/nginx
    depends_on:
      - php
    networks:
      - lnmp-network

  php:
    build:
      context: ./php
      dockerfile: Dockerfile
    volumes:
      - ./www:/var/www/html
      - ./php/conf.d:/usr/local/etc/php/conf.d:ro
    depends_on:
      - mysql
      - redis
    networks:
      - lnmp-network

  mysql:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: myapp
      MYSQL_USER: appuser
      MYSQL_PASSWORD: apppassword
    volumes:
      - mysql_data:/var/lib/mysql
      - ./mysql/conf.d:/etc/mysql/conf.d:ro
      - ./mysql/init:/docker-entrypoint-initdb.d:ro
    ports:
      - "3306:3306"
    networks:
      - lnmp-network

  redis:
    image: redis:6-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    ports:
      - "6379:6379"
    networks:
      - lnmp-network

volumes:
  mysql_data:
  redis_data:

networks:
  lnmp-network:
    driver: bridge

微服务架构示例

version: '3.8'

services:
  # API 网关
  gateway:
    image: nginx:alpine
    ports:
      - "80:80"
    volumes:
      - ./gateway/nginx.conf:/etc/nginx/nginx.conf:ro
    depends_on:
      - user-service
      - order-service
    networks:
      - microservices

  # 用户服务
  user-service:
    build: ./user-service
    environment:
      - DATABASE_URL=postgresql://user:pass@postgres:5432/users
      - REDIS_URL=redis://redis:6379
    depends_on:
      - postgres
      - redis
    networks:
      - microservices
    deploy:
      replicas: 2

  # 订单服务
  order-service:
    build: ./order-service
    environment:
      - DATABASE_URL=postgresql://user:pass@postgres:5432/orders
      - USER_SERVICE_URL=http://user-service:8080
    depends_on:
      - postgres
    networks:
      - microservices

  # 数据库
  postgres:
    image: postgres:13
    environment:
      POSTGRES_DB: microservices
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - microservices

  # 缓存
  redis:
    image: redis:6-alpine
    networks:
      - microservices

  # 监控
  prometheus:
    image: prom/prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
    networks:
      - microservices

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana_data:/var/lib/grafana
    networks:
      - microservices

volumes:
  postgres_data:
  grafana_data:

networks:
  microservices:
    driver: bridge

开发环境配置

# docker-compose.dev.yml
version: '3.8'

services:
  app:
    build:
      context: .
      target: development
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
      - DEBUG=*
    ports:
      - "3000:3000"
      - "9229:9229"  # Node.js 调试端口
    command: npm run dev

  db:
    image: postgres:13
    environment:
      POSTGRES_DB: myapp_dev
      POSTGRES_USER: dev
      POSTGRES_PASSWORD: dev
    ports:
      - "5432:5432"
    volumes:
      - postgres_dev_data:/var/lib/postgresql/data

volumes:
  postgres_dev_data:

多环境管理

# 使用不同的 compose 文件
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up

# 使用环境变量文件
docker-compose --env-file .env.dev up

# 项目名称管理
docker-compose -p myapp-dev up
docker-compose -p myapp-prod up

Docker 网络

网络模式

Docker 网络驱动类型

驱动类型作用域特点使用场景
bridge单主机默认网络,NAT模式单机容器通信
host单主机使用宿主机网络栈高性能网络应用
overlay多主机跨主机容器通信Docker Swarm 集群
macvlan单主机容器拥有独立MAC地址需要直接网络访问
none单主机禁用网络高安全要求
ipvlan单主机共享MAC地址网络虚拟化

网络模式详细对比

graph TB subgraph "Bridge 网络模式" A1["容器A
172.17.0.2"] A2["容器B
172.17.0.3"] A3["Docker Bridge
docker0"] A4["iptables NAT"] A5["宿主机网卡"] end subgraph "Host 网络模式" B1["容器C"] B2["宿主机网络栈"] end subgraph "Overlay 网络模式" C1["主机1容器"] C2["主机2容器"] C3["VXLAN隧道"] end A1 --> A3 A2 --> A3 A3 --> A4 A4 --> A5 B1 --> B2 C1 --> C3 C3 --> C2 style A3 fill:#e1f5fe style B2 fill:#e8f5e8 style C3 fill:#fff3e0

Bridge 网络详解

# 查看默认 bridge 网络
docker network inspect bridge

# 创建自定义 bridge 网络
docker network create --driver bridge my-bridge
docker network create --driver bridge --subnet=172.20.0.0/16 --gateway=172.20.0.1 my-bridge

# 指定 IP 地址
docker run --network my-bridge --ip 172.20.0.10 nginx

# 网络别名
docker run --network my-bridge --network-alias web nginx

Host 网络使用

# 使用 host 网络
docker run --network host nginx

# 查看网络配置
docker run --network host alpine ip addr show

自定义网络

创建和管理自定义网络

# 创建 bridge 网络
docker network create \
  --driver bridge \
  --subnet=172.30.0.0/16 \
  --ip-range=172.30.240.0/20 \
  --gateway=172.30.0.1 \
  --opt com.docker.network.bridge.name=my-bridge \
  --opt com.docker.network.mtu=1500 \
  my-network

# 创建 macvlan 网络
docker network create \
  --driver macvlan \
  --subnet=192.168.1.0/24 \
  --gateway=192.168.1.1 \
  --opt parent=eth0 \
  macvlan-net

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

# 连接容器到网络
docker network connect my-network container_name
docker network connect --ip 172.30.0.100 my-network container_name

# 断开网络连接
docker network disconnect my-network container_name

网络配置示例

# docker-compose.yml 网络配置
version: '3.8'

services:
  web:
    image: nginx
    networks:
      - frontend
      - backend

  api:
    image: node:alpine
    networks:
      backend:
        ipv4_address: 172.20.0.10

  db:
    image: postgres
    networks:
      - backend

networks:
  frontend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.19.0.0/16
  
  backend:
    driver: bridge
    ipam:
      config:
        - subnet: 172.20.0.0/16
          gateway: 172.20.0.1

  external-net:
    external: true
    name: existing-network

跨主机网络

Docker Swarm Overlay 网络

# 初始化 Swarm 集群
docker swarm init --advertise-addr 192.168.1.100

# 加入 Swarm 集群
docker swarm join --token SWMTKN-xxx 192.168.1.100:2377

# 创建 overlay 网络
docker network create --driver overlay --attachable my-overlay

# 在 overlay 网络中运行容器
docker run -d --network my-overlay --name web1 nginx
docker run -d --network my-overlay --name web2 nginx

# 跨主机容器通信测试
docker exec web1 ping web2

第三方网络解决方案

方案特点适用场景
Flannel简单易用,性能一般小规模集群
Calico高性能,支持网络策略大规模生产环境
Weave功能丰富,自动发现混合云环境
Cilium基于 eBPF,高性能现代化容器平台

网络故障排查

常见网络问题

  1. 容器无法访问外网
# 检查 DNS 配置
docker exec container_name nslookup google.com

# 检查路由表
docker exec container_name ip route

# 检查 iptables 规则
sudo iptables -t nat -L
  1. 容器间无法通信
# 检查网络连接
docker network ls
docker network inspect network_name

# 测试连通性
docker exec container1 ping container2
docker exec container1 telnet container2 80

# 检查端口监听
docker exec container_name netstat -tlnp
  1. 端口映射问题
# 检查端口映射
docker port container_name

# 检查宿主机端口占用
netstat -tlnp | grep :8080

# 检查防火墙规则
sudo ufw status
sudo firewall-cmd --list-all

网络诊断工具

# 安装网络工具
docker run --rm --network container:target_container nicolaka/netshoot

# 使用 tcpdump 抓包
docker exec container_name tcpdump -i eth0 -w /tmp/capture.pcap

# 使用 ss 查看连接
docker exec container_name ss -tlnp

# 查看网络统计
docker exec container_name cat /proc/net/dev

网络性能测试

# 使用 iperf3 测试网络性能
# 服务端
docker run -d --name iperf3-server --network my-network iperf3 -s

# 客户端
docker run --rm --network my-network iperf3 -c iperf3-server

# 使用 ping 测试延迟
docker exec container1 ping -c 10 container2

# 使用 curl 测试 HTTP 性能
docker exec container_name curl -w "@curl-format.txt" -o /dev/null -s http://target/

网络监控

# 实时监控网络流量
docker exec container_name iftop -i eth0

# 监控网络连接
docker exec container_name watch -n 1 'ss -tuln'

# 使用 Prometheus 监控
# 在 docker-compose.yml 中添加 cAdvisor
cadvisor:
  image: gcr.io/cadvisor/cadvisor:latest
  ports:
    - "8080:8080"
  volumes:
    - /:/rootfs:ro
    - /var/run:/var/run:ro
    - /sys:/sys:ro
    - /var/lib/docker/:/var/lib/docker:ro

网络安全配置

# 创建隔离网络
docker network create --internal isolated-network

# 使用网络策略(需要支持的网络插件)
# 示例:Calico 网络策略
apiVersion: projectcalico.org/v3
kind: NetworkPolicy
metadata:
  name: deny-all
spec:
  selector: all()
  types:
  - Ingress
  - Egress

# 限制容器网络访问
docker run --cap-drop NET_ADMIN --cap-drop NET_RAW nginx

Docker 存储

存储驱动

Docker 存储驱动类型

存储驱动特点性能适用系统推荐场景
overlay2现代化,功能完整Linux 4.0+生产环境推荐
aufs成熟稳定Ubuntu/Debian旧版本系统
devicemapper企业级特性RHEL/CentOS企业环境
btrfs写时复制,快照支持 Btrfs 的系统需要高级特性
zfs企业级,数据完整性支持 ZFS 的系统数据安全要求高
vfs无联合文件系统所有系统调试和测试

存储驱动架构

graph TB subgraph "容器层次结构" A["容器可写层
Container Layer"] B["镜像层 N
Image Layer N"] C["镜像层 2
Image Layer 2"] D["镜像层 1
Image Layer 1"] E["基础层
Base Layer"] end subgraph "存储驱动" F["overlay2"] G["联合文件系统
Union FS"] H["宿主机文件系统
Host FS"] end A --> B B --> C C --> D D --> E A --> F F --> G G --> H style A fill:#ffebee style F fill:#e1f5fe style H fill:#e8f5e8

查看和配置存储驱动

# 查看当前存储驱动
docker info | grep "Storage Driver"

# 查看存储详细信息
docker system df
docker system df -v

# 配置存储驱动(daemon.json)
{
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}

# 查看镜像层信息
docker history nginx:latest
docker inspect nginx:latest

数据持久化

数据持久化方案对比

graph TB subgraph "数据卷 (Volumes)" A["Docker 管理"] B["独立于容器生命周期"] C["可在容器间共享"] end subgraph "绑定挂载 (Bind Mounts)" D["宿主机路径"] E["直接访问宿主机文件"] F["开发调试友好"] end subgraph "tmpfs 挂载" G["内存存储"] H["临时数据"] I["高性能读写"] end style A fill:#e1f5fe style D fill:#e8f5e8 style G fill:#fff3e0

数据卷最佳实践

# 创建命名数据卷
docker volume create --driver local \
  --opt type=nfs \
  --opt o=addr=192.168.1.100,rw \
  --opt device=:/path/to/dir \
  nfs-volume

# 使用本地存储驱动选项
docker volume create --driver local \
  --opt type=btrfs \
  --opt device=/dev/sdb \
  btrfs-volume

# 数据卷标签管理
docker volume create --label environment=production \
  --label backup=daily \
  prod-data

# 查看数据卷使用情况
docker system df -v
docker volume ls --filter dangling=true

高级数据卷配置

# docker-compose.yml 高级数据卷配置
version: '3.8'

services:
  app:
    image: myapp
    volumes:
      # 命名卷
      - app_data:/app/data
      # 绑定挂载(只读)
      - ./config:/app/config:ro
      # tmpfs 挂载
      - type: tmpfs
        target: /app/tmp
        tmpfs:
          size: 100M
      # 数据卷配置
      - type: volume
        source: app_logs
        target: /app/logs
        volume:
          nocopy: true

volumes:
  app_data:
    driver: local
    driver_opts:
      type: nfs
      o: addr=nfs-server,rw
      device: ":/exports/app_data"
  
  app_logs:
    driver: local
    driver_opts:
      type: btrfs
      device: /dev/sdb1

存储优化

镜像层优化

# 优化前:多个 RUN 指令创建多层
FROM ubuntu:20.04
RUN apt-get update
RUN apt-get install -y nginx
RUN apt-get install -y curl
RUN apt-get clean

# 优化后:合并 RUN 指令
FROM ubuntu:20.04
RUN apt-get update && \
    apt-get install -y nginx curl && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 使用多阶段构建减少最终镜像大小
FROM golang:1.19 AS builder
WORKDIR /app
COPY . .
RUN go build -o main .

FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/main .
CMD ["./main"]

存储空间管理

# 清理未使用的资源
docker system prune  # 清理停止的容器、未使用的网络、悬空镜像
docker system prune -a  # 清理所有未使用的镜像
docker system prune --volumes  # 同时清理未使用的数据卷

# 分别清理不同类型的资源
docker container prune  # 清理停止的容器
docker image prune  # 清理悬空镜像
docker image prune -a  # 清理未使用的镜像
docker volume prune  # 清理未使用的数据卷
docker network prune  # 清理未使用的网络

# 查看存储使用情况
docker system df
docker system df -v

# 分析镜像大小
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
dive nginx:latest  # 使用 dive 工具分析镜像层

存储性能优化

# 配置存储驱动选项
{
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true",
    "overlay2.size=20G"
  ],
  "data-root": "/var/lib/docker"
}

# 使用 SSD 存储
# 将 Docker 数据目录移动到 SSD
sudo systemctl stop docker
sudo mv /var/lib/docker /ssd/docker
sudo ln -s /ssd/docker /var/lib/docker
sudo systemctl start docker

# 配置日志轮转
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

备份恢复

数据卷备份策略

# 方法1:使用临时容器备份
docker run --rm \
  -v mydata:/data \
  -v $(pwd):/backup \
  ubuntu tar czf /backup/backup-$(date +%Y%m%d).tar.gz -C /data .

# 方法2:直接访问数据卷目录
sudo tar czf backup.tar.gz -C /var/lib/docker/volumes/mydata/_data .

# 方法3:使用专用备份容器
docker run --rm \
  -v mydata:/source:ro \
  -v backup_storage:/backup \
  alpine sh -c "tar czf /backup/data-$(date +%Y%m%d).tar.gz -C /source ."

自动化备份脚本

#!/bin/bash
# docker-backup.sh

BACKUP_DIR="/backup/docker"
DATE=$(date +%Y%m%d_%H%M%S)

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

# 备份所有数据卷
for volume in $(docker volume ls -q); do
    echo "Backing up volume: $volume"
    docker run --rm \
        -v $volume:/data:ro \
        -v $BACKUP_DIR:/backup \
        alpine tar czf /backup/${volume}_${DATE}.tar.gz -C /data .
done

# 清理旧备份(保留7天)
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete

echo "Backup completed: $BACKUP_DIR"

数据恢复

# 恢复数据卷
# 1. 创建新的数据卷
docker volume create mydata_restored

# 2. 恢复数据
docker run --rm \
  -v mydata_restored:/data \
  -v $(pwd):/backup \
  ubuntu tar xzf /backup/backup-20231201.tar.gz -C /data

# 3. 验证恢复的数据
docker run --rm -v mydata_restored:/data alpine ls -la /data

容器状态备份

# 提交容器为镜像
docker commit container_name my-backup:$(date +%Y%m%d)

# 导出容器文件系统
docker export container_name > container-backup.tar

# 导出镜像
docker save my-app:latest > my-app-backup.tar

# 批量备份脚本
#!/bin/bash
BACKUP_DIR="/backup/containers"
mkdir -p $BACKUP_DIR

# 备份运行中的容器
for container in $(docker ps --format "{{.Names}}"); do
    echo "Backing up container: $container"
    docker commit $container ${container}-backup:$(date +%Y%m%d)
    docker save ${container}-backup:$(date +%Y%m%d) > $BACKUP_DIR/${container}-$(date +%Y%m%d).tar
done

灾难恢复计划

# 1. 系统恢复脚本
#!/bin/bash
# disaster-recovery.sh

# 重新安装 Docker
curl -fsSL https://get.docker.com | sh

# 恢复配置文件
cp backup/daemon.json /etc/docker/
systemctl restart docker

# 恢复镜像
for image in backup/*.tar; do
    docker load < $image
done

# 恢复数据卷
for volume_backup in backup/volumes/*.tar.gz; do
    volume_name=$(basename $volume_backup .tar.gz)
    docker volume create $volume_name
    docker run --rm \
        -v $volume_name:/data \
        -v $(pwd)/backup/volumes:/backup \
        alpine tar xzf /backup/$(basename $volume_backup) -C /data
done

# 重启服务
docker-compose up -d

Docker 安全

安全基础

Docker 安全模型

graph TB subgraph "宿主机安全" A["内核安全"] B["文件系统权限"] C["网络安全"] D["用户权限管理"] end subgraph "容器安全" E["命名空间隔离"] F["控制组限制"] G["能力控制"] H["安全计算模式"] end subgraph "镜像安全" I["基础镜像安全"] J["漏洞扫描"] K["签名验证"] L["最小化原则"] end subgraph "运行时安全" M["资源限制"] N["网络隔离"] O["文件系统保护"] P["监控审计"] end A --> E B --> F C --> G D --> H style E fill:#e1f5fe style I fill:#e8f5e8 style M fill:#fff3e0

安全威胁模型

威胁类型风险等级影响范围防护措施
容器逃逸宿主机内核更新、权限控制
镜像漏洞容器内漏洞扫描、及时更新
权限提升系统级最小权限原则
资源耗尽服务可用性资源限制
网络攻击网络通信网络隔离、防火墙
数据泄露敏感数据加密、访问控制

镜像安全

安全镜像构建

# 安全 Dockerfile 示例
FROM alpine:3.16 AS base

# 创建非 root 用户
RUN addgroup -g 1001 -S appgroup && \
    adduser -u 1001 -S appuser -G appgroup

# 安装必要软件包并清理
RUN apk add --no-cache \
    ca-certificates \
    curl && \
    rm -rf /var/cache/apk/*

# 设置工作目录
WORKDIR /app

# 复制应用文件并设置权限
COPY --chown=appuser:appgroup . .

# 切换到非 root 用户
USER appuser

# 健康检查
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

# 使用非 root 端口
EXPOSE 8080

CMD ["./app"]

镜像漏洞扫描

# 使用 Docker Scout 扫描
docker scout cves nginx:latest
docker scout recommendations nginx:latest

# 使用 Trivy 扫描
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL nginx:latest

# 使用 Clair 扫描
clairctl analyze nginx:latest

# 使用 Anchore 扫描
anchore-cli image add nginx:latest
anchore-cli image wait nginx:latest
anchore-cli image vuln nginx:latest all

镜像签名和验证

# 启用 Docker Content Trust
export DOCKER_CONTENT_TRUST=1

# 生成签名密钥
docker trust key generate mykey

# 签名镜像
docker trust sign myregistry.com/myimage:latest

# 验证镜像签名
docker trust inspect myregistry.com/myimage:latest

# 使用 Notary 进行高级签名管理
notary init myregistry.com/myimage
notary publish myregistry.com/myimage

容器安全

容器运行时安全配置

# 限制容器权限
docker run --user 1001:1001 nginx  # 指定用户ID
docker run --read-only nginx  # 只读文件系统
docker run --no-new-privileges nginx  # 禁止权限提升

# 删除危险能力
docker run --cap-drop ALL --cap-add NET_BIND_SERVICE nginx

# 使用安全计算模式
docker run --security-opt seccomp=seccomp-profile.json nginx
docker run --security-opt no-new-privileges nginx

# 限制系统调用
docker run --security-opt seccomp=unconfined nginx  # 不推荐

资源限制配置

# CPU 限制
docker run --cpus="1.5" nginx  # 限制 1.5 个 CPU
docker run --cpu-shares=512 nginx  # 相对权重

# 内存限制
docker run --memory=512m nginx  # 限制内存 512MB
docker run --memory=1g --memory-swap=2g nginx  # 内存+交换空间

# 磁盘 IO 限制
docker run --device-read-bps /dev/sda:1mb nginx
docker run --device-write-bps /dev/sda:1mb nginx

# 进程数限制
docker run --pids-limit=100 nginx

网络安全配置

# 网络隔离
docker run --network none nginx  # 无网络访问
docker run --network isolated-net nginx  # 自定义隔离网络

# 端口限制
docker run -p 127.0.0.1:8080:80 nginx  # 只绑定本地接口

# 使用用户定义网络
docker network create --internal secure-network
docker run --network secure-network nginx

最佳实践

安全配置清单

# docker-compose.yml 安全配置示例
version: '3.8'

services:
  web:
    image: nginx:alpine
    user: "1001:1001"
    read_only: true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - no-new-privileges:true
      - seccomp:seccomp-profile.json
    tmpfs:
      - /tmp
      - /var/cache/nginx
    volumes:
      - ./html:/usr/share/nginx/html:ro
    ports:
      - "127.0.0.1:8080:80"
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
        reservations:
          cpus: '0.25'
          memory: 128M
    healthcheck:
      test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    restart: unless-stopped
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

Seccomp 安全配置文件

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": [
        "accept",
        "accept4",
        "access",
        "bind",
        "brk",
        "close",
        "connect",
        "dup",
        "dup2",
        "execve",
        "exit",
        "exit_group",
        "fstat",
        "getpid",
        "getuid",
        "listen",
        "mmap",
        "open",
        "read",
        "socket",
        "write"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

AppArmor 配置

# 创建 AppArmor 配置文件
# /etc/apparmor.d/docker-nginx
#include <tunables/global>

profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>
  
  network inet tcp,
  network inet udp,
  
  /usr/sbin/nginx ix,
  /etc/nginx/ r,
  /etc/nginx/** r,
  /var/log/nginx/ w,
  /var/log/nginx/** w,
  /usr/share/nginx/html/ r,
  /usr/share/nginx/html/** r,
  
  deny /proc/sys/** w,
  deny /sys/** w,
}

# 加载配置文件
sudo apparmor_parser -r /etc/apparmor.d/docker-nginx

# 使用 AppArmor 配置运行容器
docker run --security-opt apparmor=docker-nginx nginx

安全监控和审计

# 启用 Docker 审计日志
# 在 /etc/audit/rules.d/docker.rules 中添加
-w /usr/bin/docker -p wa -k docker
-w /var/lib/docker -p wa -k docker
-w /etc/docker -p wa -k docker
-w /lib/systemd/system/docker.service -p wa -k docker
-w /etc/systemd/system/docker.service -p wa -k docker

# 重启审计服务
sudo systemctl restart auditd

# 查看审计日志
sudo ausearch -k docker

# 使用 Falco 进行运行时安全监控
# falco_rules.yaml
- rule: Write below binary dir
  desc: an attempt to write to any file below a set of binary directories
  condition: >
    bin_dir and evt.dir = < and open_write
    and not package_mgmt_procs
    and not exe_running_docker_save
    and not python_running_get_pip
    and not python_running_ms_oms
  output: >
    File below a known binary directory opened for writing (user=%user.name
    command=%proc.cmdline file=%fd.name parent=%proc.pname pcmdline=%proc.pcmdline gparent=%proc.aname[2])
  priority: ERROR

容器镜像安全扫描集成

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

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v3
    
    - name: Build Docker image
      run: docker build -t myapp:${{ github.sha }} .
    
    - name: Run Trivy vulnerability scanner
      uses: aquasecurity/trivy-action@master
      with:
        image-ref: 'myapp:${{ github.sha }}'
        format: 'sarif'
        output: 'trivy-results.sarif'
    
    - name: Upload Trivy scan results to GitHub Security tab
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'

Docker 监控与日志

监控方案

Docker 监控架构

graph TB subgraph "数据采集层" A["cAdvisor"] B["Node Exporter"] C["Docker Stats API"] D["容器日志"] end subgraph "数据存储层" E["Prometheus"] F["InfluxDB"] G["Elasticsearch"] end subgraph "可视化层" H["Grafana"] I["Kibana"] J["Docker Desktop"] end subgraph "告警层" K["AlertManager"] L["PagerDuty"] M["Slack/Email"] end A --> E B --> E C --> F D --> G E --> H F --> H G --> I E --> K K --> L K --> M style E fill:#e1f5fe style H fill:#e8f5e8 style K fill:#fff3e0

基础监控指标

指标类别关键指标说明告警阈值
CPUcpu_usage_percentCPU 使用率> 80%
cpu_throttled_secondsCPU 限流时间> 0
内存memory_usage_bytes内存使用量> 90%
memory_oom_killsOOM 杀死次数> 0
网络network_rx_bytes网络接收字节异常增长
network_tx_bytes网络发送字节异常增长
磁盘disk_usage_percent磁盘使用率> 85%
disk_io_bytes磁盘 IO 字节异常增长
容器container_count容器数量异常变化
container_restarts容器重启次数> 5/小时

监控工具配置

Prometheus + Grafana 监控栈

# docker-compose.monitoring.yml
version: '3.8'

services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus/prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus_data:/prometheus
    command:
      - '--config.file=/etc/prometheus/prometheus.yml'
      - '--storage.tsdb.path=/prometheus'
      - '--web.console.libraries=/etc/prometheus/console_libraries'
      - '--web.console.templates=/etc/prometheus/consoles'
      - '--storage.tsdb.retention.time=200h'
      - '--web.enable-lifecycle'
    networks:
      - monitoring

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
      - GF_USERS_ALLOW_SIGN_UP=false
    volumes:
      - grafana_data:/var/lib/grafana
      - ./grafana/provisioning:/etc/grafana/provisioning:ro
    networks:
      - monitoring

  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:ro
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
      - /dev/disk/:/dev/disk:ro
    privileged: true
    devices:
      - /dev/kmsg
    networks:
      - monitoring

  node-exporter:
    image: prom/node-exporter:latest
    ports:
      - "9100:9100"
    volumes:
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /:/rootfs:ro
    command:
      - '--path.procfs=/host/proc'
      - '--path.rootfs=/rootfs'
      - '--path.sysfs=/host/sys'
      - '--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)'
    networks:
      - monitoring

volumes:
  prometheus_data:
  grafana_data:

networks:
  monitoring:
    driver: bridge

Prometheus 配置文件

# prometheus/prometheus.yml
global:
  scrape_interval: 15s
  evaluation_interval: 15s

rule_files:
  - "alert_rules.yml"

alerting:
  alertmanagers:
    - static_configs:
        - targets:
          - alertmanager:9093

scrape_configs:
  - job_name: 'prometheus'
    static_configs:
      - targets: ['localhost:9090']

  - job_name: 'cadvisor'
    static_configs:
      - targets: ['cadvisor:8080']

  - job_name: 'node-exporter'
    static_configs:
      - targets: ['node-exporter:9100']

  - job_name: 'docker'
    static_configs:
      - targets: ['host.docker.internal:9323']
    metrics_path: /metrics

告警规则配置

# prometheus/alert_rules.yml
groups:
- name: docker_alerts
  rules:
  - alert: ContainerDown
    expr: up == 0
    for: 1m
    labels:
      severity: critical
    annotations:
      summary: "Container {{ $labels.instance }} is down"
      description: "Container {{ $labels.instance }} has been down for more than 1 minute."

  - alert: HighCPUUsage
    expr: rate(container_cpu_usage_seconds_total[5m]) * 100 > 80
    for: 5m
    labels:
      severity: warning
    annotations:
      summary: "High CPU usage on {{ $labels.name }}"
      description: "Container {{ $labels.name }} CPU usage is above 80% for more than 5 minutes."

  - alert: HighMemoryUsage
    expr: (container_memory_usage_bytes / container_spec_memory_limit_bytes) * 100 > 90
    for: 5m
    labels:
      severity: critical
    annotations:
      summary: "High memory usage on {{ $labels.name }}"
      description: "Container {{ $labels.name }} memory usage is above 90% for more than 5 minutes."

  - alert: ContainerRestartTooOften
    expr: increase(container_restart_count[1h]) > 5
    for: 0m
    labels:
      severity: warning
    annotations:
      summary: "Container restarting too often"
      description: "Container {{ $labels.name }} has restarted {{ $value }} times in the last hour."

日志管理

Docker 日志驱动

日志驱动特点适用场景配置示例
json-file默认驱动,本地存储开发环境--log-driver json-file
syslog系统日志服务传统环境--log-driver syslog
journaldsystemd 日志systemd 系统--log-driver journald
fluentd结构化日志收集微服务架构--log-driver fluentd
awslogsAWS CloudWatchAWS 环境--log-driver awslogs
splunkSplunk 平台企业环境--log-driver splunk

集中化日志收集架构

# ELK Stack 日志收集
version: '3.8'

services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.17.0
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ports:
      - "9200:9200"
    volumes:
      - elasticsearch_data:/usr/share/elasticsearch/data
    networks:
      - elk

  logstash:
    image: docker.elastic.co/logstash/logstash:7.17.0
    volumes:
      - ./logstash/config:/usr/share/logstash/pipeline:ro
    ports:
      - "5044:5044"
    environment:
      LS_JAVA_OPTS: "-Xmx256m -Xms256m"
    networks:
      - elk
    depends_on:
      - elasticsearch

  kibana:
    image: docker.elastic.co/kibana/kibana:7.17.0
    ports:
      - "5601:5601"
    environment:
      ELASTICSEARCH_HOSTS: http://elasticsearch:9200
    networks:
      - elk
    depends_on:
      - elasticsearch

  filebeat:
    image: docker.elastic.co/beats/filebeat:7.17.0
    user: root
    volumes:
      - ./filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - elk
    depends_on:
      - logstash

volumes:
  elasticsearch_data:

networks:
  elk:
    driver: bridge

Filebeat 配置

# filebeat/filebeat.yml
filebeat.inputs:
- type: container
  paths:
    - '/var/lib/docker/containers/*/*.log'
  processors:
  - add_docker_metadata:
      host: "unix:///var/run/docker.sock"
  - decode_json_fields:
      fields: ["message"]
      target: ""
      overwrite_keys: true

output.logstash:
  hosts: ["logstash:5044"]

logging.level: info
logging.to_files: true
logging.files:
  path: /var/log/filebeat
  name: filebeat
  keepfiles: 7
  permissions: 0644

Fluentd 日志收集

# Fluentd 配置
version: '3.8'

services:
  fluentd:
    build: ./fluentd
    volumes:
      - ./fluentd/conf:/fluentd/etc
    ports:
      - "24224:24224"
      - "24224:24224/udp"
    networks:
      - logging

  app:
    image: nginx
    logging:
      driver: fluentd
      options:
        fluentd-address: localhost:24224
        tag: nginx.access
    networks:
      - logging

networks:
  logging:
    driver: bridge

性能调优

容器性能监控

# 实时监控容器资源使用
docker stats
docker stats --no-stream
docker stats --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"

# 查看容器进程
docker top container_name
docker exec container_name ps aux

# 监控容器网络
docker exec container_name netstat -i
docker exec container_name ss -tuln

# 监控容器磁盘 IO
docker exec container_name iostat -x 1

性能调优参数

# CPU 性能调优
docker run --cpus="2.0" --cpu-shares=1024 nginx

# 内存性能调优
docker run --memory=1g --memory-swap=2g --oom-kill-disable nginx

# 磁盘 IO 调优
docker run --device-read-bps /dev/sda:10mb --device-write-bps /dev/sda:5mb nginx

# 网络性能调优
docker run --network=host nginx  # 使用主机网络获得最佳性能

故障排查

常见问题诊断

# 1. 容器启动失败
docker logs container_name
docker inspect container_name
docker events --filter container=container_name

# 2. 性能问题诊断
docker stats container_name
docker exec container_name top
docker exec container_name free -h
docker exec container_name df -h

# 3. 网络连接问题
docker exec container_name ping google.com
docker exec container_name nslookup google.com
docker exec container_name netstat -tlnp

# 4. 存储问题诊断
docker system df
docker system events
docker volume inspect volume_name

故障排查工具

# 使用 dive 分析镜像
dive nginx:latest

# 使用 ctop 监控容器
ctop

# 使用 docker-compose 调试
docker-compose config
docker-compose logs service_name
docker-compose exec service_name bash

# 使用 portainer 管理界面
docker run -d -p 9000:9000 --name portainer \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v portainer_data:/data \
  portainer/portainer-ce

性能基准测试

# 容器启动时间测试
time docker run --rm alpine echo "Hello World"

# 网络性能测试
docker run --rm -it networkstatic/iperf3 -c iperf.he.net

# 磁盘 IO 性能测试
docker run --rm -v /tmp:/tmp alpine sh -c "dd if=/dev/zero of=/tmp/test bs=1M count=100"

# 内存性能测试
docker run --rm alpine sh -c "free -m && sync && echo 3 > /proc/sys/vm/drop_caches && free -m"

生产环境实践

部署策略

生产环境部署模式

部署模式特点优势劣势适用场景
单机部署简单直接部署简单、成本低无高可用、扩展性差小型应用、开发环境
Docker Swarm原生集群简单易用、内置负载均衡功能相对简单中小型集群
Kubernetes容器编排平台功能强大、生态丰富复杂度高、学习成本大大规模生产环境
云服务托管服务免运维、高可用成本高、厂商绑定快速上线、企业应用

蓝绿部署示例

#!/bin/bash
# blue-green-deploy.sh

# 配置变量
IMAGE_NAME="myapp"
NEW_VERSION=$1
CURRENT_COLOR=$(docker ps --filter "name=app-" --format "{{.Names}}" | head -1 | cut -d'-' -f2)

if [ "$CURRENT_COLOR" = "blue" ]; then
    NEW_COLOR="green"
    OLD_COLOR="blue"
else
    NEW_COLOR="blue"
    OLD_COLOR="green"
fi

echo "当前版本: $OLD_COLOR, 新版本: $NEW_COLOR"

# 部署新版本
docker run -d \
    --name app-$NEW_COLOR \
    --network app-network \
    -e COLOR=$NEW_COLOR \
    $IMAGE_NAME:$NEW_VERSION

# 健康检查
echo "等待新版本启动..."
sleep 30

# 检查新版本健康状态
if docker exec app-$NEW_COLOR curl -f http://localhost:8080/health; then
    echo "新版本健康检查通过"
    
    # 切换流量
    docker exec nginx nginx -s reload
    
    # 停止旧版本
    docker stop app-$OLD_COLOR
    docker rm app-$OLD_COLOR
    
    echo "部署完成: $NEW_VERSION"
else
    echo "新版本健康检查失败,回滚"
    docker stop app-$NEW_COLOR
    docker rm app-$NEW_COLOR
    exit 1
fi

滚动更新策略

# docker-compose.yml 滚动更新配置
version: '3.8'

services:
  app:
    image: myapp:${VERSION:-latest}
    deploy:
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
        monitor: 60s
        max_failure_ratio: 0.3
      rollback_config:
        parallelism: 1
        delay: 10s
        failure_action: pause
        monitor: 60s
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s

CI/CD 集成

GitLab CI/CD 流水线

# .gitlab-ci.yml
stages:
  - build
  - test
  - security
  - deploy

variables:
  DOCKER_DRIVER: overlay2
  DOCKER_TLS_CERTDIR: "/certs"
  IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

services:
  - docker:20.10.16-dind

before_script:
  - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY

build:
  stage: build
  script:
    - docker build -t $IMAGE_TAG .
    - docker push $IMAGE_TAG
  only:
    - main
    - develop

test:
  stage: test
  script:
    - docker run --rm $IMAGE_TAG npm test
    - docker run --rm $IMAGE_TAG npm run lint
  only:
    - main
    - develop

security_scan:
  stage: security
  script:
    - docker run --rm -v /var/run/docker.sock:/var/run/docker.sock 
      aquasec/trivy image --exit-code 1 --severity HIGH,CRITICAL $IMAGE_TAG
  allow_failure: true
  only:
    - main

deploy_staging:
  stage: deploy
  script:
    - docker-compose -f docker-compose.staging.yml pull
    - docker-compose -f docker-compose.staging.yml up -d
  environment:
    name: staging
    url: https://staging.example.com
  only:
    - develop

deploy_production:
  stage: deploy
  script:
    - ./scripts/blue-green-deploy.sh $CI_COMMIT_SHA
  environment:
    name: production
    url: https://example.com
  when: manual
  only:
    - main

GitHub Actions 工作流

# .github/workflows/docker.yml
name: Docker Build and Deploy

on:
  push:
    branches: [ main, develop ]
  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 repository
      uses: actions/checkout@v3

    - name: Log in to Container Registry
      uses: docker/login-action@v2
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v4
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        tags: |
          type=ref,event=branch
          type=ref,event=pr
          type=sha

    - name: Build and push Docker image
      uses: docker/build-push-action@v4
      with:
        context: .
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}

  test:
    needs: build
    runs-on: ubuntu-latest
    steps:
    - name: Run tests
      run: |
        docker run --rm ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.sha }} npm test

  security:
    needs: build
    runs-on: ubuntu-latest
    steps:
    - 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'

    - name: Upload Trivy scan results
      uses: github/codeql-action/upload-sarif@v2
      with:
        sarif_file: 'trivy-results.sarif'

  deploy:
    if: github.ref == 'refs/heads/main'
    needs: [build, test, security]
    runs-on: ubuntu-latest
    environment: production
    steps:
    - name: Deploy to production
      run: |
        # 部署脚本
        echo "Deploying ${{ github.sha }} to production"

集群管理

Docker Swarm 集群配置

# 初始化 Swarm 集群
docker swarm init --advertise-addr 192.168.1.100

# 添加管理节点
docker swarm join-token manager
docker swarm join --token SWMTKN-xxx 192.168.1.100:2377

# 添加工作节点
docker swarm join-token worker
docker swarm join --token SWMTKN-xxx 192.168.1.100:2377

# 查看集群状态
docker node ls
docker service ls
docker stack ls

# 部署服务栈
docker stack deploy -c docker-compose.yml myapp

Docker Swarm 服务配置

# docker-compose.swarm.yml
version: '3.8'

services:
  web:
    image: nginx:alpine
    ports:
      - "80:80"
    deploy:
      replicas: 3
      placement:
        constraints:
          - node.role == worker
      resources:
        limits:
          cpus: '0.5'
          memory: 256M
        reservations:
          cpus: '0.25'
          memory: 128M
      restart_policy:
        condition: on-failure
        delay: 5s
        max_attempts: 3
        window: 120s
      update_config:
        parallelism: 1
        delay: 10s
        failure_action: rollback
    networks:
      - webnet
    volumes:
      - web_data:/usr/share/nginx/html

  db:
    image: postgres:13
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: user
      POSTGRES_PASSWORD_FILE: /run/secrets/db_password
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.labels.type == database
    secrets:
      - db_password
    volumes:
      - db_data:/var/lib/postgresql/data
    networks:
      - dbnet

volumes:
  web_data:
  db_data:

networks:
  webnet:
    driver: overlay
  dbnet:
    driver: overlay

secrets:
  db_password:
    external: true

运维经验

生产环境检查清单

#!/bin/bash
# production-checklist.sh

echo "=== Docker 生产环境检查清单 ==="

# 1. 系统资源检查
echo "1. 系统资源检查"
df -h
free -h
docker system df

# 2. 容器状态检查
echo "2. 容器状态检查"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

# 3. 镜像安全检查
echo "3. 镜像安全检查"
for image in $(docker images --format "{{.Repository}}:{{.Tag}}"); do
    echo "扫描镜像: $image"
    trivy image --severity HIGH,CRITICAL $image
done

# 4. 网络连通性检查
echo "4. 网络连通性检查"
docker network ls
for container in $(docker ps --format "{{.Names}}"); do
    echo "检查容器 $container 网络连通性"
    docker exec $container ping -c 1 google.com > /dev/null && echo "OK" || echo "FAIL"
done

# 5. 数据卷检查
echo "5. 数据卷检查"
docker volume ls
docker volume ls --filter dangling=true

# 6. 日志检查
echo "6. 日志检查"
for container in $(docker ps --format "{{.Names}}"); do
    echo "检查容器 $container 日志"
    docker logs --tail 10 $container
done

# 7. 性能指标检查
echo "7. 性能指标检查"
docker stats --no-stream

echo "=== 检查完成 ==="

故障恢复脚本

#!/bin/bash
# disaster-recovery.sh

BACKUP_DIR="/backup/docker"
DATE=$(date +%Y%m%d_%H%M%S)

# 1. 停止所有服务
echo "停止所有 Docker 服务..."
docker-compose down

# 2. 备份当前状态
echo "备份当前状态..."
mkdir -p $BACKUP_DIR/failed_$DATE
docker save $(docker images -q) > $BACKUP_DIR/failed_$DATE/images.tar
cp -r /var/lib/docker/volumes $BACKUP_DIR/failed_$DATE/

# 3. 恢复到最近的备份
echo "恢复到最近的备份..."
LATEST_BACKUP=$(ls -t $BACKUP_DIR/backup_* | head -1)
if [ -n "$LATEST_BACKUP" ]; then
    docker load < $LATEST_BACKUP/images.tar
    rsync -av $LATEST_BACKUP/volumes/ /var/lib/docker/volumes/
fi

# 4. 重启服务
echo "重启服务..."
docker-compose up -d

# 5. 健康检查
echo "执行健康检查..."
sleep 30
./production-checklist.sh

echo "故障恢复完成"

性能优化配置

{
  "data-root": "/var/lib/docker",
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  },
  "live-restore": true,
  "userland-proxy": false,
  "experimental": false,
  "metrics-addr": "127.0.0.1:9323",
  "max-concurrent-downloads": 10,
  "max-concurrent-uploads": 5,
  "default-shm-size": "64M"
}

监控告警配置

# alertmanager.yml
global:
  smtp_smarthost: 'localhost:587'
  smtp_from: '[email protected]'

route:
  group_by: ['alertname']
  group_wait: 10s
  group_interval: 10s
  repeat_interval: 1h
  receiver: 'web.hook'

receivers:
- name: 'web.hook'
  email_configs:
  - to: '[email protected]'
    subject: 'Docker Alert: {{ .GroupLabels.alertname }}'
    body: |
      {{ range .Alerts }}
      Alert: {{ .Annotations.summary }}
      Description: {{ .Annotations.description }}
      {{ end }}

inhibit_rules:
  - source_match:
      severity: 'critical'
    target_match:
      severity: 'warning'
    equal: ['alertname', 'dev', 'instance']

自动化运维脚本

#!/bin/bash
# auto-maintenance.sh

# 定期清理脚本(建议每天运行)
echo "开始自动维护..."

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

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

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

# 4. 清理未使用的数据卷(谨慎使用)
# docker volume prune -f

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

# 6. 检查磁盘空间
DISK_USAGE=$(df /var/lib/docker | tail -1 | awk '{print $5}' | sed 's/%//')
if [ $DISK_USAGE -gt 80 ]; then
    echo "警告:Docker 存储空间使用率超过 80%"
    # 发送告警
    curl -X POST -H 'Content-type: application/json' \
        --data '{"text":"Docker 存储空间不足,使用率: '$DISK_USAGE'%"}' \
        $SLACK_WEBHOOK_URL
fi

# 7. 更新镜像(可选)
# docker-compose pull
# docker-compose up -d

echo "自动维护完成"

这样就完成了 Docker 技术文档的编写。文档涵盖了从基础概念到生产环境实践的全方位内容,包括安装配置、镜像管理、容器管理、网络存储、安全监控等各个方面,为 Docker 的学习和使用提供了完整的参考指南。