Docker 全览

本文由四份 Docker 文档合并整理:工作原理、实战手册、源码 UML 建模、源码仓库关系与阅读指南。


一、架构概览

Docker 采用 客户端-服务端 (Client-Server) 架构:

Docker CLI (docker)  ──REST API──▶  Docker Daemon (dockerd)  ──▶  Containers
组件 说明
Docker Client (docker) CLI 客户端,用户交互入口,通过 REST API 与 daemon 通信
Docker Daemon (dockerd) 后台进程,管理镜像、容器、网络、卷等所有 Docker 对象
Registry 镜像仓库,负责镜像的存储与分发(默认 Docker Hub)
Image 只读模板,分层存储
Container 镜像的运行实例,隔离的进程环境
Docker Desktop 一站化应用,内含 daemon、client、Compose、Kubernetes 等

二、核心对象

1. 镜像 (Image)

2. 容器 (Container)


三、底层隔离技术

Docker 利用 Linux 内核特性实现隔离:

技术 作用
Namespaces 资源隔离:PID、NET、IPC、MNT、UTS、User 等命名空间,每个容器只看到自己的进程/网络/文件系统
Cgroups (Control Groups) 资源限制与优先级:限制 CPU、内存、磁盘 I/O 等
UnionFS (如 overlay2) 分层文件系统:将只读镜像层 + 可写容器层叠加为统一视图

四、网络与端口

端口映射与发布

Docker 不会自动为程序分配新端口。端口行为分两层:

方式 说明
-p 8080:80 手动映射,将容器 80 端口映射到宿主机 8080
-p 192.168.1.1:8080:80 绑定指定 IP
-p 8080:80/udp UDP 端口
不指定 端口完全隔离,仅同网络内其他容器可访问,外部无法访问
-P / --publish-all 自动映射,将镜像中 EXPOSE 声明的所有端口随机映射到宿主机高位端口(范围由 /proc/sys/net/ipv4/ip_local_port_range 决定,通常 32768-60999)

Docker 自动分配的是 IP 地址,不是端口

网络驱动类型

驱动 说明
bridge 默认网络驱动,单机容器间通信,容器连接到宿主机虚拟网桥
host 移除网络隔离,容器直接使用宿主机网络栈
none 完全隔离容器网络
overlay 跨多 Docker daemon 的 Swarm Overlay 网络(跨主机通信)
ipvlan 容器共享 MAC,独立 IP
macvlan 容器作为宿主机网络中的独立设备出现,可直接连接物理网络

常用操作

docker network ls                                         # 列表
docker network create my-net                             # 创建 bridge 网络
docker network create --ipv6 --subnet 10.0.0.0/24 my-net # 指定子网
docker network create -d overlay my-overlay              # 创建 overlay
docker network rm my-net                                 # 删除
docker network inspect my-net                            # 详情
docker network connect my-net container                  # 动态加入
docker network disconnect my-net container               # 断开
docker network prune                                     # 清理未使用的

共享网络栈

docker run --network container:redis ...   # 与指定容器共享网络命名空间

DNS 配置

docker run --dns 8.8.8.8 ...                # 指定 DNS
docker run --dns-search example.com ...     # DNS 搜索域
docker run --hostname myhost ...            # 主机名
docker run --add-host example.com:1.2.3.4 . # 添加 hosts 记录

自定义子网(daemon.json)

{
  "default-address-pools": [
    { "base": "172.17.0.0/16", "size": 24 }
  ]
}

五、数据存储

Docker 的存储分两层概念:

(1) 容器数据持久化

方式 管理方式 说明
Volume Docker 管理 存储在宿主机 /var/lib/docker/volumes/,生产首选
Bind Mount 宿主机路径 直接挂载宿主机任意路径到容器,开发时共享源码
tmpfs Mount 内存 存于内存,容器停止即丢失

Volume 命令:

docker volume create myvol                              # 创建
docker volume ls                                        # 列表
docker volume inspect myvol                             # 详情
docker volume rm myvol                                  # 删除
docker volume prune                                     # 清理未使用的匿名卷

挂载方式:

# --mount(推荐,更显式)
docker run --mount type=volume,src=myvol,dst=/app ...
docker run --mount type=bind,src=/host/path,dst=/app ...
docker run --mount type=tmpfs,dst=/tmp ...

# -v(简短)
docker run -v myvol:/app ...              # volume
docker run -v /host/path:/app ...         # bind mount

只读与选项:

docker run -v myvol:/app:ro ...                                 # 只读
docker run --mount src=myvol,dst=/app,readonly ...
docker run -v myvol:/app:volume-nocopy ...                      # 不复制已有内容

卷子目录挂载:

docker volume create logs
docker run --rm --mount src=logs,dst=/logs alpine mkdir -p /logs/app1 /logs/app2

docker run -d --name app1 \
  --mount src=logs,dst=/var/log/app1,volume-subpath=app1 app1:latest

备份与恢复:

# 备份
docker run --rm --volumes-from dbstore -v $(pwd):/backup \
    ubuntu tar cvf /backup/backup.tar /dbdata

# 恢复
docker run --rm --volumes-from dbstore2 -v $(pwd):/backup \
    ubuntu bash -c "cd /dbdata && tar xvf /backup/backup.tar --strip 1"

NFS / CIFS 卷:

# NFS
docker volume create --driver local \
  --opt type=nfs \
  --opt device=:/var/docker-nfs \
  --opt o=addr=10.0.0.10 \
  nfsvolume

# CIFS
docker volume create --driver local \
  --opt type=cifs \
  --opt device=//server/backup \
  --opt o=addr=server,username=user,password=pass,file_mode=0777,dir_mode=0777 \
  cifs-volume

(2) 镜像/容器层存储


六、容器 vs 虚拟机

虚拟机:每个 VM 有完整 OS + 内核 → 数 GB,启动慢
容器:共享宿主机内核,仅隔离进程+文件 → 数 MB,秒级启动

两者常结合使用:云环境中的 VM 上运行容器运行时,一台 VM 运行多个容器以提高资源利用率。

为什么 Linux 原生就能跑,macOS / Windows 需要 VM?

因为 Linux 的宿主内核本身就提供容器所需的全部机制:命名空间(Namespaces)隔离进程、cgroup 限制资源、overlayfs 做分层文件系统。dockerd 只是直接调用这些内核接口,所以 Linux 上原生运行、不需要任何中间层。

macOS 的内核是 Darwin(XNU),没有这些 Linux 容器原语,所以 Docker 必须先在一个 VM 里装好 Linux 内核,再让 dockerd 跑在 VM 内的 Linux 上。这层 VM 正是 Docker Desktop 存在的意义——也是它比 Linux 原生 Docker 重、关掉应用容器就停的原因。


七、核心工作流

Dockerfile ──build──▶  Image ──push/pull──▶ Registry (Docker Hub)
                             │
                        docker run
                             │
                             ▼
                        Container (运行实例)
                             │
                        docker compose
                             │
                             ▼
                    多容器服务编排

八、Dockerfile 核心指令速查

指令 用途 示例
FROM 指定基础镜像 FROM node:20-alpine
RUN 构建时执行命令 RUN apt-get update && apt-get install -y curl
COPY 复制文件到镜像 COPY . /app
ADD 复制+自动解压/远程下载 ADD https://example.com/file.tar.gz /tmp/
CMD 容器默认启动命令 CMD ["node", "app.js"]
ENTRYPOINT 容器入口点(与CMD配合) ENTRYPOINT ["nginx"] + CMD ["-g", "daemon off;"]
ENV 设置环境变量 ENV NODE_ENV=production
ARG 构建参数(仅构建时) ARG VERSION=1.0
WORKDIR 设置工作目录 WORKDIR /app
EXPOSE 声明端口(文档作用) EXPOSE 8080
VOLUME 声明挂载点 VOLUME /data
USER 切换用户 USER node
LABEL 添加元数据 LABEL version="1.0"
HEALTHCHECK 健康检查 HEALTHCHECK CMD curl -f http://localhost/
SHELL 指定 Shell SHELL ["/bin/bash", "-c"]
STOPSIGNAL 停止信号 STOPSIGNAL SIGTERM

九、多阶段构建(减小镜像体积)

# syntax=docker/dockerfile:1
FROM golang:1.21 AS builder
WORKDIR /app
COPY . .
RUN go build -o /server

FROM alpine:3.21
COPY --from=builder /server /server
CMD ["/server"]

复用公共阶段

FROM ubuntu AS base
RUN apt-get update && apt-get install -y shared-tooling

FROM base AS dev
RUN apt-get install -y dev-tooling

FROM base AS prod
COPY --from=build /app /app

十、RUN 挂载增强(BuildKit)

缓存挂载(加速下载)

# Go 模块缓存
RUN --mount=type=cache,target=/root/.cache/go-build go build ...

# apt 缓存
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    --mount=type=cache,target=/var/lib/apt,sharing=locked \
    apt-get update && apt-get install -y gcc

密钥挂载(不写入镜像)

RUN --mount=type=secret,id=aws,target=/root/.aws/credentials \
    aws s3 cp s3://... ...

# 构建时传入: docker buildx build --secret id=aws,src=$HOME/.aws/credentials .

SSH 挂载

RUN --mount=type=ssh \
    ssh -q -T git@gitlab.com

# 构建时: docker buildx build --ssh default=$SSH_AUTH_SOCK .

网络隔离

RUN --network=none pip install --find-links wheels mypackage   # 无网络
RUN --network=host ...                                          # 宿主机网络

十一、容器管理常用命令

生命周期

docker run -d --name myapp -p 8080:80 myimage    # 后台运行
docker run -it ubuntu bash                        # 交互式
docker run --rm alpine echo hello                 # 运行后自动删除
docker create --name myapp myimage                # 创建但不启动
docker stop/start/restart myapp                   # 停止/启动/重启
docker pause/unpause myapp                        # 暂停进程
docker rm myapp                                   # 删除容器
docker rm -f myapp                                # 强制删除
docker exec -it myapp bash                        # 进入运行中的容器

日志和调试

docker logs -f myapp                              # 跟踪日志
docker logs --tail 100 myapp                      # 最后100行
docker inspect myapp                              # 查看详情
docker stats                                      # 实时资源占用
docker top myapp                                  # 容器内进程
docker cp myapp:/path/file ./local                # 拷贝文件
docker diff myapp                                 # 查看文件变更
docker port myapp                                 # 端口映射

镜像管理

docker build -t myapp:v1 .                        # 构建
docker build --pull --no-cache -t myapp:v1 .      # 无缓存构建+拉取最新基础镜像
docker pull/push myimage:tag                      # 拉取/推送
docker images                                     # 列出镜像
docker rmi myimage:tag                            # 删除镜像
docker tag src target                             # 打标签
docker save myimage:tag -o myimage.tar            # 导出镜像
docker load -i myimage.tar                        # 导入镜像
docker image prune                                # 清理无用镜像
docker system prune -a                            # 全面清理

十二、资源限制

内存

docker run -m 512M ...                  # 硬限制 512M
docker run -m 512M --memory-swap -1 ... # 512M 内存,swap 不限
docker run -m 512M ...                  # 512M 内存 + 512M swap(默认 swap=2x)
docker run -m 512M --memory-swap 1G ... # 512M 内存 + 512M swap
docker run --memory-reservation 200M ...# 软限制
docker run -m 100M --oom-kill-disable . # 禁用 OOM Killer(需配合 -m)
docker run --memory-swappiness=0 ...    # 禁用 swap(0-100)

CPU

docker run --cpus=1.5 ...               # 最多 1.5 核
docker run --cpu-shares=512 ...         # 相对权重(默认 1024)
docker run --cpu-period=50000 --cpu-quota=25000 ...  # 50% CPU
docker run --cpuset-cpus="0-2" ...      # 绑定 CPU 核心
docker run --cpuset-mems="0-1" ...      # 绑定内存节点(NUMA)

IO

docker run --blkio-weight 300 ...                      # IO 权重 (10-1000)
docker run --blkio-weight-device "/dev/sda:200" ...    # 特定设备权重
docker run --device-read-bps /dev/sda:1mb ...          # 读速率限制
docker run --device-write-bps /dev/sda:1mb ...         # 写速率限制
docker run --device-read-iops /dev/sda:1000 ...        # IOPS 读限制
docker run --device-write-iops /dev/sda:1000 ...       # IOPS 写限制

十三、Docker Compose

基本结构

services:
  web:
    build: .
    ports:
      - "8000:5000"
    volumes:
      - .:/code
    environment:
      - REDIS_HOST=redis
    depends_on:
      - redis
    networks:
      - frontend

  redis:
    image: redis:alpine
    volumes:
      - redis-data:/data
    networks:
      - frontend

volumes:
  redis-data:

networks:
  frontend:

常用命令

docker compose up -d              # 后台启动
docker compose up --build         # 重建并启动
docker compose down               # 停止并移除
docker compose down -v            # 同时删除卷
docker compose logs -f            # 跟踪日志
docker compose logs -f web        # 指定服务
docker compose ps                 # 服务状态
docker compose exec web bash      # 进入服务容器
docker compose restart web        # 重启单个服务
docker compose pull               # 拉取最新镜像
docker compose config             # 验证/查看配置

使用外部卷

services:
  app:
    image: myapp
    volumes:
      - myvol:/data

volumes:
  myvol:
    external: true    # 引用已存在的卷

十四、Daemon 配置

配置文件位置:

OS 路径
Linux /etc/docker/daemon.json
Linux rootless ~/.config/docker/daemon.json
Windows C:\ProgramData\docker\config\daemon.json

常用配置:

{
  "data-root": "/mnt/docker-data",
  "default-address-pools": [
    { "base": "172.17.0.0/16", "size": 24 }
  ],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "dns": ["8.8.8.8", "1.1.1.1"],
  "registry-mirrors": ["https://mirror.example.com"]
}

手动启动 daemon

dockerd --debug \
  --tls=true \
  --tlscert=/var/docker/server.pem \
  --tlskey=/var/docker/serverkey.pem \
  --host tcp://192.168.59.3:2376

十五、权限与安全

# 完全权限(谨慎使用)
docker run --privileged ...

# 精细控制 capabilities
docker run --cap-add=NET_ADMIN ...
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE ...

# 挂载设备
docker run --device=/dev/snd:/dev/snd ...
docker run --device=/dev/sda:/dev/xvdc:r ...     # 只读(r)、写(w)、mknod(m)

# 只读根文件系统
docker run --read-only ...

# 添加附加组
docker run --group-add audio --group-add 777 ...

默认 Capabilities(可被 drop)

Capability 说明
CHOWN 修改文件 UID/GID
DAC_OVERRIDE 绕过文件权限检查
FSETID 修改文件时不清除 SUID/SGID
KILL 发信号绕过权限
NET_BIND_SERVICE 绑定 1024 以下端口
NET_RAW 使用 RAW/PACKET 套接字
SETGID 操纵进程 GID
SETUID 操纵进程 UID
SETFCAP 设置文件 capabilities
SETPCAP 修改进程 capabilities
SYS_CHROOT chroot

常用附加 Capabilities

Capability 说明
NET_ADMIN 网络配置操作
SYS_ADMIN 系统管理操作
SYS_PTRACE ptrace 调试
SYS_TIME 设置系统时钟
IPC_LOCK 锁定内存

退出码

退出码 含义
0 正常退出
125 Docker daemon 自身错误
126 容器命令无法执行
127 容器命令不存在
其他 容器内命令的退出码

十六、最佳实践

镜像构建

  1. 使用小型/受信基础镜像:优先 Alpine 或 Docker Official Images
  2. 多阶段构建:编译与运行分离,减小最终镜像体积
  3. 合并 RUN 指令 + 清理缓存:
    dockerfile RUN apt-get update && apt-get install -y --no-install-recommends \ curl ca-certificates \ && rm -rf /var/lib/apt/lists/*
  4. 使用 .dockerignore:排除 node_modules、.git、build 产物
  5. 非 root 运行:
    dockerfile RUN groupadd -r app && useradd --no-log-init -r -g app app USER app
  6. 固定基础镜像:FROM alpine:3.21 或进一步用 digest pinning
  7. 定期重建:docker build --pull 拉取最新安全补丁
  8. CI 中构建测试:利用 GitHub Actions 等自动化流程

指令使用

  1. CMD 用 exec 形式:CMD ["node", "app.js"]
  2. ENTRYPOINT + CMD:入口脚本 + 默认参数
  3. WORKDIR 用绝对路径:避免 cd && 模式
  4. 管道命令加 set -o pipefail:避免管道中错误被忽略
  5. 参数字母排序:便于维护和 review
  6. COPY 优于 ADD:ADD 仅用于远程下载/自动解压场景
  7. ENV 用于运行时变量,ARG 用于构建时:避免环境变量泄露到镜像

容器设计

  1. 一个容器一个职责:解耦应用,便于横向扩展
  2. 容器应为临时性:可随时销毁重建
  3. 健康检查:HEALTHCHECK 确保服务可用性
  4. 不安装多余软件包:减小体积和攻击面

Dockerfile 示例(综合最佳实践)

# syntax=docker/dockerfile:1
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN --mount=type=cache,target=/root/.npm \
    npm ci --production
COPY . .

FROM node:20-alpine
RUN addgroup -S app && adduser -S app -G app
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
USER app
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=3s \
    CMD wget -qO- http://localhost:3000/health || exit 1
CMD ["node", "dist/main.js"]

十七、容器环境变量

Docker 自动设置的 Linux 容器环境变量:

变量 值
HOME 基于 USER 的值
HOSTNAME 容器主机名(可覆盖)
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
TERM xterm(分配 TTY 时)

自定义环境变量:

docker run -e "MYVAR=value" ...                 # 直接设置
docker run -e MYVAR ...                         # 从宿主机传递
docker run --env-file .env ...                  # 从文件加载

十八、完整实战:用 Docker 运行 MySQL

用一个完整的 MySQL 示例串联前面的知识点,并与「正常安装的 MySQL」对照,展示 Docker 方式的差异。

启动(与常规安装对比)

常规安装方式:

# Debian/Ubuntu
apt install mysql-server
systemctl start mysql            # 作为系统服务启动
mysql -uroot -p                  # 本机客户端直接连接

Docker 方式:

# 拉取并启动 MySQL 8.0 容器
docker run -d \
  --name mysql8 \
  -e MYSQL_ROOT_PASSWORD=secret \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

差异点:

对比项 常规安装 Docker
启动 systemctl start mysql,随系统自启 docker run 一条命令,进程隔离在容器里
MySQL 监听 默认监听宿主机 127.0.0.1:3306 默认只在容器内监听,需 -p 3306:3306 才暴露到宿主机
数据目录 /var/lib/mysql /var/lib/mysql(容器内),配合 volume 持久化
客户端 宿主机自带 mysql 命令 宿主机通常没有,需 docker exec 进容器使用

使用 MySQL(两种连接方式)

方式一:进入容器执行(推荐,无需额外安装客户端)

docker exec -it mysql8 mysql -uroot -p
# 输入密码后进入 mysql> 提示符,之后的 SQL 操作与常规 MySQL 完全一致

注意:-i 是交互式输入,必须加上;不加 -t 则没有终端提示符。

方式二:宿主机客户端连接(需已映射端口)

mysql -h127.0.0.1 -P3306 -uroot -p

与常规 mysql -uroot -p 的区别:容器版必须显式指定主机和端口(容器不在默认的本地 socket 上)。

创建库与用户

docker exec -it mysql8 mysql -uroot -p
CREATE DATABASE appdb;
CREATE USER 'app'@'%' IDENTIFIED BY 'pass123';
GRANT ALL PRIVILEGES ON appdb.* TO 'app'@'%';
FLUSH PRIVILEGES;
EXIT;

从宿主机/应用连接

# 命令行
mysql -h127.0.0.1 -P3306 -uapp -pappdb
# 应用连接串(JDBC 示例)
jdbc:mysql://127.0.0.1:3306/appdb?user=app&password=pass123

数据持久化与备份

容器删除后数据仍在 mysql-data 卷里,重新 docker run 时挂载同一卷即可恢复。

# 备份(在容器内执行 mysqldump,输出到宿主机)
docker exec mysql8 sh -c 'exec mysqldump -uroot -p"$MYSQL_ROOT_PASSWORD" appdb' > backup.sql

停止与删除

docker stop mysql8                 # 停止
docker rm mysql8                   # 删除容器(命名卷 mysql-data 保留)
docker volume ls                   # 查看卷,含 mysql-data
docker volume rm mysql-data        # 确认不再需要时手动删除数据

十九、镜像仓库(Registry)与私有项目

镜像从哪里来

镜像:docker pull 时从 Registry 拉取,默认是 Docker Hub(docker.io)。国内常配置镜像加速器(registry-mirrors)中转。

Docker 软件本身:Linux 上从官方仓库 https://download.docker.com 安装(配置 apt/yum 源后 apt install docker-ce);macOS 则直接下载 Docker Desktop 安装包。

第一节架构概述中的 Registry 就是镜像来源(默认 Docker Hub),相关配置见「十四、Daemon 配置」的 registry-mirrors。

Registry 里不一定什么都有

Docker Hub 只包含公开的官方镜像与社区上传的镜像,很多私有或企业镜像并不在上面。想要什么镜像:

推送自己的项目(完整例子)

# 1. 构建镜像
docker build -t myapp:v1 .

# 2. 打标签(带上仓库地址前缀),再推送
docker tag myapp:v1 <registry>/<namespace>/myapp:v1
docker push <registry>/<namespace>/myapp:v1

# 3. 其他机器拉取
docker pull <registry>/<namespace>/myapp:v1

可选仓库:

类型 地址示例 说明
Docker Hub 私有仓库 docker.io/<username>/myapp 登录后创建 private repo
自建 registry 192.168.1.10:5000/myapp docker run -d -p 5000:5000 registry,局域网内可用
云仓库 阿里云 ACR / 腾讯云 TCR 国内访问快,支持私有与免密拉取
GitHub Packages ghcr.io/<user>/myapp 与 GitHub 仓库联动,需 token 认证
自建 registry 默认走 HTTP,若客户端需 HTTPS 可加 --insecure-registry 或配置 TLS。

二十、容器文件系统与数据存放位置

容器不是一台完整主机

容器不能完全当作一台「完整主机」来使用:

容器内目录结构

Volume 数据实际落在宿主机哪里

挂 volume 本质就是把数据放在宿主机磁盘上,但分两种形态:

类型 宿主机位置 说明
Volume(推荐) /var/lib/docker/volumes/<卷名>/_data Docker 托管,藏在 Docker 数据目录里;docker rm 删容器后卷仍保留,需 docker volume rm 才删数据;用 docker volume inspect 查真实位置。
Bind Mount 你指定的宿主路径 如 -v /home/brian/mysql:/var/lib/mysql,宿主机可直接看到/编辑;常用于开发时共享源码。

容器路径 vs 宿主路径(以 MySQL 为例)

docker run -d \
  --name mysql8 \
  -e MYSQL_ROOT_PASSWORD=secret \
  -p 3306:3306 \
  -v mysql-data:/var/lib/mysql \
  mysql:8.0

不挂 Volume 时数据何时丢


二十一、容器进程 vs 直接进程

容器本质是宿主机的隔离进程,所以 ps/top/htop 都能看到并操作容器内进程。但从进程管理工具角度看,两者有明显差异:

管理工具 直接启动的进程 Docker 容器进程
ps / top / htop 正常可见 可见(宿主 PID 视角)
systemctl 可管理(配 systemd unit) 不可见,挂在 dockerd → containerd → containerd-shim 进程树下,只能用 docker 命令管理
kill 按宿主 PID 发送信号 对普通进程有效;容器内 PID 1 可能忽略 SIGINT/SIGTERM 等默认信号,建议用 docker stop

二十二、源码架构 UML 建模

基于 moby/moby、docker/cli、containerd/containerd、opencontainers/runc、moby/buildkit 五个仓库源码梳理。
UML 标准依据:UML 2.5.1 (formal-17-12-05)。

一、组件图(Component Diagram)—— Docker 系统架构

diagram
图 1

二、部署图(Deployment Diagram)—— 物理部署拓扑

diagram
图 2

三、类图(Class Diagram)—— 核心域模型

3.1 dockerd 核心类图

diagram
图 3

3.2 graphdriver / overlay2 存储驱动类图

diagram
图 4

3.3 containerd 核心接口类图

diagram
图 5

3.4 BuildKit solver 核心类图

diagram
图 6

四、序列图(Sequence Diagram)—— 关键交互

4.1 docker run 完整调用链

diagram
图 7

4.2 docker build 调用链(BuildKit 路径)

diagram
图 8

4.3 容器退出与重启流程

diagram
图 9

五、状态机图(State Machine Diagram)—— 容器状态转移

diagram
图 10

六、用例图(Use Case Diagram)—— Docker 系统功能

diagram
图 11

七、包图(Package Diagram)—— 代码模块依赖关系

7.1 moby 核心包依赖

diagram
图 12

7.2 五仓库整体依赖关系

diagram
图 13

7.3 BuildKit 内部包依赖

diagram
图 14

八、通信图(Communication Diagram)—— 组件协作关系

8.1 镜像构建协作

diagram
图 15

8.2 容器运行协作

diagram
图 16

九、关键设计模式与架构决策总结

层级 仓库 核心抽象 设计模式
CLI docker/cli Cobra Command + DockerCli Command 模式、Facade
API Gateway moby/moby REST API Router Front Controller、Adapter
Engine moby/moby Daemon + ImageService interface Strategy(graphdriver vs containerd snapshotter)
Runtime containerd/containerd Plugin-based gRPC services Plugin 架构、桥接模式
Runtime opencontainers/runc libcontainer + State FSM 状态模式、Builder 模式(Spec -> Config)
Build moby/buildkit Vertex -> Edge -> Op -> Solver DAG 求解器、缓存模式、Pipeline
Storage moby/moby graphdriver.ProtoDriver 策略模式(overlay2/aufs/btrfs/devicemapper)
Storage containerd/containerd snapshots.Snapshotter + content.Store 内容寻址存储 (CAS)
Network moby/moby libnetwork.Controller Driver 模式(bridge/host/overlay/macvlan)

十、对照 UML 规范关键点说明

UML 元素 本图中的使用 规范依据 (UML 2.5.1)
组件图 各仓库独立组件(runc, containerd, dockerd, buildkit, cli) §11 Structured Classifiers
部署图 物理节点与软件部署映射(device/executable/artifact) §19 Deployments
类图 <<interface>> + 实现 ImageService, Driver, Vertex, Worker 等 §9 Classification
组合 *-- Container *-- State,State 随 Container 创建/销毁 §9.5.3 composite aggregation
聚合 o-- Solver 1..* Vertex, Solver 持有 Vertex 但 Vertex 可独立 §9.5.3 shared aggregation
序列图 alt/opt/loop docker run 的 alt(本地无镜像)、opt(AutoRemove) §17 Interactions CombinedFragment
状态机转移+守卫 [restartPolicy matches] [wait duration elapsed] §14 StateMachines
用例图 includes/extends compose 依赖 create/start/network/volume §18 UseCases
包图依赖(无环) 所有依赖均自上向下,无循环依赖 §12 Packages

二十三、源码仓库关系与阅读指南

本文档基于官方源码仓库,梳理 Docker 各组件之间的调用关系及推荐阅读顺序。

1. 仓库清单

仓库 本地路径 职责
moby/moby repos/moby Docker 引擎核心(daemon + API)
docker/cli repos/cli docker 命令行客户端
opencontainers/runc repos/runc OCI 标准容器运行时
moby/buildkit repos/buildkit 新一代镜像构建引擎
containerd/containerd repos/containerd 容器运行时管理器

2. 调用关系图

用户
 │
 ▼
┌──────────────┐     Unix Socket / TCP     ┌──────────────────┐
│  docker CLI  │ ────────────────────────▶ │  dockerd (moby)  │
│  (repos/cli) │     REST API              │  (repos/moby)    │
└──────────────┘                           └───────┬──────────┘
                                                   │
                          ┌────────────────────────┼────────────────────────┐
                          │ grpc                   │ grpc                   │ gRPC
                          ▼                        ▼                        ▼
                   ┌──────────────┐      ┌──────────────────┐      ┌──────────────┐
                   │  containerd   │      │    BuildKit      │      │  Registry   │
                   │  (containerd) │      │  (repos/buildkit)│      │  (外部)     │
                   └──────┬───────┘      └──────────────────┘      └──────────────┘
                          │ fork/exec + shim
                          ▼
                   ┌──────────────┐
                   │    runc      │
                   │ (repos/runc) │
                   └──────┬───────┘
                          │ Linux namespaces / cgroups
                          ▼
                   ┌──────────────┐
                   │  Container   │
                   │  Process     │
                   └──────────────┘

关键调用链:

docker run nginx
  → docker CLI 发送 POST /containers/create 到 dockerd
    → dockerd 调用 containerd gRPC API
      → containerd 创建 shim 进程
        → shim 调起 runc create + start
          → runc 设置 namespace / cgroup,exec 用户进程

3. 仓库关系详解

3.1 dockerd (moby) → containerd

3.2 containerd → runc

3.3 dockerd (moby) → BuildKit

3.4 docker CLI → dockerd

4. 推荐阅读顺序(由浅入深)

第一阶段:看懂 runc — 理解"容器到底是什么"

目标:理解 Linux 容器底层原理(namespace / cgroup / rootfs)

顺序 文件 内容
1 runc/main.go CLI 入口,urfave/cli 框架
2 runc/run.go runc run 命令,创建+启动容器
3 runc/create.go runc create,仅创建不运行
4 runc/start.go runc start,启动已创建的容器
5 runc/libcontainer/ 核心:Linux namespace 设置、cgroup 管理
6 runc/libcontainer/process_linux.go 容器进程启动逻辑
7 runc/libcontainer/nsenter/ C 代码 + Go,进入 namespace 的底层入口

runc 总共约 2 万行 Go 代码,是理解容器本质的最佳入口。

第二阶段:看懂 containerd — 理解"容器运行时管理器"

目标:理解 gRPC 服务架构、镜像管理、Snapshot 机制

顺序 文件 内容
1 containerd/core/ 核心接口定义,理解 containerd 的数据模型
2 containerd/core/containers/ Container metadata 增删改查
3 containerd/core/content/ 内容寻址存储(镜像层 blob)
4 containerd/core/snapshots/ 文件系统快照管理(overlay 层)
5 containerd/core/runtime/v2/ Runtime v2 接口,shim 管理
6 containerd/plugins/services/tasks/ Task 服务的 gRPC 实现
7 containerd/api/services/ Proto 定义(先看 tasks.proto, images.proto)
8 containerd/cmd/containerd/main.go Daemon 启动流程
9 containerd/cmd/containerd-shim-runc-v2/ Shim 进程实现

containerd 是 gRPC 服务化架构的典范,适合学习 Go 服务端编程。

第三阶段:看懂 dockerd (moby) — 理解"Docker 引擎全貌"

目标:理解 Docker 高阶功能(API、网络、卷、Swarm)

顺序 文件 内容
1 moby/cmd/dockerd/main.go Daemon 启动入口
2 moby/api/ REST API 定义(Swagger + types)
3 moby/client/ Go SDK,对 daemon API 的封装
4 moby/daemon/daemon.go 最核心:Daemon 结构体定义
5 moby/daemon/start.go 容器启动流程
6 moby/daemon/container/ 容器状态机(创建→启动→运行→停止→删除)
7 moby/daemon/images/ 镜像管理(pull/push/commit)
8 moby/daemon/containerd/ 与 containerd 的集成调用
9 moby/daemon/network/ 网络配置
10 moby/daemon/graphdriver/ 存储驱动(overlay2 等)
11 moby/daemon/cluster/ Swarm 集群模式

moby 是最大的仓库(12,700+ 文件),阅读时聚焦 daemon/ 和 api/ 即可。

第四阶段:看懂 docker CLI — 理解"命令行实现"

目标:理解 CLI 到 daemon 的调用模式

顺序 文件 内容
1 cli/cmd/docker/docker.go CLI 入口,cobra 框架
2 cli/cli/command/commands/commands.go 所有子命令注册
3 cli/cli/command/container/run.go docker run 实现
4 cli/cli/command/container/create.go docker create 实现
5 cli/cli/command/image/build.go docker build 实现
6 cli/cli/command/inspect/ docker inspect
7 cli/cli/command/formatter/ 格式化输出

cli 是理解 CLI + REST 客户端模式的好参考。

第五阶段:看懂 BuildKit — 理解"镜像构建引擎"

目标:理解 LLB(Low-Level Build)图、Dockerfile 解析、缓存机制

顺序 文件 内容
1 buildkit/cmd/buildkitd/main.go BuildKit daemon 入口
2 buildkit/frontend/dockerfile/ Dockerfile 前端(解析 → LLB 转换)
3 buildkit/frontend/dockerfile/parser/ Dockerfile 解析器
4 buildkit/frontend/dockerfile/dockerfile2llb/ Dockerfile → LLB 转换
5 buildkit/solver/ 构建图求解引擎
6 buildkit/source/ 源码拉取(git, http, image)
7 buildkit/cache/ 构建缓存管理
8 buildkit/exporter/ 构建产物导出
9 buildkit/worker/ 构建执行 worker

BuildKit 相对独立,可单独研读。

5. 关键文件速查表

想了解一个 docker run 全流程?

cli/cli/command/container/run.go        → CLI 发起命令
moby/client/container_create.go         → Go SDK 调用 API
moby/api/server/router/container/       → API Router
moby/daemon/create.go                   → daemon 创建容器
moby/daemon/start.go                    → daemon 启动容器
moby/daemon/containerd/image_*.go       → 与 containerd 交互
containerd/plugins/services/tasks/      → containerd Task 服务
containerd/core/runtime/v2/             → runtime v2 接口
containerd/cmd/containerd-shim-runc-v2/ → shim 进程
runc/create.go + runc/start.go          → OCI runtime 执行
runc/libcontainer/process_linux.go      → 进程启动

想了解 docker build 全流程?

cli/cli/command/image/build.go          → CLI 发起构建
moby/daemon/builder/builder.go          → daemon 构建接口
buildkit/frontend/dockerfile/           → Dockerfile 前端
buildkit/frontend/dockerfile/parser/    → 语法解析
buildkit/frontend/dockerfile/dockerfile2llb/ → 转为 LLB 图
buildkit/solver/                        → 图执行引擎
buildkit/source/local/                  → 读取 build context
buildkit/cache/                         → 缓存管理
buildkit/exporter/                      → 导出镜像层

6. 各仓库代码规模

仓库 文件数(估算) 语言 核心抽象
moby ~12,700 Go daemon/ — 引擎核心
cli ~4,000 Go cli/command/ — 子命令
containerd ~6,500 Go core/ 接口 + plugins/ 实现
buildkit ~7,500 Go solver/ + frontend/
runc ~500 Go + C libcontainer/ — 容器运行时

7. 调试技巧

dockerd 调试模式

dockerd --debug                           # 开启调试日志
dockerd --log-level=debug                 # 同上

containerd 调试

ctr --debug tasks ls                      # ctr 调试模式

手动调 runc

# 创建 rootfs
mkdir -p /tmp/mycontainer/rootfs
docker export $(docker create alpine) | tar -C /tmp/mycontainer/rootfs -xf -

# 生成 OCI spec
runc spec                                    # 生成 config.json
cd /tmp/mycontainer && runc run mycontainer  # 启动容器

BuildKit 调试

buildkitd --debug
buildctl --debug build ...

8. 标准与规范

标准 对应仓库 说明
OCI Image Spec 全部 镜像格式规范
OCI Runtime Spec runc 容器运行时配置规范
OCI Distribution Spec containerd / moby 镜像仓库 API 规范
CRI (K8s) containerd/plugins/cri/ Kubernetes 容器运行时接口
Compose Spec cli/cli/compose/ 多容器编排文件格式