Loading...

文章背景图

Docker 生产环境运维指南(持续更新)

2026-06-03
1
-
- 分钟
|

Docker 生产环境运维指南(持续更新)

前言

Docker 是什么?

想象一下:你要开一家餐厅。传统方式:

  • 买地皮、盖房子(买服务器)
  • 装修、买厨房设备(装系统、配环境)
  • 请厨师(部署应用)

Docker 方式:

  • 直接租一个标准化集装箱厨房(容器)
  • 里面已经配好了灶台、烤箱等设备(系统+环境)
  • 厨师进去就能开工(应用直接运行)

这就是 Docker 的魔力:一次打包,到处运行!

Docker 是现代云原生的基石,被无数公司用于:

  • 应用的打包和部署
  • 微服务架构
  • 持续集成/持续部署(CI/CD)
  • 开发环境标准化

作为运维工程师,我们的职责是:让容器稳如磐石、快如闪电

本文档会告诉你:

  • Docker 核心概念和命令
  • docker info 所有信息的含义
  • 怎么部署 Docker Swarm 集群
  • Docker 底层原理(namespace、cgroups、内核态)

目录

  1. 快速入门
  2. docker info 详解
  3. Dockerfile 构建镜像
  4. docker-compose 编排服务
  5. 镜像层详解
  6. daemon.json 配置
  7. 常用命令
  8. Docker Swarm 集群
  9. Docker 底层原理
  10. 运维监控
  11. 常见问题排查

快速入门

Docker 基本概念

概念 通俗解释
镜像(Image) 就像"菜谱",定义了怎么制作这道菜
容器(Container) 就像"做好的菜",按照菜谱做出来的成品
仓库(Registry) 就像"菜市场",存放和分发菜谱的地方
Dockerfile 就像"烹饪配方",告诉 Docker 怎么制作镜像

安装 Docker

# Ubuntu/Debian
sudo apt update
sudo apt install docker.io

# 启动 Docker
sudo systemctl start docker
sudo systemctl enable docker

# 把当前用户加入 docker 组(免 sudo)
sudo usermod -aG docker $USER
# 需要重新登录生效

第一个容器

# 👀 运行一个 Nginx 容器
docker run -d --name my-nginx -p 80:80 nginx

# 查看运行中的容器
docker ps

# 停止容器
docker stop my-nginx

# 启动容器
docker start my-nginx

# 删除容器
docker rm my-nginx

docker info 详解

docker info 是最重要的诊断命令!

就像汽车的"仪表盘",docker info 显示 Docker 的所有配置信息和运行状态。

Client(客户端)

Client:
 Version:    29.1.3
 Context:    default
 Debug Mode: false
 Plugins:
  compose: Docker Compose (Docker Inc.)
  Version:  2.40.3+ds1-0ubuntu1~24.04.1
  Path:     /usr/libexec/docker/cli-plugins/docker-compose
  trust: Manage trust on Docker images (Docker Inc.)
  Version:  29.1.3
  Path:     /usr/libexec/docker/cli-plugins/docker-trust

通俗解释:

字段 通俗解释
Version Docker 客户端版本(你正在使用的版本)
Context 当前使用的上下文环境(default = 默认)
Debug Mode 调试模式(false = 关闭)
Plugins 安装的插件(compose、trust 等)

Server / Engine(服务端)

Server:
 Containers: 5
  Running: 4
  Paused: 0
  Stopped: 1
 Images: 4

通俗解释:

字段 通俗解释
Containers 容器总数(5个)
Running 正在运行的(4个)
Paused 暂停的(0个)
Stopped 已停止的(1个)
Images 镜像数量(4个)

Server Version(服务端版本)

Server Version: 29.1.3

通俗解释:

Docker 服务端(daemon)版本。客户端和服务端版本最好保持一致!


Storage Driver(存储驱动)

Storage Driver: overlayfs
 driver-type: io.containerd.snapshotter.v1

通俗解释:

字段 通俗解释
Storage Driver 存储驱动(overlayfs)
driver-type 容器镜像存储类型

常见的存储驱动:

驱动 通俗解释 适用场景
overlayfs 叠加文件系统,快照方式 推荐,性能好
devicemapper 设备映射 早期版本
btrfs B树文件系统 完整支持快照
zfs Z文件系统 功能强大,占用高

Logging Driver(日志驱动)

Logging Driver: json-file

通俗解释:

容器日志的存储方式。json-file 把日志存成 JSON 文件。

常见的日志驱动:

驱动 通俗解释
json-file JSON 格式文件(默认)
syslog 系统日志
journald systemd 日志
fluentd Fluentd 日志收集
awslogs AWS CloudWatch

Cgroup(控制组)

Cgroup Driver: systemd
Cgroup Version: 2

通俗解释:

字段 通俗解释
Cgroup Driver Cgroup 驱动(systemd)
Cgroup Version Cgroup 版本(2)

什么是 Cgroup?
就像公司的"部门预算管理"。每个部门(容器)只能用分配给它的资源(CPU、内存),不能多用。Cgroup 就是 Linux 内核用来限制资源的功能。


Plugins(插件)

Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local splunk syslog

通俗解释:

插件类型 支持的插件 通俗解释
Volume local 存储卷插件
Network bridge, host, overlay 等 网络插件
Log json-file, syslog 等 日志插件

Runtimes(运行时)

Runtimes: io.containerd.runc.v2 runc
Default Runtime: runc

通俗解释:

字段 通俗解释
Runtimes 支持的容器运行时
Default Runtime 默认使用的运行时(runc)

什么是容器运行时?
就像"厨房设备"。真正执行容器的是 runc,它负责和内核交互,启动容器。


Security Options(安全选项)

Security Options:
 apparmor
 seccomp
  Profile: builtin
 cgroupns

通俗解释:

安全选项 通俗解释
apparmor AppArmor 安全模块(应用程序安全策略)
seccomp 安全计算模式(限制系统调用)
Profile: builtin 使用内置的安全配置文件
cgroupns Cgroup 命名空间(隔离资源控制组)

Kernel(内核)信息

Kernel Version: 6.8.0-124-generic
Operating System: Ubuntu 24.04.4 LTS
OSType: linux
Architecture: x86_64
CPUs: 4
Total Memory: 7.709GiB

通俗解释:

字段 通俗解释
Kernel Version Linux 内核版本(6.8.0)
Operating System 操作系统(Ubuntu 24.04)
OSType 操作系统类型(linux)
Architecture CPU 架构(x86_64 = 64位)
CPUs CPU 核心数(4核)
Total Memory 总内存(7.7GB)

Docker 信息

Name: test
ID: cd89be2d-6031-4168-a755-e03d5d0ec052
Docker Root Dir: /var/lib/docker

通俗解释:

字段 通俗解释
Name Docker 主机名称(test)
ID 主机唯一标识
Docker Root Dir Docker 数据存储目录

Registry(镜像仓库)

Registry Mirrors:
 https://registry.cn-shanghai.aliyuncs.com/

通俗解释:

镜像加速器地址。中国大陆使用阿里云加速器可以提高下载速度。


其他信息

Debug Mode: false
Experimental: false
Insecure Registries:
 ::1/128
 127.0.0.0/8
Live Restore Enabled: false
Firewall Backend: iptables
字段 通俗解释
Debug Mode 调试模式(关闭)
Experimental 实验性功能(关闭)
Insecure Registries 不安全的仓库(本地测试用)
Live Restore 守护进程重启时保持容器运行
Firewall Backend 防火墙后端(iptables)

Dockerfile 构建镜像

什么是 Dockerfile?

想象一下:你去餐厅吃饭,厨房是封闭的,你看不到厨师怎么做菜。

Dockerfile 就是"开放式厨房的菜谱"! 它清清楚楚写明了:

  • 用什么食材(基础镜像)
  • 先放什么后放什么(指令顺序)
  • 火候多大(环境变量)
  • 做完了怎么装盘(端口映射)

有了这个菜谱,任何人都能做出一样的菜!

Dockerfile 常用指令

指令 通俗解释 示例
FROM 基础镜像(用哪种面粉) FROM ubuntu:24.04
RUN 执行命令(和面、揉面) RUN apt update && apt install nginx
COPY 复制文件(把食材放进厨房) COPY ./app /app
ADD 复制文件(支持 URL 和 tar) ADD https://example.com/file.tar.gz /tmp/
WORKDIR 设置工作目录(切换到哪个操作台) WORKDIR /app
ENV 设置环境变量(厨房温度、湿度) ENV NODE_ENV=production
EXPOSE 声明端口(告诉别人从哪个门取餐) EXPOSE 80
CMD 容器启动命令(按下烹饪按钮) CMD ["npm", "start"]
ENTRYPOINT 入口点(和 CMD 类似,但不会被覆盖) ENTRYPOINT ["python"]
ARG 构建参数(临时变量) ARG VERSION=1.0
VOLUME 声明卷(外部存储) VOLUME ["/data"]
LABEL 元数据标签 LABEL version="1.0"

Dockerfile 示例

# 使用官方 Node.js 基础镜像
FROM node:18-alpine

# 设置工作目录
WORKDIR /app

# 复制 package.json
COPY package*.json ./

# 安装依赖(利用缓存加速构建)
RUN npm ci --only=production

# 复制应用代码
COPY . .

# 设置环境变量
ENV NODE_ENV=production
ENV PORT=3000

# 暴露端口
EXPOSE 3000

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

# 启动命令
CMD ["node", "server.js"]

多阶段构建

什么是多阶段构建?

想象一下:做蛋糕需要烤箱,但最终送到客户手里的只需要蛋糕,不需要烤箱。

多阶段构建就是:在厨房里用烤箱(构建阶段),最后只打包蛋糕(运行阶段)。

# 阶段1:构建
FROM node:18 AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# 阶段2:运行(只复制构建产物)
FROM node:18-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
CMD ["node", "dist/server.js"]

构建缓存机制

# ❌ 不推荐的写法(每次都重新安装依赖)
COPY . /app
RUN npm install

# ✅ 推荐的写法(利用缓存,只有 package.json 变化才重新安装)
COPY package*.json /app/
RUN npm install
COPY . /app/

.dockerignore 文件

什么是 .dockerignore?

就像装修时不让工人带某些工具进场,.dockerignore 告诉 Docker 哪些文件不要打包进镜像。

# .dockerignore
node_modules
npm-debug.log
.git
.gitignore
.env
*.md

构建镜像命令

# ⚙️ 构建镜像
docker build -t myapp:1.0 .

# ⚙️ 带构建参数
docker build --build-arg VERSION=1.0 -t myapp:1.0 .

# ⚙️ 使用指定 Dockerfile
docker build -f Dockerfile.dev -t myapp:dev .

# ⚙️ 构建时不使用缓存
docker build --no-cache -t myapp:latest .

最佳实践

  1. 使用官方基础镜像

    # ✅ 推荐
    FROM python:3.11-slim
    
    # ❌ 不推荐
    FROM ubuntu
    RUN apt-get install python3.11
    
  2. 减少镜像层数

    # ✅ 合并命令减少层数
    RUN apt-get update && \
        apt-get install -y nginx && \
        apt-get clean && \
        rm -rf /var/lib/apt/lists/*
    
  3. 使用多用户(安全)

    RUN addgroup -S appgroup && adduser -S appuser -G appgroup
    USER appuser
    

docker-compose 编排服务

什么是 docker-compose?

想象一下:你开的不是一家餐厅,而是一整条美食街!

  • 川菜馆(Web 服务)
  • 粤菜馆(数据库)
  • 火锅店(Redis 缓存)
  • 奶茶店(消息队列)

docker-compose 就是同时管理整条美食街的配置手册

docker-compose.yml 结构

version: '3.8'  # compose 文件版本

services:  # 服务列表
  web:      # 服务名
    image: nginx:latest  # 使用的镜像
    ports:    # 端口映射
      - "80:80"
    environment:  # 环境变量
      - NODE_ENV=production
    volumes:       # 挂载卷
      - ./html:/usr/share/nginx/html
    networks:      # 所属网络
      - frontend
    depends_on:    # 依赖的服务
      - redis
    restart: always  # 重启策略

  redis:      # 另一个服务
    image: redis:7-alpine
    ports:
      - "6379:6379"
    volumes:
      - redis-data:/data
    networks:
      - frontend
    restart: always

networks:  # 网络定义
  frontend:
    driver: bridge

volumes:  # 卷定义
  redis-data:

docker-compose 常用命令

# 👀 启动所有服务(后台运行)
docker-compose up -d

# 👀 启动指定服务
docker-compose up -d web

# 👀 停止所有服务
docker-compose down

# 👀 停止并删除卷和网络
docker-compose down -v

# 🔄 重启所有服务
docker-compose restart

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

# 👀 查看服务状态
docker-compose ps

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

# ⚙️ 扩展服务(增加副本)
docker-compose up -d --scale web=3

depends_on vs healthcheck

# depends_on:只保证启动顺序,不保证服务就绪
services:
  web:
    depends_on:
      - db
      - redis

# healthcheck:保证服务真正就绪
services:
  web:
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

环境变量文件

# .env 文件
POSTGRES_DB=myapp
POSTGRES_USER=admin
POSTGRES_PASSWORD=secret123
# docker-compose.yml
services:
  db:
    image: postgres:16
    env_file:
      - .env
    # 或者直接在环境变量中引用
    environment:
      POSTGRES_DB: ${POSTGRES_DB}

多环境配置

# docker-compose.yml(基础配置)
services:
  web:
    image: myapp

# docker-compose.prod.yml(生产环境覆盖)
services:
  web:
    image: myapp:latest
    environment:
      - NODE_ENV=production
    deploy:
      replicas: 5
    restart: always
# 使用生产配置
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

完整示例:Web 应用 + 数据库 + Redis

version: '3.8'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    image: myapp:latest
    ports:
      - "80:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - REDIS_HOST=redis
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_started
    networks:
      - backend
    restart: always
    volumes:
      - ./logs:/app/logs

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: admin
      POSTGRES_PASSWORD: ${DB_PASSWORD:-secret123}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    networks:
      - backend
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U admin -d myapp"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: always

  redis:
    image: redis:7-alpine
    command: redis-server --requirepass ${REDIS_PASSWORD:-redis123}
    volumes:
      - redis-data:/data
    networks:
      - backend
    restart: always

networks:
  backend:
    driver: bridge

volumes:
  postgres-data:
  redis-data:

镜像层详解

什么是镜像层?

想象一下:你学做菜,先买一本菜谱基础书(基础镜像),然后:

  • 在书的第一页贴了个便签(层1)
  • 在第二页折了个角(层2)
  • 在第三页夹了一片树叶(层3)

镜像层就是这样的"叠加"结构! 每一层都是只读的,叠加在一起形成完整的文件系统。

镜像层结构

┌─────────────────────────────────────────┐
│           容器层 (Container Layer)         │
│         (writable, 可写层)               │
│    新增文件、修改文件、删除文件            │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────┴───────────────────────┐
│           镜像层 (Image Layers)           │
│            (read-only, 只读层)           │
├─────────────────────────────────────────┤
│  Layer 4: CMD, EXPOSE (元数据层)       │
├─────────────────────────────────────────┤
│  Layer 3: RUN apt-get install (安装层)  │
├─────────────────────────────────────────┤
│  Layer 2: COPY package.json (复制层)    │
├─────────────────────────────────────────┤
│  Layer 1: WORKDIR /app (工作目录层)     │
├─────────────────────────────────────────┤
│  Layer 0: FROM ubuntu (基础镜像层)      │
└─────────────────────────────────────────┘

层的作用

层类型 是否可写 通俗解释
只读层 (Image Layer) 菜谱的每一页(不可撕毁、不可涂改)
容器层 (Container Layer) 操作台上的临时操作(可以随时擦掉重做)

查看镜像层

# 👀 查看镜像的所有层
docker history myapp:1.0

# 输出示例:
# IMAGE          CREATED        SIZE
# a1b2c3d4       2 hours ago    0B
# <missing>      2 hours ago    123MB   # Layer 3
# <missing>      2 hours ago    45MB    # Layer 2
# <missing>      2 hours ago    78MB    # Layer 1
# ubuntu:24.04   3 weeks ago   78MB    # Layer 0

查看镜像详细信息

# 👀 查看镜像的完整信息
docker inspect myapp:1.0

# 查看 RootFS(只读层)
docker inspect myapp:1.0 | grep -A 20 "RootFS"

分层缓存原理

为什么 Docker 构建这么快?

想象一下:你已经做了一道红烧肉,第二次再做同样的菜,只需要把新加的调料(层)加上,之前的步骤(层)不用重复。

Docker 的分层缓存就是这样工作的! 如果某一层没变化,直接用缓存,不用重新构建。

构建过程:
Step 1: FROM ubuntu      → 没有缓存,从头开始
Step 2: RUN apt update   → 没有缓存,重新执行
Step 3: COPY package.json → 文件没变,用缓存!
Step 4: RUN npm install  → package.json 变了,重新执行
Step 5: COPY .          → 文件变了,重新执行

共享层原理

为什么不同镜像可以共享层?

想象一下:你和邻居都买了同一本菜谱书(基础镜像),你们各自在书上加了自己的便签(不同的层)。

虽然你们的便签不同,但菜谱书本身是共享的!

Docker 也是这样! 不同镜像共享相同的基础层,节省磁盘空间。

# 👀 查看层被哪些镜像共享
docker images --format "{{.Repository}}:{{.Tag}} -> {{.ID}}"

UnionFS(联合文件系统)

什么是 UnionFS?

就像把多张透明塑料纸叠加在一起,每张纸上画不同的内容,叠加后能看到完整图案。

Docker 用 UnionFS 实现层的叠加!

文件系统 通俗解释 Docker 使用情况
overlayfs 叠加文件系统 ✅ 推荐
aufs 高级多层统一文件系统 早期 Docker 使用
btrfs B树文件系统 部分使用
devicemapper 设备映射 早期版本

容器的读写机制

读取文件:
容器层没有 → 镜像层有 → 读取成功

修改文件(Copy-On-Write):
容器层没有 → 复制到容器层 → 修改容器层

删除文件:
在容器层添加"删除标记" → 文件在容器层不可见
(实际文件仍在镜像层,只是被遮盖了)

daemon.json 配置

什么是 daemon.json?

想象一下:你开了一家餐厅,需要在开业前配置好各种事项:

  • 食材从哪进货(镜像仓库)
  • 厨房多大(存储驱动)
  • 垃圾怎么处理(日志)

daemon.json 就是 Docker 的"开业前配置手册"! 告诉 Docker 守护进程怎么工作。

daemon.json 位置

# 默认位置
/etc/docker/daemon.json

常用配置项

{
  "registry-mirrors": [
    "https://registry.docker-cn.com",
    "https://mirror.ccs.tencentyun.com"
  ],
  "insecure-registries": [
    "192.168.1.100:5000"
  ],
  "storage-driver": "overlayfs",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "data-root": "/data/docker",
  "live-restore": true,
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  },
  "dns": ["8.8.8.8", "8.8.4.4"],
  "mtu": 1500
}

配置项详解

1. registry-mirrors(镜像加速器)

通俗解释:
就像你从国外进口食材太慢了,在中国设立"中转仓库",从国内拿货就快了!

{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ]
}

常用加速器:

  • 阿里云:需要登录获取专属地址
  • 腾讯云:需要登录获取专属地址
  • Docker 中国:https://registry.docker-cn.com

2. insecure-registries(不安全仓库)

通俗解释:
有些仓库没有"正规营业执照"(没有 HTTPS),需要单独声明才能使用。

{
  "insecure-registries": [
    "192.168.1.100:5000",
    "registry.mycompany.com:5000"
  ]
}

3. storage-driver(存储驱动)

通俗解释:
就像餐厅用不同的货架管理系统,Docker 用不同的存储驱动管理文件。

{
  "storage-driver": "overlayfs"
}

推荐选择:

  • overlayfs:性能好,推荐使用
  • btrfs:支持完整快照功能
  • zfs:功能强大,占用资源多

4. log-driver(日志驱动)

通俗解释:
就像餐厅的"收银记录系统",记录每个顾客的点单。

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",    // 单个日志文件最大 100MB
    "max-file": "3"         // 最多保留 3 个日志文件
  }
}

日志总大小 = 100MB × 3 = 300MB

5. data-root(数据存储路径)

通俗解释:
餐厅的"仓库"在哪,默认是 /var/lib/docker。

{
  "data-root": "/data/docker"
}

适合场景:

  • 系统盘空间不足
  • 需要挂载更大的数据盘

6. live-restore(热恢复)

通俗解释:
餐厅的"值班经理"。即使老板(Docker daemon)暂时离开去开会,餐厅(容器)也能继续营业。

{
  "live-restore": true
}
行为
true daemon 重启时,容器继续运行
false daemon 重启时,容器也重启

7. default-ulimits(默认资源限制)

通俗解释:
给每个厨师(容器)分配固定的工作台面积(文件描述符数量)。

{
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 64000,
      "Soft": 64000
    }
  }
}

8. dns(DNS 服务器)

{
  "dns": ["8.8.8.8", "114.114.114.114"]
}

配置生效

# 1. 编辑配置文件
sudo vim /etc/docker/daemon.json

# 2. 重启 Docker
sudo systemctl restart docker

# 3. 验证配置
docker info | grep -A 5 "Registry Mirrors"

完整配置示例

{
  "registry-mirrors": [
    "https://registry.docker-cn.com"
  ],
  "insecure-registries": [],
  "storage-driver": "overlayfs",
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m",
    "max-file": "3"
  },
  "live-restore": true,
  "default-ulimits": {
    "nofile": {
      "Name": "nofile",
      "Hard": 65535,
      "Soft": 65535
    }
  },
  "dns": ["8.8.8.8", "114.114.114.114"],
  "experimental": false,
  "features": {
    "buildkit": true
  }
}

Docker 配置验证

# 👀 查看当前 daemon 配置
docker info 2>&1 | head -50

# 👀 验证 daemon.json 语法
python3 -m json.tool /etc/docker/daemon.json

# 👀 查看 Docker 数据目录
docker info | grep "Docker Root Dir"

常用命令

镜像操作

# 👀 查看本地镜像
docker images

# 👀 搜索镜像
docker search nginx

# ➕ 拉取镜像
docker pull nginx:latest

# 🗑️ 删除镜像
docker rmi nginx:latest

# ➕ 构建镜像
docker build -t myapp:1.0 .

容器操作

# 👀 查看容器
docker ps              # 运行中的
docker ps -a          # 所有容器

# ➕ 运行容器
docker run -d --name myapp -p 8080:80 nginx

# ✏️ 停止/启动容器
docker stop myapp
docker start myapp

# 🗑️ 删除容器
docker rm myapp
docker rm -f myapp    # 强制删除(运行中)

# 👀 查看容器日志
docker logs myapp
docker logs -f myapp  # 实时跟踪

# 👀 进入容器
docker exec -it myapp bash

# 👀 查看容器信息
docker inspect myapp

# 👀 查看容器资源使用
docker stats myapp

docker-compose 操作

# ➕ 启动服务
docker-compose up -d

# 🗑️ 停止服务
docker-compose down

# 🔄 重启服务
docker-compose restart

# 👀 查看服务状态
docker-compose ps

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

网络操作

# 👀 查看网络
docker network ls

# ➕ 创建网络
docker network create mynetwork

# ➕ 连接容器到网络
docker network connect mynetwork myapp

# 🗑️ 删除网络
docker network rm mynetwork

清理操作

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

# 🗑️ 删除停止的容器
docker container prune

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

# 🗑️ 删除未使用的卷
docker volume prune

# 🗑️ 清理所有未使用资源
docker system prune

Docker Swarm 集群

什么是 Docker Swarm?

通俗解释:

想象一下:一家餐厅太忙了,一个厨师忙不过来怎么办?

答案是:组建厨师团队!

  • 一个主厨(Manager)负责分配任务
  • 其他厨师(Worker)负责做菜
  • 主厨挂了?没关系,选举新的主厨

Docker Swarm 就是这个"厨师团队"! 它让多个 Docker 主机协同工作,自动分配任务,自动故障切换。

Swarm 架构

┌─────────────────────────────────────────────────────────┐
│                    Docker Swarm Cluster                   │
│                                                          │
│              ┌─────────────────────────────────┐         │
│              │       Manager Nodes (主节点)      │         │
│              │  (负责: 调度、API、故障切换)       │         │
│              └─────────────────────────────────┘         │
│                           │                               │
│    ┌──────────────────────┼──────────────────────┐      │
│    │                      │                      │      │
│    ▼                      ▼                      ▼      │
│ ┌────────┐          ┌────────┐          ┌────────┐      │
│ │ Worker │          │ Worker │          │ Worker │      │
│ │ 节点1  │          │ 节点2  │          │ 节点3  │      │
│ │(执行任务)│          │(执行任务)│          │(执行任务)│      │
│ └────────┘          └────────┘          └────────┘      │
└─────────────────────────────────────────────────────────┘

Swarm 核心概念

概念 通俗解释
Node(节点) 餐厅里的一个厨师
Manager(管理器) 主厨,负责分配任务
Worker(工作者) 普通厨师,负责执行任务
Service(服务) 就像"菜谱",定义怎么制作这道菜
Task(任务) 分配给厨师的具体工作
Stack(堆栈) 一整套菜谱(多个服务)

初始化 Swarm

# 👀 初始化 Swarm(成为主节点)
docker swarm init

# 👀 查看 Swarm 状态
docker info | grep Swarm

# 👀 查看节点列表
docker node ls

添加节点到 Swarm

# 👀 在主节点生成加入令牌
docker swarm join-token worker

# 输出示例:
# docker swarm join --token SWMTKN-xxxxx 192.168.1.10:2377

# 👀 在其他服务器执行上面的命令加入集群

部署服务

# ➕ 部署服务(就像派一个厨师去做一道菜)
docker service create --name myapp --replicas 3 -p 8080:80 nginx

# 👀 查看服务列表
docker service ls

# 👀 查看服务详情
docker service ps myapp

# 👀 查看服务日志
docker service logs myapp

# ✏️ 更新服务(滚动更新)
docker service update --image nginx:1.19 myapp

# 🗑️ 删除服务
docker service rm myapp

服务扩缩容

# ⚙️ 扩容(增加厨师数量)
docker service scale myapp=5

# ⚙️ 缩容(减少厨师数量)
docker service scale myapp=2

Docker Stack(多服务部署)

使用 docker-compose.yml 部署多服务:

# docker-compose.yml
version: '3.8'

services:
  web:
    image: nginx
    ports:
      - "80:80"
    deploy:
      replicas: 3
      placement:
        constraints:
          - node.role == worker

  api:
    image: myapi:latest
    ports:
      - "8080:8080"
    deploy:
      replicas: 2

networks:
  frontend:

volumes:
  data:
# ➕ 部署 Stack
docker stack deploy -c docker-compose.yml myapp

# 👀 查看 Stack 列表
docker stack ls

# 👀 查看 Stack 中的服务
docker stack ps myapp

# 🗑️ 删除 Stack
docker stack rm myapp

Swarm 常用命令

# 👀 查看节点
docker node ls

# 👀 查看服务
docker service ls

# 👀 查看 Stack
docker stack ls

# 👀 查看密钥
docker secret ls

# 👀 查看配置
docker config ls

# ⚙️ 创建密钥
echo "mypassword" | docker secret create db_password -

# ⚙️ 创建配置
docker config create nginx_config nginx.conf

Swarm 高可用

# 👀 查看主节点信息
docker node inspect self

# ⚙️ 提升节点为主节点
docker node promote node2

# ⚙️ 降级节点为工作节点
docker node demote node2

Docker 底层原理

Docker 架构

┌─────────────────────────────────────────────────────────┐
│                      Docker Client                        │
│                    (命令行工具 docker)                    │
└─────────────────────────┬───────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                     Docker Daemon                         │
│                    (Docker 守护进程)                      │
│  ┌───────────────┬───────────────┬───────────────┐      │
│  │   containerd  │   Builder    │    Network    │      │
│  │  (容器运行时) │  (镜像构建)  │   (网络管理)  │      │
│  └───────────────┴───────────────┴───────────────┘      │
└─────────────────────────┬───────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                       runc                               │
│                   (容器运行时)                            │
└─────────────────────────┬───────────────────────────────┘
                          │
                          ▼
┌─────────────────────────────────────────────────────────┐
│                      Linux Kernel                         │
│                   (Linux 内核)                           │
└─────────────────────────────────────────────────────────┘

组件详解

组件 通俗解释 类比
Docker Client 命令行工具 餐厅的"前台接待"
Docker Daemon 后台守护进程 餐厅的"经理"
containerd 容器运行时 厨房的"调度员"
runc 容器启动器 厨房的"灶台"
Docker Registry 镜像仓库 餐厅的"食材库"

用户态 vs 内核态

什么是用户态和内核态?

想象一家医院:

  • 内核态 = 院长办公室,掌握医院所有资源(CPU、内存、磁盘)
  • 用户态 = 普通医生的诊室,不能直接访问手术室、药房

用户态的程序想用资源,必须通过系统调用请求内核帮忙。

┌─────────────────────────────────────────┐
│            用户空间 (User Space)          │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │ Docker  │  │   App   │  │  Shell  │ │
│  │ Client  │  │ Process │  │ Process │ │
│  └────┬────┘  └────┬────┘  └────┬────┘ │
│       │            │            │       │
└───────┼────────────┼────────────┼───────┘
        │            │            │
        ▼            ▼            ▼
┌─────────────────────────────────────────┐
│              系统调用接口                 │
│         (System Call Interface)          │
└─────────────────────┬───────────────────┘
                      │
                      ▼
┌─────────────────────────────────────────┐
│            内核空间 (Kernel Space)        │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │ Process │  │  Memory │  │  File   │ │
│  │Manager  │  │Manager  │  │ System  │ │
│  └─────────┘  └─────────┘  └─────────┘ │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │ Network │  │   I/O   │  │ Device  │ │
│  │ Stack  │  │Manager  │  │ Drivers │ │
│  └─────────┘  └─────────┘  └─────────┘ │
└─────────────────────────────────────────┘

用户态的特点:

  • 普通应用程序运行在这里
  • 不能直接访问硬件
  • 不能访问其他程序的内存
  • 必须通过系统调用请求内核帮忙

内核态的特点:

  • 操作系统内核运行在这里
  • 可以直接访问所有硬件
  • 可以访问所有内存
  • 拥有最高权限

Docker 的位置:

┌─────────────────────────────────────────┐
│            用户空间                       │
│  ┌─────────────────────────────────┐   │
│  │      Docker Client + Daemon      │   │
│  └─────────────────────────────────┘   │
└─────────────────────────────────────────┘
        │ (通过系统调用和内核交互)
        ▼
┌─────────────────────────────────────────┐
│            内核空间                       │
│  ┌─────────────────────────────────┐   │
│  │  Namespaces | Cgroups | Overlay │   │
│  └─────────────────────────────────┘   │
└─────────────────────────────────────────┘

Namespace(命名空间)

什么是 Namespace?

想象一下:一家酒店有很多房间(Namespace)。

  • 每个房间的人以为自己住的是"整栋楼"
  • 房间 A 的"301号"和房间 B 的"301号"是不同的人
  • 每个房间有独立的电视、空调、电话

Namespace 就是 Docker 的"隔离房间"! 每个容器以为自己是"整台服务器"。

六种 Namespace

Namespace 作用 通俗解释
PID 进程隔离 每个容器从 PID 1 开始
NET 网络隔离 每个容器有自己的 IP 地址
IPC 进程通信隔离 容器间不能互相通信
MNT 挂载隔离 每个容器有自己的文件系统
UTS 主机名隔离 每个容器有自己的 hostname
USER 用户隔离 容器内的 root 相当于宿主机的普通用户

查看容器的 Namespace

# 👀 查看运行中容器的 PID
docker inspect --format '{{.State.Pid}}' myapp

# 👀 查看该进程的所有 Namespace
ls -la /proc/$(docker inspect --format '{{.State.Pid}}' myapp)/ns/

输出示例:

total 0
lrwxrwxrwx 1 root root 0 Jun  2 12:00 cgroup -> /proc/12345/ns/cgroup
lrwxrwxrwx 1 root root 0 Jun  2 12:00 ipc -> /proc/12345/ns/ipc
lrwxrwxrwx 1 root root 0 Jun  2 12:00 mnt -> /proc/12345/ns/mnt
lrwxrwxrwx 1 root root 0 Jun  2 12:00 net -> /proc/12345/ns/net
lrwxrwxrwx 1 root root 0 Jun  2 12:00 pid -> /proc/12345/ns/pid
lrwxrwxrwx 1 root root 0 Jun  2 12:00 user -> /proc/12345/ns/user
lrwxrwxrwx 1 root root 0 Jun  2 12:00 uts -> /proc/12345/ns/uts

Cgroups(控制组)

什么是 Cgroups?

想象一下:公司财务给每个部门分配预算:

  • 研发部:最多用 100 万
  • 销售部:最多用 50 万
  • 市场部:最多用 30 万

每个部门只能在自己的预算内花钱,不能多用!

Cgroups 就是 Docker 的"预算管理"! 它限制每个容器使用的资源(CPU、内存、磁盘 I/O)。

Cgroups 版本

Cgroup Driver: systemd
Cgroup Version: 2
版本 通俗解释
v1 早期版本,每个资源类型独立 hierarchy
v2 统一 hierarchy,性能更好

Cgroups 资源限制

# 👀 查看容器的 Cgroup 信息
docker inspect myapp | grep -i cgroup

# 查看 CPU Cgroup
cat /sys/fs/cgroup/cpu/docker/<container-id>/cpu.cfs_quota_us

# 查看内存 Cgroup
cat /sys/fs/cgroup/memory/docker/<container-id>/memory.limit_in_bytes

常用资源限制

# ⚙️ 限制内存
docker run -d --name myapp --memory=512m nginx

# ⚙️ 限制 CPU
docker run -d --name myapp --cpus=1.5 nginx

# ⚙️ 限制 CPU 核数
docker run -d --name myapp --cpuset-cpus=0,1 nginx

# ⚙️ 限制 IO
docker run -d --name myapp --device-write-iops=/dev/sda:100 nginx

OverlayFS(叠加文件系统)

什么是 OverlayFS?

想象一下:你有两张透明塑料纸:

  • 底层纸:画了一个完整的圆
  • 顶层纸:画了一个三角形

叠加在一起,你看到的就是:圆上有个三角形!

OverlayFS 就是 Docker 的"叠加魔法"! 它把多个目录叠加成一个。

OverlayFS 结构

┌─────────────────────────────────────────┐
│           容器层 (Container Layer)       │
│        (writable, 写入的文件)            │
└─────────────────┬───────────────────────┘
                  │
┌─────────────────┴───────────────────────┐
│           镜像层 (Image Layer)           │
│      (lowerdir, 只读的镜像层)            │
│   ┌─────────┐ ┌─────────┐ ┌─────────┐   │
│   │ Layer 3 │ │ Layer 2 │ │ Layer 1 │   │
│   └─────────┘ └─────────┘ └─────────┘   │
└─────────────────────────────────────────┘

查看 OverlayFS 信息

# 👀 查看容器使用的文件系统
docker inspect myapp | grep -A 10 "GraphDriver"

# 输出示例:
# "GraphDriver": {
#     "Name": "overlayfs",
#     "Data": {
#         "LowerDir": "/var/lib/docker/overlay2/xxx/diff",
#         "UpperDir": "/var/lib/docker/overlay2/xxx/diff",
#         "MergedDir": "/var/lib/docker/overlay2/xxx/merged"
#     }
# }

systemd 与 Docker

什么是 systemd?

systemd 是 Linux 系统的"总管家",负责:

  • 启动/停止服务
  • 管理进程
  • 记录日志

Docker 作为系统服务,由 systemd 管理。

systemd 管理 Docker

# 👀 查看 Docker 服务状态
sudo systemctl status docker

# ⚙️ 启动 Docker
sudo systemctl start docker

# ⚙️ 停止 Docker
sudo systemctl stop docker

# ⚙️ 重启 Docker
sudo systemctl restart docker

# ⚙️ 设置开机启动
sudo systemctl enable docker

# ⚙️ 禁止开机启动
sudo systemctl disable docker

# 👀 查看 Docker 日志
sudo journalctl -u docker -f

Docker 服务文件

# 👀 查看 Docker 服务文件
cat /lib/systemd/system/docker.service

服务文件示例:

[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service containerd.service
Wants=network-online.target

[Service]
Type=notify
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=on-failure

[Install]
WantedBy=multi-user.target

字段解释:

字段 通俗解释
Description 服务描述
After 依赖的其他服务
ExecStart 启动命令
Restart 失败重启策略
WantedBy 开机启动级别

容器启动流程

用户输入命令
     │
     ▼
┌─────────────────┐
│ docker run      │
│ (Docker Client) │
└────────┬────────┘
         │
         │ API 调用
         ▼
┌─────────────────┐
│ dockerd         │
│ (Docker Daemon) │
└────────┬────────┘
         │
         │ 创建容器
         ▼
┌─────────────────┐
│ containerd     │
│ (容器运行时)    │
└────────┬────────┘
         │
         │ 创建容器
         ▼
┌─────────────────┐
│ runc           │
│ (启动容器)      │
└────────┬────────┘
         │
         │ 系统调用
         ▼
┌─────────────────┐
│ Linux Kernel    │
│ 创建 Namespace  │
│ 设置 Cgroups    │
│ 启动进程        │
└─────────────────┘

运维监控

监控命令

# 👀 查看容器资源使用
docker stats

# 👀 查看所有容器(包含停止的)
docker ps -a

# 👀 查看镜像
docker images

# 👀 查看磁盘使用
docker system df

# 👀 查看 Docker 磁盘使用详情
docker system df -v

监控脚本

#!/bin/bash

echo "=========================================="
echo "        Docker 监控报告"
echo "=========================================="
echo "时间: $(date)"
echo ""

echo "📊 【容器状态】"
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
echo ""

echo "💾 【资源使用】"
docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
echo ""

echo "💾 【磁盘使用】"
docker system df
echo "=========================================="

常见问题排查

问题 1:容器无法启动

现象: docker run 失败

排查步骤:

# 👀 查看 Docker 服务状态
sudo systemctl status docker

# 👀 查看 Docker 日志
sudo journalctl -u docker -f

# 👀 检查磁盘空间
df -h

# 👀 检查容器日志
docker logs myapp

解决方案:

  1. 重启 Docker
sudo systemctl restart docker
  1. 清理未使用的资源
docker system prune -a

问题 2:容器网络不通

现象: 容器无法访问外部网络

排查步骤:

# 👀 查看网络
docker network ls

# 👀 查看容器网络详情
docker inspect myapp | grep -A 20 "Networks"

# 👀 测试网络连通性
docker exec myapp ping google.com

解决方案:

  1. 创建新的网络
docker network create mynetwork
docker network connect mynetwork myapp
  1. 重启容器
docker restart myapp

问题 3:磁盘空间不足

现象: 无法创建容器或拉取镜像

排查步骤:

# 👀 查看磁盘使用
df -h

# 👀 查看 Docker 磁盘使用
docker system df

解决方案:

  1. 清理未使用的资源
docker system prune -a
  1. 清理镜像
docker image prune -a
  1. 清理卷
docker volume prune

问题 4:Swarm 节点不可用

现象: docker node ls 显示节点为 Down

排查步骤:

# 👀 查看节点状态
docker node ls

# 👀 查看节点详情
docker node inspect node2

解决方案:

  1. 检查节点网络
  2. 重启 Docker 服务
  3. 重新加入集群
# 在故障节点执行
docker swarm leave --force
docker swarm join --token xxx manager-ip:2377

总结

核心概念

概念 通俗解释
镜像 菜谱
容器 做好的菜
Namespace 隔离房间
Cgroups 资源预算
OverlayFS 叠加魔法
Swarm 厨师团队

运维黄金法则

  1. 监控资源使用 - 别让容器撑爆了
  2. 设置资源限制 - 给容器分配合理的预算
  3. 定期清理 - 删除不需要的镜像和容器
  4. 使用 Swarm - 生产环境必须用集群
  5. 查看日志 - 出问题先看日志

最后一句话总结:
Docker 就是"集装箱标准化",让应用部署变得简单。但背后是复杂的内核机制(Namespace、Cgroups、OverlayFS),理解这些才能更好地运维!


持续更新中… 如有问题或建议,欢迎交流讨论!

原创

Docker 生产环境运维指南(持续更新)

本文链接: Docker 生产环境运维指南(持续更新)

本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

评论交流

文章目录