最后更新于:2026年7月

Docker 容器编排指南
Docker:标准化软件交付单元

Docker 改变了软件的打包和交付方式。 从"在我的机器上能跑"到"在任何地方都能跑",容器技术让应用部署变得简单、一致、可复制。根据 2025 年 CNCF 调查,超过 90% 的组织在生产环境使用容器。

但很多人对 Docker 的使用还停留在 docker run 和简单的 docker-compose up。镜像是怎么构建的?网络是怎么工作的?数据怎么持久化?多容器怎么编排?生产环境怎么部署?

本文从核心原理到生产级实践,带你全面掌握 Docker 进阶技能。


一、Docker 核心概念回顾

1.1 Docker 架构

PLAINTEXT
Docker 架构:

┌─────────────────────────────────────────┐
│             Docker Client               │
│         (docker CLI / API)              │
└─────────────────┬───────────────────────┘
                  │ REST API
┌─────────────────▼───────────────────────┐
│             Docker Daemon               │
│    (dockerd, 运行在宿主机上)            │
└──────┬──────────────┬───────────────────┘
       │              │
┌──────▼──────┐ ┌─────▼──────┐ ┌─────────────┐
│   Images    │ │ Containers │ │   Network   │
│   镜像      │ │   容器      │ │   网络      │
└─────────────┘ └────────────┘ └─────────────┘
       │              │
┌──────▼──────────────▼─────────────────────┐
│              Storage Driver               │
│   (overlay2 / devicemapper / btrfs)      │
└──────────────────────────────────────────┘
       │
┌──────▼──────┐
│  Registry   │
│ (镜像仓库)   │
│ Docker Hub  │
│ 阿里云/腾讯云│
└─────────────┘

1.2 核心概念对比

概念说明类比
Image(镜像)只读模板,包含运行应用所需的一切安装光盘/ISO
Container(容器)镜像的运行实例,可读写的层运行中的虚拟机
Registry(仓库)存储和分发镜像的服务应用商店
Dockerfile构建镜像的脚本编译脚本
Volume(卷)持久化存储,独立于容器生命周期外部硬盘
Network(网络)容器间通信的虚拟网络局域网

1.3 镜像分层原理

PLAINTEXT
镜像分层结构:

┌──────────────────────┐
│  Container Layer     │  ← 容器层(可写,运行时)
│  (R/W)               │
├──────────────────────┤
│  Layer N: App Code   │  ← 应用代码层
├──────────────────────┤
│  Layer N-1: Runtime  │  ← 运行时层(Node/Python)
├──────────────────────┤
│  Layer N-2: OS Base  │  ← 基础系统层(alpine/ubuntu)
├──────────────────────┤
│  Layer 1: Kernel     │  ← 内核(共享宿主机内核)
└──────────────────────┘

特点:
- 每一层都是只读的
- 镜像复用:相同层只存储一份
- 容器启动时在顶层添加可写层
- UnionFS(联合文件系统)实现多层叠加

二、镜像优化

2.1 基础镜像选择

DOCKERFILE
# ❌ 不推荐:使用完整版 Ubuntu/Debian
FROM ubuntu:latest
RUN apt-get update && apt-get install -y nodejs npm
# 镜像大小:~700MB

# ✅ 推荐:使用 Alpine 版本
FROM node:20-alpine
# 镜像大小:~150MB

# ✅ 推荐:使用 distroless(Google 出品,最小化)
FROM gcr.io/distroless/nodejs20-debian11
# 镜像大小:~50MB,无 Shell,更安全

基础镜像大小对比:

镜像大小特点
ubuntu:latest~77MB完整版
ubuntu:22.04~77MBLTS 版
debian:12-slim~74MB精简版
alpine:3.19~7MB超小,musl libc
gcr.io/distroless/base~20MB无 Shell,生产推荐

2.2 多阶段构建(Multi-stage Build)

DOCKERFILE
# Dockerfile 多阶段构建示例

# ===== 构建阶段 =====
FROM node:20-alpine AS builder

WORKDIR /app

# 安装依赖
COPY package.json pnpm-lock.yaml ./
RUN npm install -g pnpm && pnpm install --frozen-lockfile

# 复制源码并构建
COPY . .
RUN pnpm build

# ===== 运行阶段 =====
FROM node:20-alpine AS runner

WORKDIR /app

# 创建非 root 用户
RUN addgroup --system --gid 1001 nodejs && \
    adduser --system --uid 1001 nextjs

# 只复制构建产物
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000

ENV PORT=3000
ENV NODE_ENV=production

CMD ["node", "server.js"]

# 构建命令:
# docker build -t myapp:latest .
# 最终镜像大小:~100MB(而不是 ~500MB)

2.3 减少镜像层的技巧

DOCKERFILE
# ❌ 不推荐:多个 RUN 命令,每层都增加大小
RUN apt-get update
RUN apt-get install -y python3
RUN apt-get install -y python3-pip
RUN apt-get clean

# ✅ 推荐:合并为一个 RUN 命令,清理缓存
RUN apt-get update && \
    apt-get install -y --no-install-recommends \
        python3 \
        python3-pip \
    && rm -rf /var/lib/apt/lists/* \
    && apt-get clean

# ✅ 推荐:使用 --no-install-recommends
RUN apt-get install -y --no-install-recommends vim

# ✅ 推荐:清理缓存
RUN pip install --no-cache-dir -r requirements.txt

# ✅ 推荐:COPY . 后立即 RUN,利用缓存
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm build

2.4 .dockerignore 文件

DOCKERIGNORE
# .dockerignore

# 依赖目录
node_modules
.pnpm-store

# 构建产物
dist
build
.next
.nuxt
out

# 日志
*.log
logs

# 环境变量
.env
.env.*
!.env.example

# IDE
.idea
.vscode
*.swp

# Git
.git
.gitignore

# Docker
Dockerfile*
docker-compose*
.docker

# 测试
coverage
.nyc_output
__tests__

# 文档
*.md
!README.md
docs

# 其他
.DS_Store
Thumbs.db
*.bak
*.tmp

2.5 构建缓存优化

DOCKERFILE
# 利用 Docker 构建缓存的正确顺序

# 1. 先复制依赖文件(变化频率低)
COPY package.json pnpm-lock.yaml ./

# 2. 安装依赖(只有依赖变化才重新执行)
RUN pnpm install --frozen-lockfile

# 3. 复制源码(变化频率高,放最后)
COPY . .

# 4. 构建
RUN pnpm build

# 原理:
# Docker 会根据每层的内容计算哈希
# 如果哈希相同,就使用缓存
# 所以把变化最少的层放前面

三、网络配置

3.1 Docker 网络模式

模式说明使用场景
bridge默认模式,容器有独立 IP单机多容器
host共享宿主机网络高性能、无网络隔离
none无网络安全隔离、离线任务
overlay跨主机网络Swarm 集群
macvlan容器有独立 MAC网络设备仿真

3.2 自定义网络

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

# 创建带子网的网络
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --gateway 172.20.0.1 \
  my-network

# 创建网络时指定 IP 范围
docker network create \
  --driver bridge \
  --subnet 172.20.0.0/16 \
  --ip-range 172.20.0.0/24 \
  my-network

# 查看网络
docker network ls
docker network inspect my-network

# 删除网络
docker network rm my-network

3.3 容器连接到网络

BASH
# 启动容器时连接到网络
docker run -d --name app \
  --network my-network \
  nginx:alpine

# 指定固定 IP
docker run -d --name app \
  --network my-network \
  --ip 172.20.0.100 \
  nginx:alpine

# 运行中的容器连接到网络
docker network connect my-network app

# 断开网络
docker network disconnect my-network app

3.4 容器间通信

YAML
# docker-compose.yml 网络配置示例

services:
  web:
    image: nginx:alpine
    networks:
      - frontend
    depends_on:
      - api

  api:
    image: node:20-alpine
    networks:
      - frontend
      - backend
    environment:
      - DB_HOST=db

  db:
    image: postgres:16-alpine
    networks:
      - backend
    volumes:
      - db-data:/var/lib/postgresql/data

networks:
  frontend:
  backend:

volumes:
  db-data:

3.5 端口映射详解

BASH
# 基本端口映射
docker run -d -p 80:80 nginx

# 映射到特定 IP
docker run -d -p 127.0.0.1:80:80 nginx

# 映射 UDP
docker run -d -p 53:53/udp dnsmasq

# 映射多个端口
docker run -d -p 80:80 -p 443:443 nginx

# 随机端口映射
docker run -d -P nginx  # 大写 P,随机分配宿主机端口

# 查看端口映射
docker port container_name

四、数据卷管理

4.1 数据持久化方式

方式说明生命周期使用场景
VolumeDocker 管理的存储独立于容器生产推荐
Bind Mount挂载宿主机目录依赖宿主机开发环境
tmpfs内存存储容器停止即消失敏感数据、临时文件

4.2 Volume 操作

BASH
# 创建卷
docker volume create my-data

# 查看所有卷
docker volume ls

# 查看卷详情
docker volume inspect my-data

# 使用卷
docker run -d --name app \
  -v my-data:/app/data \
  nginx:alpine

# 匿名卷(Docker 自动命名)
docker run -d -v /app/data nginx:alpine

# 删除卷
docker volume rm my-data

# 删除所有未使用的卷
docker volume prune

# 备份卷
docker run --rm \
  -v my-data:/data \
  -v $(pwd):/backup \
  alpine tar czf /backup/my-data.tar.gz -C /data .

# 恢复卷
docker run --rm \
  -v my-data:/data \
  -v $(pwd):/backup \
  alpine tar xzf /backup/my-data.tar.gz -C /data

4.3 Bind Mount

BASH
# 挂载宿主机目录
docker run -d --name app \
  -v /path/on/host:/path/in/container \
  nginx:alpine

# 只读挂载
docker run -d --name app \
  -v /path/on/host:/path/in/container:ro \
  nginx:alpine

# 开发环境热更新
docker run -d --name app \
  -v $(pwd)/src:/app/src \
  -v $(pwd)/package.json:/app/package.json \
  node:20-alpine \
  npm run dev

# 使用 $PWD 更方便
docker run -d -v ${PWD}:/app node:20-alpine

4.4 数据卷容器

BASH
# 创建数据卷容器(只存储数据)
docker create --name db-data \
  -v /var/lib/postgresql/data \
  postgres:16-alpine /bin/true

# 其他容器使用数据卷容器的卷
docker run -d --name db1 \
  --volumes-from db-data \
  postgres:16-alpine

docker run -d --name db2 \
  --volumes-from db-data \
  postgres:16-alpine

五、资源限制与安全

5.1 资源限制

BASH
# 内存限制
docker run -d --name app \
  --memory="512m" \          # 最大内存
  --memory-swap="1g" \       # 内存+交换分区上限
  --memory-reservation="256m" \ # 内存软限制
  nginx:alpine

# CPU 限制
docker run -d --name app \
  --cpus="1.5" \             # 最多使用 1.5 个 CPU
  --cpu-shares=512 \         # CPU 权重(相对值)
  --cpuset-cpus="0,2" \      # 只使用 CPU 0 和 2
  nginx:alpine

# IO 限制(需要 --device)
docker run -d --name app \
  --device-read-bps=/dev/sda:10mb \
  --device-write-bps=/dev/sda:10mb \
  nginx:alpine

# PIDs 限制(防止 Fork 炸弹)
docker run -d --name app \
  --pids-limit 100 \
  nginx:alpine

5.2 Docker Compose 资源限制

YAML
services:
  api:
    image: node:20-alpine
    deploy:
      resources:
        limits:
          cpus: '1.0'
          memory: 512M
        reservations:
          cpus: '0.5'
          memory: 256M

5.3 安全最佳实践

DOCKERFILE
# 1. 使用非 root 用户
FROM node:20-alpine

RUN addgroup -g 1001 appgroup && \
    adduser -u 1001 -G appgroup -D appuser

USER appuser

# 2. 只复制必要文件
COPY --chown=appuser:appgroup package.json ./
COPY --chown=appuser:appgroup dist/ ./dist/

# 3. 不暴露敏感信息
# 使用环境变量或 secrets

# 4. 使用 COPY 代替 ADD(除非需要解压)
COPY app.jar /app/

# 5. 指定版本号,不使用 latest
FROM node:20.10.0-alpine
BASH
# 运行时安全选项
docker run -d --name app \
  --read-only \                    # 只读文件系统
  --cap-drop ALL \                 # 删除所有权限
  --cap-add NET_BIND_SERVICE \     # 只添加必要权限
  --security-opt no-new-privileges \ # 禁止提权
  --pids-limit 100 \               # 限制进程数
  --tmpfs /tmp:rw,size=100m,mode=1777 \ # tmpfs 挂载
  nginx:alpine

# 只读容器 + tmpfs
docker run -d --name app \
  --read-only \
  --tmpfs /tmp \
  --tmpfs /var/run \
  --tmpfs /var/cache/nginx \
  nginx:alpine

5.4 Docker Content Trust(镜像签名)

BASH
# 启用镜像签名验证
export DOCKER_CONTENT_TRUST=1

# 推送签名镜像
docker push myregistry.com/myapp:1.0

# 拉取时验证签名
docker pull myregistry.com/myapp:1.0

# 管理密钥
docker trust key generate mykey
docker trust signer add --key mykey.pub me myregistry.com/myapp

六、监控与日志

6.1 日志管理

BASH
# 查看容器日志
docker logs app
docker logs -f app          # 实时跟踪
docker logs --tail 100 app  # 最近 100 行
docker logs --since 1h app  # 最近 1 小时

# 日志驱动
docker run -d --name app \
  --log-driver json-file \
  --log-opt max-size=10m \
  --log-opt max-file=3 \
  nginx:alpine

# syslog 日志驱动
docker run -d --name app \
  --log-driver syslog \
  --log-opt syslog-address=tcp://logserver:514 \
  nginx:alpine

# 无日志(用于批处理)
docker run -d --name app \
  --log-driver none \
  nginx:alpine

6.2 资源监控

BASH
# 实时监控
docker stats

# 只看一次
docker stats --no-stream

# 指定容器
docker stats app1 app2

# 查看进程
docker top app

# 查看容器资源使用
docker container ls -s  # -s 显示大小

6.3 cAdvisor + Prometheus + Grafana

YAML
# docker-compose.monitoring.yml

services:
  cadvisor:
    image: gcr.io/cadvisor/cadvisor:latest
    container_name: cadvisor
    ports:
      - "8080:8080"
    volumes:
      - /:/rootfs:ro
      - /var/run:/var/run:rw
      - /sys:/sys:ro
      - /var/lib/docker/:/var/lib/docker:ro
    restart: always

  prometheus:
    image: prom/prometheus:latest
    container_name: prometheus
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    restart: always

  grafana:
    image: grafana/grafana:latest
    container_name: grafana
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
    volumes:
      - grafana-data:/var/lib/grafana
    restart: always

volumes:
  grafana-data:

七、Docker Compose 进阶

7.1 完整配置示例

YAML
# docker-compose.yml 生产级配置

version: '3.8'

services:
  # ===== 前端 =====
  web:
    build:
      context: ./web
      dockerfile: Dockerfile
      args:
        - NODE_ENV=production
    image: myapp-web:${VERSION:-latest}
    container_name: web
    restart: always
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - API_URL=http://api:8000
    depends_on:
      api:
        condition: service_healthy
    networks:
      - frontend
    deploy:
      resources:
        limits:
          cpus: '1'
          memory: 512M
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 40s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  # ===== 后端 API =====
  api:
    build:
      context: ./api
      dockerfile: Dockerfile
    image: myapp-api:${VERSION:-latest}
    container_name: api
    restart: always
    ports:
      - "8000:8000"
    environment:
      - DATABASE_URL=postgresql://postgres:password@db:5432/myapp
      - REDIS_URL=redis://redis:6379
      - JWT_SECRET=${JWT_SECRET}
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - frontend
      - backend
    volumes:
      - api-uploads:/app/uploads
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 1G
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
      interval: 30s
      timeout: 10s
      retries: 3
      start_period: 30s
    logging:
      driver: json-file
      options:
        max-size: "10m"
        max-file: "3"

  # ===== 数据库 =====
  db:
    image: postgres:16-alpine
    container_name: db
    restart: always
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=password
      - POSTGRES_DB=myapp
    volumes:
      - db-data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    logging:
      driver: json-file
      options:
        max-size: "5m"
        max-file: "3"

  # ===== Redis =====
  redis:
    image: redis:7-alpine
    container_name: redis
    restart: always
    command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis-data:/data
    networks:
      - backend
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

networks:
  frontend:
    driver: bridge
  backend:
    driver: bridge
    internal: true  # 内部网络,不能访问外网

volumes:
  db-data:
  redis-data:
  api-uploads:

7.2 多环境配置

YAML
# docker-compose.yml(基础配置)
version: '3.8'
services:
  web:
    build: ./web
    ports:
      - "${PORT:-3000}:3000"

---
# docker-compose.override.yml(开发环境,自动加载)
version: '3.8'
services:
  web:
    volumes:
      - ./web:/app
    environment:
      - NODE_ENV=development

---
# docker-compose.prod.yml(生产环境)
version: '3.8'
services:
  web:
    restart: always
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: '1'
          memory: 512M
BASH
# 开发环境(自动加载 override)
docker-compose up -d

# 生产环境
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

7.3 常用命令

BASH
# 启动
docker-compose up -d

# 构建并启动
docker-compose up -d --build

# 指定文件
docker-compose -f docker-compose.prod.yml up -d

# 查看状态
docker-compose ps

# 查看日志
docker-compose logs -f
docker-compose logs -f web

# 进入容器
docker-compose exec web sh

# 重启服务
docker-compose restart web

# 停止并删除
docker-compose down

# 停止并删除卷
docker-compose down -v

# 拉取镜像
docker-compose pull

# 查看资源使用
docker-compose top
docker-compose stats

八、多架构构建

8.1 buildx 多架构构建

BASH
# 启用 buildx
docker buildx version

# 创建多架构构建器
docker buildx create --name mybuilder --use

# 查看构建器
docker buildx inspect --bootstrap

# 构建多架构镜像
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myregistry.com/myapp:latest \
  --push \
  .

# 只构建不推送
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myregistry.com/myapp:latest \
  --load \
  .

8.2 Dockerfile 多架构兼容

DOCKERFILE
# 使用平台参数
FROM --platform=$BUILDPLATFORM node:20-alpine AS builder

ARG TARGETPLATFORM
ARG BUILDPLATFORM

WORKDIR /app

COPY . .

RUN echo "Building on $BUILDPLATFORM for $TARGETPLATFORM"

# 或使用条件判断
FROM node:20-alpine AS builder

ARG TARGETARCH

RUN if [ "$TARGETARCH" = "arm64" ]; then \
      echo "Building for ARM64"; \
    else \
      echo "Building for AMD64"; \
    fi

九、镜像仓库管理

9.1 Docker Hub

BASH
# 登录
docker login

# 推送镜像
docker tag myapp:latest username/myapp:latest
docker push username/myapp:latest

# 推送带标签
docker push username/myapp:v1.0.0

# 拉取镜像
docker pull username/myapp:latest

# 搜索镜像
docker search nginx

9.2 私有仓库

BASH
# 启动私有仓库
docker run -d -p 5000:5000 --name registry \
  -v registry-data:/var/lib/registry \
  registry:2

# 推送到私有仓库
docker tag myapp:latest localhost:5000/myapp:latest
docker push localhost:5000/myapp:latest

# 从私有仓库拉取
docker pull localhost:5000/myapp:latest

# 查看仓库中的镜像
curl -s localhost:5000/v2/_catalog | jq

9.3 Harbor 企业级仓库

YAML
# docker-compose.harbor.yml(简化版)
# 完整安装请参考 Harbor 官方文档

services:
  harbor-core:
    image: goharbor/harbor-core:v2.10.0
    ...

  harbor-portal:
    image: goharbor/harbor-portal:v2.10.0
    ...

  registry:
    image: goharbor/registry-photon:v2.10.0
    ...

十、实用技巧与故障排查

10.1 清理空间

BASH
# 删除停止的容器
docker container prune

# 删除未使用的镜像
docker image prune -a

# 删除未使用的卷
docker volume prune

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

# 一键清理所有未使用资源
docker system prune -a --volumes

# 查看空间占用
docker system df
docker system df -v

10.2 常见问题排查

BASH
# 容器无法启动
docker logs container_name
docker inspect container_name

# 镜像拉取慢
# 配置镜像加速
# /etc/docker/daemon.json
{
  "registry-mirrors": [
    "https://mirror.ccs.tencentyun.com",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}

# 重启 Docker
sudo systemctl restart docker

# 网络问题
docker network inspect bridge
iptables -t nat -L -n

# 磁盘空间不足
docker system df
docker system prune -a

# 权限问题
sudo usermod -aG docker $USER
# 重新登录

# 查看 Docker 信息
docker info
docker version

10.3 调试技巧

BASH
# 进入运行中的容器
docker exec -it container_name sh

# 使用不同 Shell
docker exec -it container_name bash
docker exec -it container_name ash  # Alpine

# 复制文件
docker cp file.txt container_name:/path/
docker cp container_name:/path/file.txt ./

# 查看容器变化
docker diff container_name

# 导出容器为镜像
docker export container_name | docker import - myapp:latest

# 保存镜像为文件
docker save -o myapp.tar myapp:latest

# 从文件加载镜像
docker load -i myapp.tar

十一、总结

Docker 进阶技能清单

学习路径

PLAINTEXT
入门(第1周):
  → Docker 基础命令
  → Dockerfile 编写
  → Docker Compose 基础

进阶(第2-3周):
  → 镜像优化
  → 网络配置
  → 数据卷管理

高级(第1-2月):
  → 多阶段构建
  → 安全配置
  → 监控日志
  → 多架构构建

专家(第3月+):
  → Kubernetes 迁移
  → Docker Swarm 集群
  → CI/CD 集成
  → 自定义网络插件

【相关推荐】


Docker 是现代开发的基石。 掌握 Docker 进阶技能,你才能在微服务、云原生、DevOps 的世界里游刃有余。🚀

版权声明

作者: 易邦

链接: https://blog.e8k.net/posts/docker-advanced-container-orchestration-2026/

许可证: 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。