Docker 教程
本文档系统介绍 Docker 容器技术的核心概念、安装配置、镜像构建、容器管理、数据持久化、网络配置、容器编排(Docker Compose)、监控日志及安全实践,帮助用户掌握容器化应用的完整开发运维流程。
本文档涵盖 Docker 基础概念、镜像与容器操作、Dockerfile 定制、数据卷与网络、Docker Compose 编排、监控告警、私有仓库搭建等完整知识体系。
📚 相关文档:
💡 创作不易,请点个收藏关注!
目录
- 一、Docker 简介
- 二、Docker 安装
- 三、Docker 基础命令
- 四、Dockerfile 镜像定制
- 五、数据管理与网络
- 六、Docker Compose 容器编排
- 七、容器监控与日志
- 八、私有镜像仓库
- 九、容器安全
- 十、Docker 进阶特性
- 十一、Docker Swarm 集群编排
- 十二、镜像优化与安全扫描
- 十三、CI/CD 集成
- 十四、调试与排障
一、Docker 简介
1.1、什么是 Docker
Docker 是一个开源的应用容器引擎,让开发者可以打包应用及其依赖到一个可移植的容器中,然后发布到任何流行的 Linux 或 Windows 机器上。容器使用沙箱机制,相互隔离且开销极低。
1.2、Docker 能做什么
| 应用场景 | 说明 |
|---|---|
| 开发环境 | 保持开发、测试、生产环境一致,消除"在我机器上运行正常"的问题 |
| 微服务架构 | 轻量级、松耦合、可扩展的容器化服务部署 |
| CI/CD | 持续集成和持续部署,提高开发和交付效率 |
| 云计算 | 弹性、可扩展的云原生应用平台 |
| 多租户 | 资源隔离,提高安全性和资源利用率 |
1.3、Docker vs 虚拟机
| 对比项 | Docker 容器 | 传统虚拟机 |
|---|---|---|
| 资源利用率 | 共享宿主机内核,轻量高效 | 运行完整 OS,资源开销大 |
| 启动速度 | 秒级启动 | 分钟级启动 |
| 镜像大小 | MB 级(仅应用+依赖) | GB 级(完整操作系统) |
| 隔离性 | 进程级隔离 | 系统级强隔离 |
| 可移植性 | 跨平台运行 | 依赖特定虚拟化平台 |
Docker vs 虚拟机架构对比
graph TB
subgraph VM["传统虚拟机架构"]
VM_H["Hypervisor / 虚拟机管理器"]
subgraph VM1["虚拟机 1"]
VM1_OS["Guest OS (Linux/Windows)"]
VM1_App1["App A"]
VM1_App2["App B"]
end
subgraph VM2["虚拟机 2"]
VM2_OS["Guest OS (Linux/Windows)"]
VM2_App["App C"]
end
VM_H --> VM1_OS
VM_H --> VM2_OS
VM1_OS --> VM1_App1
VM1_OS --> VM1_App2
VM2_OS --> VM2_App
end
subgraph Docker["Docker 容器架构"]
Docker_H["Docker Engine (守护进程)"]
subgraph C1["容器 1 (nginx)"]
C1_Lib["依赖库"]
C1_App["nginx"]
end
subgraph C2["容器 2 (mysql)"]
C2_Lib["依赖库"]
C2_App["mysql"]
end
Docker_H --> C1
Docker_H --> C2
end
Host["宿主机 (Linux/Windows)"]
Host --> VM_H
Host --> Docker_H
style VM fill:#ffcccc
style Docker fill:#ccffcc
style Host fill:#cce5ff
核心区别:
- 虚拟机:每个虚拟机运行完整的操作系统(Guest OS),需要独立的内核,占用大量资源
- 容器:共享宿主机内核,容器内只包含应用和依赖库,更加轻量
1.4、Docker 架构
| 组件 | 说明 |
|---|---|
| Docker 引擎 | 由守护进程(daemon)和客户端(CLI)组成,负责容器的创建、运行和管理 |
| Docker 镜像 | 只读模板,包含应用及其依赖,可分层构建和复用 |
| Docker 容器 | 镜像的运行实例,提供隔离的进程、网络和存储空间 |
| Docker Registry | 镜像仓库服务,Docker Hub 是官方公共仓库 |
| Docker 网络 | 容器通信机制,支持 bridge/host/overlay 等网络模式 |
| Docker 存储 | 数据持久化机制,支持 volume/bind mount/tmpfs |
Docker 核心架构图
graph TB
subgraph Client["Docker 客户端 (CLI)"]
CLI["docker CLI<br/>用户命令"]
end
subgraph Host["Docker 宿主机"]
subgraph Engine["Docker Engine"]
API["REST API<br/>接口层"]
Daemon["Docker Daemon<br/>守护进程"]
subgraph Components["核心组件"]
Builder["Builder<br/>镜像构建"]
Container["Containerd<br/>容器运行时"]
Network["Network<br/>网络管理"]
Volume["Volume<br/>存储管理"]
Plugin["Plugin<br/>插件管理"]
end
API --> Daemon
Daemon --> Components
end
subgraph Containers["运行的容器"]
C1["容器 1"]
C2["容器 2"]
Cn["容器 N"]
end
subgraph Images["本地镜像"]
I1["镜像层 1"]
I2["镜像层 2"]
I3["镜像层 3"]
end
Daemon -. "创建/管理" .-> Containers
Daemon -. "读取" .-> Images
end
subgraph Registry["镜像仓库 (Registry)"]
Hub["Docker Hub<br/>公共仓库"]
Private["私有仓库<br/>Harbor/Registry"]
end
CLI -->|"命令"| API
Images <-. "拉取/推送" .-> Hub
Images <-. "拉取/推送" .-> Private
style Client fill:#e3f2fd
style Host fill:#fff3e0
style Registry fill:#f3e5f5
style Daemon fill:#ffcdd2
工作流程:
- 用户通过 CLI 发送命令(如
docker run)- CLI 通过 REST API 与 Daemon 通信
- Daemon 调用 Containerd 管理容器生命周期
- 如本地无镜像,从 Registry 拉取
- 容器运行时创建隔离的进程、网络、存储空间
二、Docker 安装
2.1、Ubuntu 安装
Docker 支持 Linux、Windows 和 macOS。以下是在 Ubuntu 上安装的步骤:
- 更新系统软件包列表:
sudo apt-get update
- 安装Docker的依赖包:
sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
gnupg \
lsb-release
- 添加Docker的APT仓库:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=amd64 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
- 更新APT仓库:
sudo apt-get update
- 安装Docker Engine:
sudo apt-get install docker-ce docker-ce-cli containerd.io
- 验证Docker是否安装成功:
sudo docker run hello-world
- 启动Docker服务:
sudo systemctl start docker
- 设置Docker开机自启动:
sudo systemctl enable docker
- 配置Docker镜像加速器(可选):
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://<your-mirror-url>"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker
- 添加Docker用户组(可选):
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
2.2、镜像加速配置
国内用户建议配置镜像加速器以提高下载速度:
| 镜像源 | 地址 |
|---|---|
| 阿里云 | https://<your-id>.mirror.aliyuncs.com |
| 网易云 | https://hub-mirror.c.163.com |
| 腾讯云 | https://mirror.ccs.tencentyun.com |
| DaoCloud | https://docker.m.daocloud.io |
| 中科大 | https://docker.mirrors.ustc.edu.cn |
配置方法(以阿里云为例):
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
2.3、免 sudo 配置
将用户加入 docker 组,避免每次执行 docker 命令都需要 sudo:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker # 重新加载组权限
docker run hello-world # 验证
三、Docker 基础命令
3.1、镜像管理
| 命令 | 说明 | 示例 |
|---|---|---|
docker pull | 拉取镜像 | docker pull nginx:latest |
docker images | 列出本地镜像 | docker images |
docker rmi | 删除镜像 | docker rmi nginx:latest |
docker build | 构建镜像 | docker build -t myapp:1.0 . |
docker tag | 标记镜像 | docker tag nginx myregistry/nginx:v1 |
docker push | 推送镜像 | docker push myregistry/nginx:v1 |
3.2、容器管理
| 命令 | 说明 | 示例 |
|---|---|---|
docker run | 创建并启动容器 | docker run -d -p 80:80 nginx |
docker ps | 列出运行中容器 | docker ps -a |
docker start/stop/restart | 启停容器 | docker stop container_id |
docker rm | 删除容器 | docker rm -f container_id |
docker exec | 执行容器内命令 | docker exec -it container_id bash |
docker logs | 查看容器日志 | docker logs -f container_id |
docker inspect | 查看容器详情 | docker inspect container_id |
3.3、常用命令速查
# 清理无用资源
docker system prune # 清理未使用的数据
docker volume prune # 清理未使用的卷
docker image prune # 清理未使用的镜像
# 查看资源占用
docker system df # 磁盘使用情况
docker stats # 实时资源监控
# 容器操作技巧
docker cp container:/path/to/file . # 复制文件到本地
docker top container_id # 查看容器进程
docker port container_id # 查看端口映射
四、Dockerfile 镜像定制
Dockerfile 工作流程
graph LR
subgraph Build["镜像构建过程"]
DF["Dockerfile<br/>构建文件"] -->|"docker build"| Layer["镜像层<br/>Layer 1, 2, 3..."]
Layer -->|"叠加"| Image["最终镜像<br/>Image"]
end
subgraph Dockerfile["Dockerfile 指令顺序"]
A["FROM<br/>基础镜像"] --> B["MAINTAINER<br/>维护者"]
B --> C["RUN<br/>执行命令"]
C --> D["COPY/ADD<br/>复制文件"]
D --> E["ENV<br/>环境变量"]
E --> F["EXPOSE<br/>端口声明"]
F --> G["VOLUME<br/>数据卷"]
G --> H["WORKDIR<br/>工作目录"]
H --> I["USER<br/>用户"]
I --> J["CMD/ENTRYPOINT<br/>启动命令"]
end
subgraph Lifecycle["镜像与容器"]
Image -->|"docker run"| Container["容器<br/>Container"]
Container -->|"docker commit"| Image2["新镜像"]
end
style Build fill:#e8f5e9
style Dockerfile fill:#fff3e0
style Lifecycle fill:#e3f2fd
Dockerfile 指令执行顺序说明:
- 指令按从上到下顺序执行
- 每条指令创建一个新的镜像层
- 前面的层会被后面的层覆盖
- 频繁变化的指令(如 COPY、RUN)放在后面,优化构建缓存
4.1、Dockerfile 指令
Dockerfile是一个文本文件,其中包含了用于构建Docker镜像的指令。以下是一些常用的Dockerfile指令:
-
FROM:指定基础镜像。
- 作用:基于某个镜像构建新的镜像,即指定基础镜像。
- 格式:
FROM <image>[:<tag>],其中<image>是镜像名称,<tag>是镜像标签。
-
MAINTAINER:指定维护者信息。
- 作用:指定镜像的维护者信息。
- 格式:
MAINTAINER <name> <email>,其中<name>是维护者名称,<email>是维护者邮箱。
-
RUN:执行命令。
- 作用:在构建镜像时执行命令。
- 格式:
RUN <command>,其中<command>是要执行的shell命令。
-
CMD:容器启动时执行的命令。
- 作用:指定容器启动时执行的命令。
- 格式:
CMD ["executable","param1","param2"],其中executable是要执行的命令,param1和param2是命令的参数。
-
ENTRYPOINT:容器启动时执行的命令。
- 作用:指定容器启动时执行的主命令。
- 格式:
ENTRYPOINT ["executable","param1","param2"],其中executable是要执行的命令,param1和param2是命令的参数。
-
COPY:复制文件到镜像中。
- 作用:将本地文件或目录复制到镜像中。
- 格式:
COPY <src> <dst>,其中<src>是本地文件或目录的路径,<dst>是镜像中的目标路径。
-
ADD:复制文件到镜像中,并自动处理URL和解压tar文件。
- 作用:将本地文件或目录复制到镜像中,并自动处理URL和解压tar文件。
- 格式:
ADD <src> <dst>,其中<src>是本地文件或目录的路径,<dst>是镜像中的目标路径。
-
ENV:设置环境变量。
- 作用:设置环境变量。
- 格式:
ENV <key>=<value>,其中<key>是环境变量的名称,<value>是环境变量的值。
-
EXPOSE:声明容器监听的端口。
- 作用:声明容器监听的端口。
- 格式:
EXPOSE <port> [<port>/<protocol>...],其中<port>是端口号,<protocol>是协议(如tcp、udp)。
-
VOLUME:声明容器挂载的卷。
- 作用:声明容器挂载的卷。
- 格式:
VOLUME ["/data"],其中/data是卷的路径。
-
WORKDIR:设置工作目录。
- 作用:设置工作目录。
- 格式:
WORKDIR /path/to/workdir,其中/path/to/workdir是工作目录的路径。后续指令(如 COPY、RUN)在此目录下执行。
-
USER:设置运行命令的用户。
- 作用:设置运行命令的用户。
- 格式:
USER <user>[:<group>],其中<user>是用户名,<group>是组名。
-
ONBUILD:为镜像添加触发器。
- 作用:为镜像添加触发器,当该镜像作为其他镜像的基础镜像时,触发器会被执行。
- 格式:
ONBUILD <INSTRUCTION>,其中<INSTRUCTION>是要执行的指令。
-
ARG:定义构建时的变量,构建时通过
--build-arg传递。- 作用:定义构建时的变量,构建时通过
--build-arg传递。 - 格式:
ARG <name>[=<default>],其中<name>是变量名,<default>是默认值。
- 作用:定义构建时的变量,构建时通过
4.2、镜像构建流程
镜像定制是指通过修改基础镜像,添加自定义的配置、软件包、环境变量等,生成新的镜像。
定制镜像的步骤如下:
- 创建一个Dockerfile文件,其中包含定制镜像所需的指令。
- 使用
docker build命令构建镜像,指定Dockerfile文件和构建上下文路径。 - 使用
docker images命令查看生成的镜像。 - 使用
docker run命令运行镜像,启动容器。 - 使用
docker commit命令将容器保存为新的镜像。 - 使用
docker push命令将镜像推送到Docker Hub或其他镜像仓库。 - 使用
docker pull命令从镜像仓库拉取镜像。
4.3、实战案例:Redis 镜像
4.3.1、编写 Dockerfile
以下是一个简单的Redis镜像定制的Dockerfile示例:
# 使用官方的Redis镜像作为基础镜像
FROM redis
# 设置环境变量
ENV REDIS_PASSWORD=mysecret
# 复制自定义的配置文件到镜像中
COPY redis.conf /usr/local/etc/redis/redis.conf
# 暴露Redis默认端口
EXPOSE 6379
# 容器启动时执行的命令
CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]
4.3.2、构建镜像
使用以下命令构建镜像:
docker build -t my-redis .
其中,-t参数指定镜像的名称和标签,.表示构建上下文路径。
五、数据管理与网络
5.1、数据卷(Volume)
Docker提供了两种数据管理方式:数据卷(Volumes)和绑定挂载(Bind mounts)。
Docker 存储类型对比
graph TB
subgraph Volumes["数据卷 (Volume)"]
V1["Docker 管理<br/>/var/lib/docker/volumes/"]
V2["容器 A"]
V3["容器 B"]
V4["持久化数据<br/>独立于容器生命周期"]
V1 --> V2
V1 --> V3
V2 -. "共享访问".-> V1
V3 -. "共享访问".-> V1
V1 --> V4
end
subgraph BindMount["绑定挂载 (Bind Mount)"]
B1["宿主机目录<br/>/home/user/data"]
B2["容器内目录<br/>/app/data"]
B1 --> B2
B3["直接访问宿主机文件"]
end
subgraph Tmpfs["tmpfs (内存存储)"]
T1["内存<br/>/dev/shm"]
T2["容器内目录<br/>/app/secrets"]
T1 --> T2
T3["数据不持久化<br/>高性能敏感数据"]
end
Host["宿主机文件系统"]
style Volumes fill:#e8f5e9
style BindMount fill:#fff3e0
style Tmpfs fill:#fce4ec
| 存储类型 | 存储位置 | 生命周期 | 性能 | 适用场景 |
|---|---|---|---|---|
| Volume | Docker 管理目录 | 独立于容器,可持久化 | 高 | 生产环境数据持久化 |
| Bind Mount | 宿主机任意路径 | 依赖宿主机 | 高 | 开发调试,访问宿主机文件 |
| tmpfs | 内存中 | 随容器删除 | 最高 | 敏感数据,临时缓存 |
5.1.1、创建和管理数据卷
数据卷是Docker中的一种特殊类型的存储,它可以在容器之间共享,并且在容器停止后仍然存在。数据卷可以用于存储持久化数据,也可以用于在容器之间共享数据。
- 创建数据卷:
docker volume create my_volume
- 查看数据卷:
docker volume ls
- 在容器中操作数据卷:
docker run -v my_volume:/data my_image
- 删除数据卷:
docker volume rm my_volume
5.1.2、绑定挂载(Bind Mount)
绑定挂载是将宿主机上的文件或目录挂载到容器中,类似于Linux中的mount命令。绑定挂载可以用于在容器中访问宿主机上的文件或目录,也可以用于在容器中存储数据。
- 在容器中操作绑定挂载:
docker run -v /path/on/host:/path/in/container my_image
其中,/path/on/host是宿主机上的路径,/path/in/container是容器中的路径。
- 删除绑定挂载:
docker rm -v my_container
5.2、数据备份与迁移
5.2.1、备份数据
可以使用docker export命令将容器的文件系统导出为tar文件,从而实现数据的备份。
docker export my_container > my_container_backup.tar
5.2.2、恢复数据
可以使用docker import命令将tar文件导入为新的镜像,从而实现数据的恢复。
docker import my_container_backup.tar my_image
5.2.3、迁移数据
可以使用docker save命令将镜像保存为tar文件,从而实现数据的迁移。
docker save my_image > my_image.tar
可以使用docker load命令将tar文件加载为镜像,从而实现数据的迁移。
docker load < my_image.tar
5.3、Docker 网络
Docker提供了多种网络模式,包括bridge、host、overlay等。默认情况下,Docker使用bridge网络模式,每个容器都会分配一个独立的IP地址。
- 查看网络列表:
docker network ls
- 创建自定义网络:
docker network create my_network
- 在容器中使用自定义网络:
docker run --network=my_network my_image
- 删除网络:
docker network rm my_network
5.3.1、同一宿主机容器通信
在同一宿主机上的容器之间,可以通过容器的IP地址或容器名进行通信。例如,如果容器A的IP地址是172.17.0.2,容器B的IP地址是172.17.0.3,那么容器A可以通过172.17.0.3或containerB与容器B进行通信。
默认桥接网络(Bridge) Docker 默认创建名为 bridge 的网络,所有容器自动加入该网络,但只能通过 IP 地址通信。容器无法通过名称通信。
操作步骤:
# 运行两个容器(自动加入默认桥接网络)
docker run -d --name web nginx
docker run -it --name client alpine
# 进入 client 容器测试通信
docker exec -it client sh
ping 172.17.0.2 # 替换为 web 容器的实际IP
curl http://172.17.0.2
自定义网络 创建自定义网络,并指定容器加入该网络,可以解决容器间通过容器名通信的问题。
优势:
- 容器可以通过容器名进行通信,无需知道对方的IP地址。
- 容器可以加入多个网络,实现更复杂的网络拓扑。
- 自动DNS解析,容器可以通过容器名进行通信。
操作步骤:
# 1. 创建自定义网络
docker network create my_network
# 2. 将容器加入同一网络
docker run -d --name web --network my_network nginx
docker run -it --name client --network my_network alpine
# 3. 测试名称解析
docker exec -it client ping web # 直接使用容器名
curl http://web
容器直连(--link) 通过 --link 参数建立单向通信(已过时,仅适用于旧版 Docker),被链接容器需先启动。仅适用于默认桥接网络。
操作步骤:
docker run -d --name mysql mysql:5.7
docker run --link mysql:db --name app myapp
# 在 app 容器中可通过别名访问
ping db
curl http://db
共享网络命名空间(--network=container) 将容器加入另一个容器的网络命名空间,实现容器间共享网络栈。Sidecar 模式(日志收集/监控代理)。需要零延迟通信的场景。
操作步骤:
# 1. 启动主容器
docker run -d --name web nginx
# 2. 启动副容器共享其网络
docker run -it --network container:web --name monitor alpine
# 在 monitor 容器中访问 web 服务
curl http://localhost
Host网络(--network=host) 将容器加入宿主机的网络命名空间,容器与宿主机共享网络栈。容器没有独立的网络栈,无法与其他容器通信。容器内服务监听端口与宿主机端口相同。
操作步骤:
# 容器1 暴露端口
docker run -d --network host --name web nginx
# 容器2 访问服务
docker run --network host --name client curl http://localhost
端口映射穿透(-p参数) 将宿主机的端口映射到容器的端口,实现容器与宿主机之间的通信。容器内服务监听端口与宿主机端口不同。
操作步骤:
# 容器暴露端口
docker run -d -p 8080:80 --name web nginx
# 其他容器通过宿主机IP访问
curl http://宿主机IP:8080
选择建议:
| 场景 | 网络模式 | 特点 |
|---|---|---|
| 临时测试 | 默认桥接网络 | 快速启动,无需配置 |
| 多容器通信 | 自定义网络 | 容器名通信,可加入多个网络 |
| 单向通信 | --link参数 | 已过时,仅适用于旧版 Docker |
| 监控/日志代理 | 共享网络命名空间 --network=container | Sidecar 模式,零延迟通信 |
| 高性能需求 | Host 网络模式 --network=host | 无NAT损耗,但牺牲安全性 |
Docker 网络模式对比图
graph TB
subgraph Host["宿主机 (Host)"]
subgraph Bridge["Bridge 网络"]
C1["容器 1<br/>nginx"]
C2["容器 2<br/>mysql"]
end
subgraph Host_Network["Host 网络"]
C3["容器 3<br/>直接使用宿主机网络"]
end
subgraph Custom["自定义网络"]
C4["容器 4"]
C5["容器 5"]
C4 <--> C5
end
subgraph Container_Network["共享网络 (container:)"]
C6["主容器<br/>web"]
C7["副容器<br/>monitor<br/>共享网络栈"]
end
end
External["外部网络"]
Internet["互联网"]
External -->|"NAT"| Bridge
External -->|"直接访问"| Host_Network
C1 <-->|"Docker DNS"| C2
style Bridge fill:#e3f2fd
style Host_Network fill:#fff3e0
style Custom fill:#e8f5e9
style Container_Network fill:#fce4ec
5.3.2、跨主机容器通信
我需要考虑不同跨主机通信的技术方案。常见的包括Overlay网络(如Docker Swarm)、第三方网络插件(如Calico、Flannel)、VPN隧道、云服务商的内网方案以及API网关或服务网格。每种方案都有其特定的使用场景和配置步骤。
对于每个方案,我需要解释其工作原理,例如Overlay网络如何通过VXLAN封装数据包实现跨主机通信,或者Calico如何利用BGP协议进行路由。然后提供具体的操作步骤,比如如何创建Docker Swarm集群,或如何安装和配置Calico。同时,要指出各个方案的优缺点,例如Overlay网络可能简单易用但性能有损耗,而Calico适合大规模集群但配置复杂。
此外,用户可能关心实际应用中的选择建议,因此需要在最后给出一个对比表格,列出不同方案的特点和适用场景,帮助用户根据具体需求做出决策。例如,小规模部署可能适合Overlay网络或云服务内网,而大规模企业环境可能需要Calico或服务网格。
Overlay网络(如Docker Swarm原生方案) Docker Swarm原生支持Overlay网络,通过VXLAN封装数据包实现跨主机通信,实现跨主机虚拟网络。适用于小规模部署。
操作步骤:
- 创建Swarm集群
# 主机1(Manager节点)
docker swarm init --advertise-addr <主机1_IP>
# 主机2(Worker节点)
docker swarm join --token <SWARM_TOKEN> <主机1_IP>:2377
- 创建Overlay网络
docker network create --driver overlay my_overlay
- 启动容器加入网络
docker service create --network my_overlay --name web nginx
优点: Docker 原生支持,无需第三方工具。
缺点: 适用于中小规模集群,性能有隧道开销。
Calico + BGP 路由(企业级方案) Calico 是一款开源的网络和网络策略解决方案,适用于大规模集群。通过BGP协议实现跨主机路由,性能优异。
操作步骤:
- 安装Calico
# 所有主机安装 Calico
curl -O -L https://github.com/projectcalico/calico/releases/download/v3.24.5/calicoctl-linux-amd64
chmod +x calicoctl
sudo mv calicoctl /usr/local/bin/
- 配置BGP路由
# 创建Calico配置文件 calico-config.yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
name: default-ipv4-ippool
spec:
logSeverityScreen: Info
nodeToNodeMeshEnabled: true
- 创建 Calico IP 池
calicoctl apply -f calico-config.yaml
- 启动容器加入网络
docker network create --driver calico --config-only my_calico
docker run -it --network my_calico --name client alpine
- 配置网络策略(可选)
# 创建网络策略
calicoctl apply -f network-policy.yaml
优点: 性能优异,适用于大规模集群,支持网络策略。
缺点: 配置复杂,需要额外安装Calico工具。
API 网关/Nginx 反向代理(微服务架构) 适用于微服务架构,通过API网关或Nginx反向代理实现跨主机通信。
操作步骤:
- 部署API网关/Nginx
# 部署API网关或Nginx
docker run -d --name api-gateway nginx
- 配置路由规则
# Nginx 配置(位于独立主机)
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://<容器主机1_IP>:8080;
}
location /v2/ {
proxy_pass http://<容器主机2_IP>:3000;
}
}
优点: 灵活,适用于微服务架构。 缺点: 需要额外部署API网关/Nginx,配置复杂。
六、Docker Compose 容器编排
6.1、Docker Compose 简介[/kəmˈpoʊz/]
Docker Compose 是一个用于定义和运行多容器Docker应用程序的工具。通过一个YAML文件,可以定义多个容器及其配置,然后使用一条命令即可启动所有容器。
Docker Compose 工作原理
graph TB
subgraph YAML["docker-compose.yml<br/>配置文件"]
Y1["services:<br/>定义服务"]
Y2["networks:<br/>定义网络"]
Y3["volumes:<br/>定义数据卷"]
end
subgraph Compose["Docker Compose<br/>编排工具"]
C1["docker-compose up"]
C2["解析 YAML"]
C3["创建网络"]
C4["创建数据卷"]
C5["拉取/构建镜像"]
C6["启动容器"]
end
subgraph Result["最终结果"]
R1["Web 服务<br/>nginx:80"]
R2["API 服务<br/>nodejs:3000"]
R3["数据库<br/>mysql:3306"]
R4["Redis<br/>redis:6379"]
R1 <-->|"app_network"| R2
R2 <--> R3
R2 <--> R4
end
YAML --> C1
C1 --> C2
C2 --> C3
C2 --> C4
C2 --> C5
C2 --> C6
C3 --> Result
C4 --> Result
C5 --> Result
C6 --> Result
style YAML fill:#fff3e0
style Compose fill:#e3f2fd
style Result fill:#e8f5e9
Compose 核心价值:
- 声明式配置:用 YAML 定义整个应用栈
- 一键启停:
docker-compose up/down管理全部服务- 服务发现:自动配置容器间网络通信
- 环境隔离:通过
docker-compose.override.yml覆盖配置
6.1.1、安装 Compose
Linux安装
# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
Windows安装 在 Windows 上使用 Docker Desktop: 同样,Docker Desktop 包含 Docker Compose,安装后即可使用。
Mac安装 在 Mac 上使用 Docker Desktop: 同样,Docker Desktop 包含 Docker Compose,安装后即可使用。
验证安装
docker-compose --version
6.1.2、基础使用
- 创建一个
docker-compose.yml文件,定义服务:
version: '3'
services:
web:
image: nginx
ports:
- "80:80"
db:
image: mysql
environment:
- MYSQL_ROOT_PASSWORD=my-secret-pw
networks:
app_network:
driver: bridge
配置说明:
version: '3':指定 Compose 文件格式版本,版本 3 是目前最常用的版本services:定义需要运行的服务容器
web:自定义服务名称image: nginx:使用的镜像(无则拉取,有则使用)ports:端口映射,格式为"主机端口:容器端口"environment:环境变量,用于配置容器内部参数(如 MySQL 密码)networks:自定义网络配置,bridge为桥接模式
- 启动服务:
docker-compose up
# docker-compose up -d # 后台运行
- 查看运行状态:
docker-compose ps
- 停止服务:
docker-compose down
# docker-compose down -v # 删除网络、卷等资源
- 重建服务:
docker-compose up --build
6.1.3、环境变量
可以在 docker-compose.yml 文件中使用环境变量,或者创建一个 .env 文件来存储变量,避免在 YAML 文件中硬编码敏感信息。例如:
version: '3'
services:
web:
image: nginx
environment:
- ENV_VAR=value
- ANOTHER_ENV_VAR=another_value
# 使用文件中的环境变量
- $(ENV_FILE_PATH)
# 使用环境变量文件
- ./env_file
# 使用环境变量文件中的变量
- $(ENV_FILE_PATH:default_value)
6.1.4、服务依赖
Docker Compose 会自动处理服务之间的依赖关系。例如,如果您定义了一个服务依赖于另一个服务,Compose 会确保先启动依赖的服务。
6.1.5、网络配置
在上面的例子中,我们定义了一个桥接网络 app_network,使得 web 和 db 服务可以在同一个网络中通信。您可以通过服务名称来访问其他服务,而无需知道具体的 IP 地址。
6.1.6、服务扩展
Docker Compose 支持通过 deploy 部分定义服务的扩展策略,例如副本数量、资源限制等。这对于在开发和测试环境中模拟生产负载非常有用。
version: '3'
services:
web:
image: nginx
deploy:
replicas: 3
resources:
limits:
cpus: '0.50'
memory: 256M
replicas: 3 表示启动 3 个 web 服务副本。
resources: 限制每个副本使用的 CPU 和内存资源。
6.1.7、构建配置
Docker Compose 支持使用 Dockerfile 构建镜像。您可以在 docker-compose.yml 文件中定义构建上下文,例如:
version: '3'
services:
web:
build:
context: .
# Dockerfile 文件路径
dockerfile: Dockerfile
# 构建参数
args:
- VERSION=1.0.0
# 镜像标签
- TAG=latest
# 镜像名称
- NAME=myapp
6.1.8、监控和日志
Docker Compose 提供了 docker-compose logs 命令来查看服务的日志。您可以使用 -f 选项来实时查看日志输出。
docker-compose logs -f
6.1.9、更新和回滚
Docker Compose 支持服务的更新和回滚。您可以使用 docker-compose up 命令来更新服务,并使用 docker-compose down 命令来回滚到先前的配置。
docker-compose up --build
docker-compose up --force-recreate --no-deps --build
--force-recreate:强制重新创建容器。
--no-deps:不重新创建依赖的服务。
6.1.10、CI/CD 集成
Docker Compose 可以与 CI/CD 工具集成,例如 Jenkins、GitLab CI/CD 和 GitHub Actions。您可以在 CI/CD 流程中使用 Docker Compose 来构建、测试和部署应用程序。
# 在流水线中执行
docker-compose build
docker-compose up -d
docker-compose run --rm tests
docker-compose down
七、容器监控与日志
7.1、资源监控
Docker 提供了 docker stats 命令,可以实时查看容器的资源使用情况,包括 CPU、内存、网络和磁盘 I/O。
7.2、Prometheus + Grafana(普若-米-西-厄斯) + Grafana(格若-发-呐)
7.2.1、Prometheus 配置
Prometheus 是一个开源的监控和警报工具,用于收集和存储时间序列数据。Prometheus 可以与 Docker 容器一起使用,以收集容器的资源使用情况。
7.2.2、Grafana 可视化
Grafana 是一个开源的监控仪表板工具,用于可视化 Prometheus 收集的数据。Grafana 可以与 Docker 容器一起使用,以展示容器的资源使用情况。
7.2.3、典型工作流程
- 安装 Prometheus 和 Grafana。
# 安装 node-exporter,虚拟机监控的exporter,包括虚拟机cpu、内存使用情况等。
docker run -d --name node-exporter -p 9100:9100 prom/node-exporter
# 用于收集和存储时间序列数据
docker run -d --name prometheus -p 9090:9090 -v /Volumes/czx/dev_tool/docker/prometheus/conf/prometheus.yml:/etc/prometheus/prometheus.yml prom/prometheus:latest
# 用于展示 Prometheus 收集的数据
docker run -d --name grafana -p 3000:3000 --name=grafana -v /Volumes/czx/dev_tool/docker/grafana/data:/var/lib/grafana grafana/grafana
# 安装 cadvisor,用于收集 Docker 容器的资源使用情况。
docker run -v /:/rootfs:ro -v /var/run:/var/run:rw -v /sys:/sys:ro -v /var/lib/docker/:/var/lib/docker:ro -v /dev/disk/:/dev/disk:ro -p 8080:8080 -d --name=cadvisor google/cadvisor:latest
prometheus.yml 文件中配置了要监控的目标。
global:
scrape_interval: 60s # 全局默认抓取间隔(60秒抓取一次数据)
evaluation_interval: 60s # 规则评估间隔(60秒评估一次告警规则)
scrape_configs: # 抓取配置列表
- job_name: prometheus # 任务名称:监控 Prometheus 自身
static_configs:
- targets: ['localhost:9090'] # 监控目标地址(Prometheus 的 Web UI)
labels:
instance: prometheus # 自定义标签,标识实例名称
- job_name: linux # 任务名称:监控 Linux 系统指标(通过 node-exporter)
static_configs:
- targets: ['172.17.0.3:9100'] # node-exporter 暴露的指标接口地址
labels:
instance: localhost # 标签:标识为本地服务器
- job_name: cadvisor # 任务名称:监控 Docker 容器指标
static_configs:
- targets: ['172.17.0.3:8080'] # cadvisor 暴露的指标接口地址
labels:
instance: cadvisor # 标签:标识为容器监控服务
配置说明:
global:全局配置,对所有任务生效
scrape_interval:数据抓取间隔,决定监控数据的采集频率evaluation_interval:规则评估间隔,用于计算告警规则scrape_configs:抓取配置列表,可定义多个监控任务
job_name:任务名称,具有唯一性static_configs:静态配置方式,targets定义监控目标地址labels:为监控目标添加自定义标签,便于分类和筛选
- 访问prometheus,http://ip:9090/targets 可以看到我们起来的几个exporter:
3. 访问node-exporter, http://ip:9100/metrics 可以看到node-exporter收集的指标:
- 访问Grafana,http://ip:3000,配置prometheus数据源:
- 创建仪表板以展示容器的资源使用情况。
具体参照:www.jb51.net/server/3375…
7.2、日志管理
7.2.1、docker logs 命令
| 命令 | 说明 | 示例 |
|---|---|---|
docker logs | 查看容器日志 | docker logs container_id |
docker logs -f | 实时跟踪日志 | docker logs -f container_id |
docker logs --tail | 查看最后N行 | docker logs --tail 100 container_id |
docker logs -t | 显示时间戳 | docker logs -t container_id |
7.2.2、日志驱动配置
Docker 支持多种日志驱动:
| 驱动 | 说明 | 适用场景 |
|---|---|---|
| json-file | 默认驱动,JSON 格式写入文件 | 开发测试 |
| syslog | 发送到系统 syslog | 传统环境 |
| journald | 发送到 systemd journal | systemd 系统 |
| fluentd | 发送到 Fluentd 收集器 | 集中日志收集 |
| awslogs | 发送到 AWS CloudWatch | AWS 云环境 |
配置示例:
docker run --log-driver fluentd --log-opt fluentd-address=localhost:24224 nginx
7.2.3、ELK Stack 集成
ELK Stack(Elasticsearch + Logstash + Kibana)是 Docker 日志收集、存储和可视化的完整方案。
ELK 日志收集架构
flowchart LR
subgraph Collect["日志采集层"]
C1["Docker 容器"]
C2["应用日志<br/>/var/lib/docker/containers/"]
end
subgraph Transport["日志传输层"]
T1["Filebeat<br/>轻量级采集器"]
T2["Fluentd<br/>统一日志层"]
T3["Logstash<br/>日志处理"]
end
subgraph Storage["日志存储层"]
S1["Elasticsearch<br/>全文搜索引擎"]
S2["索引存储<br/>logs-YYYY.MM.DD"]
end
subgraph Visualize["日志可视化层"]
V1["Kibana<br/>可视化界面"]
V2["Dashboard<br/>仪表盘"]
V3["搜索查询<br/>DSL"]
end
C1 --> C2
C2 --> T1
C2 --> T2
T1 --> T3
T2 --> T3
T3 --> S1
S1 --> V1
V1 --> V2
V1 --> V3
style Collect fill:#e3f2fd
style Transport fill:#fff3e0
style Storage fill:#e8f5e9
style Visualize fill:#fce4ec
ELK 各组件职责:
- Filebeat:轻量级日志采集器,监控日志文件变化,发送到 Logstash 或 Elasticsearch
- Logstash:日志处理管道,进行解析、过滤、转换
- Elasticsearch:分布式搜索引擎,存储和索引日志,支持高速查询
- Kibana:Web 可视化界面,提供搜索、图表分析、仪表盘功能
八、私有镜像仓库
8.1、Docker Registry
Docker Registry 是一个用于存储和分发Docker镜像的服务。可以使用Docker Registry搭建私有镜像仓库。
镜像仓库工作流程
flowchart LR
subgraph Push["镜像推送 (Push)"]
Build["docker build<br/>构建镜像"]
Tag["docker tag<br/>打标签"]
PushAct["docker push<br/>推送到仓库"]
Build --> Tag --> PushAct
end
subgraph Registry["镜像仓库 (Registry)"]
R1["index.json<br/>索引"]
R2["manifests<br/>清单"]
R3["layers<br/>镜像层"]
end
subgraph Pull["镜像拉取 (Pull)"]
PullCmd["docker pull<br/>拉取镜像"]
Run["docker run<br/>运行容器"]
PullCmd --> Run
end
PushAct -. "HTTP/HTTPS".-> Registry
Registry -. "HTTP/HTTPS".-> PullCmd
style Push fill:#e8f5e9
style Registry fill:#fff3e0
style Pull fill:#e3f2fd
| 仓库类型 | 说明 | 特点 |
|---|---|---|
| Docker Hub | 官方公共仓库 | 镜像丰富,但访问慢,有速率限制 |
| 阿里云镜像 | 国内镜像加速 | 访问快,需登录,有配额限制 |
| 私有 Registry | 自建 Registry | 完全可控,需自行维护 |
| Harbor | 企业级镜像仓库 | 权限管理、镜像扫描、高可用 |
8.2、Harbor
Harbor 是一个开源的容器镜像仓库,提供了安全、高效和可扩展的镜像管理功能。Harbor 可以与Docker Registry无缝集成,提供更高级的功能,如镜像扫描、镜像复制和镜像同步。
九、容器安全
9.1、安全基础
Docker 提供了一些安全功能,如命名空间隔离、安全选项和镜像扫描。用户可以使用这些功能来提高容器的安全性。
Docker 安全多层防护体系
%%{init: {'theme':'base'}}%%
graph TB
subgraph App[应用层]
A1[应用代码]
A2[非 root 用户运行]
end
subgraph Container[容器层]
C1[只读镜像]
C2[最小镜像<br/>distroless/alpine]
C3[资源限制<br/>CPU/内存]
C4[Capabilities 控制]
end
subgraph Namespace[命名空间层]
N1[PID 命名空间<br/>进程隔离]
N2[Network 命名空间<br/>网络隔离]
N3[Mount 命名空间<br/>文件系统隔离]
N4[User 命名空间<br/>用户隔离]
end
subgraph Kernel[内核层]
K1[Cgroups<br/>资源配额]
K2[Seccomp<br/>系统调用过滤]
K3[AppArmor/SELinux<br/>强制访问控制]
K4[Linux Capabilities<br/>特权控制]
end
subgraph Scan[扫描层]
S1[Trivy/Clair<br/>漏洞扫描]
S2[镜像签名<br/>Notary]
end
A1 --> C1
A2 --> C1
C1 --> C2
C2 --> C3
C2 --> C4
C3 --> N1
C3 --> N2
C3 --> N3
C3 --> N4
N1 --> K1
N2 --> K2
N3 --> K3
N4 --> K4
C2 -. 安全扫描 .-> S1
C2 -. 内容信任 .-> S2
style App fill:#e8f5e9,stroke:#333,stroke-width:2px
style Container fill:#e3f2fd,stroke:#333,stroke-width:2px
style Namespace fill:#fff3e0,stroke:#333,stroke-width:2px
style Kernel fill:#fce4ec,stroke:#333,stroke-width:2px
style Scan fill:#f3e5f5,stroke:#333,stroke-width:2px
9.2、安全最佳实践
在容器化应用时,应遵循以下安全最佳实践:
- 使用最小权限原则运行容器。
- 使用非root用户运行容器。
- 使用安全镜像。
- 限制容器对主机的访问权限。
- 定期更新和升级容器镜像。
十、Docker 进阶特性
10.1、多阶段构建(Multi-stage Builds)
多阶段构建是 Docker 17.05 引入的特性,允许在单个 Dockerfile 中使用多个 FROM 指令,每个阶段可以基于不同的基础镜像,最终只保留最后一个阶段的产物,大幅减小镜像体积。
10.1.1、传统构建的问题
# 传统方式:构建环境和运行环境混在一起
FROM golang:1.21
WORKDIR /app
COPY . .
RUN go build -o myapp
CMD ["./myapp"]
问题:
- 镜像包含 Go 编译器(>800MB)
- 包含源代码和构建缓存
- 最终镜像体积巨大
10.1.2、多阶段构建优化
# 第一阶段:构建
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o myapp
# 第二阶段:运行(使用最小镜像)
FROM alpine:latest
WORKDIR /root/
# 从构建阶段复制产物
COPY --from=builder /app/myapp .
CMD ["./myapp"]
多阶段构建原理图
graph TB
subgraph Stage1["阶段 1:构建环境 (builder)"]
S1_Base["golang:1.21-alpine<br/>~800MB"]
S1_Deps["go mod download<br/>依赖包"]
S1_Src["复制源代码"]
S1_Binary["编译二进制文件<br/>myapp (~10MB)"]
S1_Base --> S1_Deps --> S1_Src --> S1_Binary
end
subgraph Stage2["阶段 2:运行环境"]
S2_Base["alpine:latest<br/>~5MB"]
S2_Copy["COPY --from=builder"]
S2_Final["最终镜像<br/>~15MB"]
S2_Base --> S2_Copy --> S2_Final
end
S1_Binary -. "只复制二进制".-> S2_Copy
Discard["丢弃 (构建工具、源码、依赖)"]
S1_Base -. "丢弃".-> Discard
S1_Deps -. "丢弃".-> Discard
S1_Src -. "丢弃".-> Discard
style Stage1 fill:#fff3e0
style Stage2 fill:#e8f5e9
style Discard fill:#ffcdd2
优化效果:
- 最终镜像从 800MB+ 降至 15MB
- 只包含二进制文件,无编译工具
- 攻击面更小,更安全
10.1.3、多阶段构建常用技巧
| 技巧 | 说明 | 示例 |
|---|---|---|
| 命名阶段 | 使用 AS 命名便于引用 | FROM node:18 AS builder |
| 复制产物 | 从前阶段复制文件 | COPY --from=builder /app/dist . |
| 多阶段依赖 | 多个构建阶段相互依赖 | COPY --from=builder1 ... |
| 使用缓存 | 分离依赖安装和代码复制 | 先 COPY go.mod,再 COPY 源码 |
10.1.4、实战案例:前端应用构建
# 构建阶段
FROM node:18-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
RUN npm run build
# 生产阶段
FROM nginx:alpine
COPY --from=builder /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
10.1.5、Java 多阶段构建示例
# 构建阶段
FROM maven:3.9-eclipse-temurin-17-alpine AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -DskipTests
# 运行阶段
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
10.2、Healthcheck 健康检查
10.2.1、HEALTHCHECK 指令
FROM nginx:alpine
# 每30秒检查一次,超时3秒,连续2次失败视为不健康
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=2 \
CMD curl -f http://localhost:80/ || exit 1
| 参数 | 说明 | 默认值 |
|---|---|---|
--interval | 检查间隔 | 30s |
--timeout | 超时时间 | 30s |
--start-period | 启动宽限期 | 0s |
--retries | 重试次数 | 3 |
10.2.2、常见健康检查命令
| 应用类型 | 健康检查命令 |
|---|---|
| Web 服务 | curl -f http://localhost:8080/health |
| 数据库 | pg_isready -U postgres |
| Redis | redis-cli ping | grep PONG |
| 自定义 | wget --quiet --tries=1 --spider http://localhost/ || exit 1 |
10.2.3、查看健康状态
# 查看容器健康状态
docker ps
# STATUS 列显示 (healthy) 或 (unhealthy)
# 查看健康检查日志
docker inspect --format='{{.State.Health}}' container_id
# 禁用容器健康检查
docker run --no-healthcheck nginx
10.3、BuildKit 构建加速器
10.3.1、启用 BuildKit
# 临时启用(单次构建)
DOCKER_BUILDKIT=1 docker build -t myapp .
# 永久启用(写入配置文件)
echo '{"features":{"buildkit":true}}' > ~/.docker/daemon.json
10.3.2、BuildKit 特性
| 特性 | 说明 |
|---|---|
| 并行构建 | 多层同时构建 |
| 缓存导出 | 支持远程缓存(S3、 registry) |
| 秘密挂载 | 安全传递构建密钥 |
| SSH 转发 | 构建时使用 SSH 密钥 |
10.3.3、秘密挂载(Secret Mount)
# syntax=docker/dockerfile:1.2
FROM node:18
RUN --mount=type=secret,id=npmrc,target=/root/.npmrc \
npm ci
# 构建时传递秘密
docker build --secret id=npmrc,src=$HOME/.npmrc -t myapp .
10.3.4、缓存挂载(Cache Mount)
# syntax=docker/dockerfile:1.2
FROM python:3.11
RUN --mount=type=cache,target=/root/.cache/pip \
pip install -r requirements.txt
十一、Docker Swarm 集群编排
11.1、Swarm 简介
Docker Swarm 是 Docker 原生的集群管理工具,将多个 Docker 主机虚拟成一个虚拟主机,提供容器编排能力。
Docker Swarm 集群架构
graph TB
subgraph Manager["管理节点 (Manager)"]
M1["API Server"]
M2["Scheduler<br/>调度器"]
M3["Orchestrator<br/>编排器"]
M4["Dispatcher<br/>分发器"]
M1 --> M2
M1 --> M3
M1 --> M4
end
subgraph Workers["工作节点 (Workers)"]
subgraph W1["Worker 1"]
WC1["容器 1"]
WC2["容器 2"]
end
subgraph W2["Worker 2"]
WC3["容器 3"]
WC4["容器 4"]
end
subgraph W3["Worker 3"]
WC5["容器 5"]
end
end
subgraph Overlay_Network["Overlay 网络 (VXLAN)"]
O1["Service A<br/>负载均衡"]
O2["Service B<br/>负载均衡"]
O1 -. "跨主机通信".-> WC1
O1 -.-> WC3
O1 -.-> WC5
end
User["用户请求"]
LB["Ingress<br/>负载均衡"]
Registry["镜像仓库"]
User --> LB
LB --> Manager
Manager --> W1
Manager --> W2
Manager --> W3
Registry -. "拉取镜像".-> Workers
style Manager fill:#fff3e0
style Workers fill:#e3f2fd
style Overlay_Network fill:#e8f5e9
与 Docker Compose 对比:
| 特性 | Docker Compose | Docker Swarm |
|---|---|---|
| 部署范围 | 单机 | 多机集群 |
| 高可用 | ❌ | ✅ |
| 负载均衡 | ❌ | ✅ |
| 滚动更新 | ❌ | ✅ |
| 服务发现 | 容器名 | 内置 DNS |
| 使用场景 | 开发测试 | 生产环境 |
11.2、Swarm 集群搭建
11.2.1、初始化管理节点
# 在管理节点上执行
docker swarm init --advertise-addr 192.168.1.10
# 输出示例:
# Swarm initialized: current node (xxx) is now a manager.
# To add a worker to this swarm, run the following command:
# docker swarm join --token SWMTKN-1-xxx 192.168.1.10:2377
11.2.2、添加工作节点
# 在工作节点上执行(使用上面输出的命令)
docker swarm join --token SWMTKN-1-xxx 192.168.1.10:2377
# 验证节点加入成功
docker node ls
11.2.3、常用节点管理命令
| 命令 | 说明 |
|---|---|
docker swarm leave | 离开集群 |
docker swarm leave --force | 强制离开 |
docker node ls | 列出节点 |
docker node rm node_id | 删除节点 |
docker node promote node_id | 提升为管理节点 |
docker node demote node_id | 降级为工作节点 |
11.3、Service 服务管理
Service(服务) 是 Swarm 集群中管理的最小调度单位,定义了一个镜像在集群中的运行方式。与单个容器不同,Service 可以横向扩展为多个副本(Replica),自动分配到不同的节点上运行,实现高可用和负载均衡。
核心概念:
- Service 是 Docker Swarm 中的高级抽象,将应用封装为可管理的单元
- 一个 Service 对应一个镜像,但可以运行多个容器副本
- Swarm 自动处理副本的调度、故障恢复和负载分配
11.3.1、创建服务
# 创建 Nginx 服务,3 个副本
docker service create --name nginx --replicas 3 -p 80:80 nginx:alpine
# 创建带挂载的服务
docker service create \
--name mysql \
--replicas 1 \
--mount type=volume,source=mysql_data,target=/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
mysql:8.0
11.3.2、服务扩缩容
# 扩展服务到 10 个副本
docker service scale nginx=10
# 缩减到 2 个副本
docker service scale nginx=2
11.3.3、服务更新与回滚
# 滚动更新镜像版本
docker service update --image nginx:1.25 nginx
# 配置滚动更新策略
docker service update \
--update-parallelism 2 \
--update-delay 10s \
--update-failure-action rollback \
nginx
# 回滚到上一个版本
docker service rollback nginx
| 更新参数 | 说明 | 默认值 |
|---|---|---|
--update-parallelism | 每次更新容器数 | 1 |
--update-delay | 更新间隔 | 0s |
--update-failure-action | 更新失败动作(pause/continue/rollback) | pause |
11.4、Stack 部署
Stack(栈) 是 Docker Swarm 中管理多个 Service 的方式,通过一个 docker-compose.yml 文件定义一组相关联的服务、网络、卷等资源,实现一键部署完整的分布式应用。
核心概念:
- Stack 是多个 Service 的集合,类似于 Docker Compose 的概念,但运行在集群环境中
- 一条命令即可部署整个应用栈,自动创建所有依赖的服务和网络
- Stack 提供了比单个 Service 更高层次的应用管理
11.4.1、docker-compose.yml 适配 Swarm
version: '3.8' # Compose 文件版本
services:
web: # 服务名称:前端 Web 服务
image: nginx:alpine # 使用的镜像
ports:
- "80:80" # 端口映射
deploy: # Swarm 部署配置(Compose v3 特有)
replicas: 3 # 运行 3 个副本实例
update_config: # 滚动更新策略
parallelism: 1 # 每次更新 1 个容器
delay: 10s # 更新间隔 10 秒
failure_action: rollback # 失败时回滚
restart_policy: # 重启策略
condition: on-failure # 容器异常退出时重启
delay: 5s # 重启延迟 5 秒
max_attempts: 3 # 最大重试 3 次
placement: # 调度约束
constraints: # 部署约束条件
- node.role == worker # 必须部署到 worker 节点
db: # 服务名称:数据库服务
image: postgres:15 # 使用的镜像
environment:
POSTGRES_PASSWORD: secret # 环境变量(数据库密码)
volumes:
- db_data:/var/lib/postgresql/data # 持久化卷挂载
deploy:
replicas: 1 # 单副本(数据库通常用单实例)
placement:
constraints:
- node.labels.storage == ssd # 部署到带有 ssd 标签的节点
volumes: # 定义持久化卷
db_data:
driver: local # 使用本地存储驱动
networks: # 定义网络
default:
driver: overlay # 使用 overlay 网络(集群内跨主机通信)
配置说明:
deploy:Swarm 特有的部署配置,在单机 Docker Compose 中不使用
replicas:副本数量,决定运行多少个容器实例update_config:滚动更新时的并行数、间隔和失败处理restart_policy:容器异常退出后的重启策略placement.constraints:限制服务部署到满足特定条件的节点volumes:声明持久化存储,数据卷独立于容器生命周期networks:overlay 网络用于集群中服务间的跨主机通信
11.4.2、部署 Stack
# 部署 stack
docker stack deploy -c docker-compose.yml myapp
# 查看 stack 服务
docker stack ls
docker stack ps myapp
docker stack services myapp
# 删除 stack
docker stack rm myapp
11.5、Swarm 网络与存储
11.5.1、Overlay 网络
# 创建 overlay 网络
docker network create --driver overlay --attachable my_network
# 使用 attachable 允许独立容器加入
docker run --network my_network nginx
11.5.2、存储配置
| 存储类型 | 用途 | 配置 |
|---|---|---|
| volume | 持久化数据 | type=volume,source=vol,target=/data |
| bind | 绑定挂载 | type=bind,source=/host,target=/container |
| tmpfs | 临时存储 | type=tmpfs,target=/tmp |
十二、镜像优化与安全扫描
12.1、镜像优化最佳实践
12.1.1、减小镜像体积的技巧
| 技巧 | 方法 | 效果 |
|---|---|---|
| 使用精简基础镜像 | alpine、distroless、scratch | 减小 50-90% |
| 多阶段构建 | 分离构建和运行环境 | 减小 80%+ |
| 合并 RUN 指令 | 使用 && 连接命令 | 减少层数 |
| 清理缓存 | apt-get clean、rm -rf /var/cache | 移除临时文件 |
| .dockerignore | 排除不必要的文件 | 减小构建上下文 |
12.1.2、.dockerignore 配置
# Git
.git
.gitignore
# 依赖(构建时会重新安装)
node_modules
vendor
__pycache__
# 构建产物(构建时会重新生成)
dist
build
target
# IDE
.idea
.vscode
*.iml
# 测试文件
*.test.js
__tests__
coverage
# 文档
README.md
CHANGELOG.md
docs/
# 其他
*.log
.env
.env.local
.DS_Store
12.1.3、镜像分层优化
# ❌ 差的实践:每次代码变更都重新安装依赖
COPY . /app
RUN npm install
# ✅ 好的实践:利用缓存层
COPY package*.json /app/
RUN npm ci --only=production
COPY . /app
12.2、镜像安全扫描
12.2.1、Docker Scout(官方)
# 启用 Docker Scout
docker scout quickview nginx:latest
# 详细漏洞扫描
docker scout cves nginx:latest
# 比较两个镜像
docker scout compare nginx:1.24 nginx:1.25
12.2.2、Trivy(开源)
# 安装 Trivy
brew install trivy
# 扫描镜像
trivy image nginx:latest
# 扫描并过滤高危漏洞
trivy image --severity HIGH,CRITICAL nginx:latest
# 导出报告
trivy image --format json -o report.json nginx:latest
12.2.3、Clair(集成 Harbor)
# 在 Harbor UI 中启用扫描
# 配置 > 漏洞 > 启用 Clair/Anchore 扫描
# 通过 API 触发扫描
curl -X POST "https://harbor.example.com/api/v2.0/projects/library/repositories/nginx/artifacts/latest/scan"
12.3、Distroless 镜像
12.3.1、什么是 Distroless
Google 提供的无发行版镜像,只包含应用及其运行时依赖,没有包管理器、shell 等工具。
# 使用 distroless 基础镜像
FROM gcr.io/distroless/java17-debian12
COPY target/app.jar /app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
12.3.2、Distroless 镜像类型
| 镜像 | 适用场景 |
|---|---|
gcr.io/distroless/static | 静态编译的 Go/C++ 应用 |
gcr.io/distroless/base | 动态链接的 C/C++ 应用 |
gcr.io/distroless/java17 | Java 17 应用 |
gcr.io/distroless/nodejs18 | Node.js 18 应用 |
gcr.io/distroless/python3 | Python 3 应用 |
12.3.3、调试 Distroless 容器
# 多阶段构建,包含调试版本
FROM gcr.io/distroless/java17-debian12:debug AS debug
# 调试版本包含 busybox shell
十三、CI/CD 集成
CI/CD(持续集成/持续部署) 是现代软件开发的核心实践,通过自动化流程实现代码的构建、测试、部署。Docker 与 CI/CD 的结合,使得应用可以在隔离的容器环境中完成整个交付流程,确保环境一致性和快速部署。
CI/CD 流水线核心流程:
- Build(构建):拉取代码,编译打包成 Docker 镜像
- Test(测试):在容器中运行单元测试和集成测试
- Security Scan(安全扫描):使用工具(如 Trivy)扫描镜像漏洞
- Push(推送):将镜像推送到私有仓库
- Deploy(部署):从仓库拉取镜像,完成服务部署
主流 CI/CD 工具对比
| 工具 | 配置文件 | 特点 | 适用场景 |
|---|---|---|---|
| Jenkins | Jenkinsfile | 插件生态丰富,灵活性高,需自建服务器 | 大型企业,复杂流水线 |
| GitLab CI | .gitlab-ci.yml | GitLab 内置,配置简单,与代码库紧密集成 | 使用 GitLab 的团队 |
| GitHub Actions | .github/workflows/*.yml | 社区 Actions 丰富,事件驱动,托管式 | 开源项目,GitHub 团队 |
流水线架构图
flowchart LR
subgraph CI["持续集成 (CI)"]
A1[代码提交] --> B1[构建镜像]
B1 --> C1[运行测试]
C1 --> D1[安全扫描]
end
subgraph CD["持续部署 (CD)"]
D1 --> E1[推送镜像]
E1 --> F1[部署服务]
end
subgraph Tools["工具实现"]
G1[Jenkins<br/>Jenkinsfile]
G2[GitLab CI<br/>.gitlab-ci.yml]
G3[GitHub Actions<br/>workflows/*.yml]
end
CI --> Tools
CD --> Tools
style CI fill:#e1f5fe
style CD fill:#f3e5f5
style Tools fill:#fff3e0
sequenceDiagram
participant Dev as 开发者
participant VCS as 代码仓库
participant CI as CI/CD 系统
participant Registry as 镜像仓库
participant Server as 生产服务器
Dev->>VCS: 提交代码 (git push)
VCS->>CI: 触发流水线
CI->>CI: 1. Build 构建镜像
CI->>CI: 2. Test 运行测试
CI->>CI: 3. Scan 安全扫描
CI->>Registry: 4. Push 推送镜像
Registry-->>CI: 镜像地址
CI->>Server: 5. Deploy SSH部署
Server-->>CI: 部署完成
CI-->>Dev: 通知结果
13.1、Docker + Jenkins 流水线
Jenkins 是最流行的 CI/CD 工具之一,通过 Jenkinsfile 定义流水线逻辑,docker.pipeline 插件提供了与 Docker 的深度集成。
13.1.1、Jenkinsfile 示例
pipeline {
agent any // 在任意可用代理节点执行
environment { // 定义环境变量
DOCKER_REGISTRY = 'registry.example.com' // 私有镜像仓库地址
IMAGE_NAME = 'myapp' // 镜像名称
IMAGE_TAG = "${BUILD_NUMBER}" // 使用构建编号作为镜像标签(便于追溯)
}
stages { // 定义流水线阶段
stage('Build') { // 阶段1:构建镜像
steps {
script {
// 执行 Docker 多阶段构建
docker.build("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}", ".")
}
}
}
stage('Test') { // 阶段2:运行测试
steps {
script {
// 在构建的镜像内部执行测试命令
docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").inside {
sh 'npm test'
}
}
}
}
stage('Security Scan') { // 阶段3:安全扫描
steps {
// 使用 Trivy 扫描镜像漏洞
sh "trivy image ${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}"
}
}
stage('Push') { // 阶段4:推送到仓库
when {
branch 'main' // 仅在 main 分支执行
}
steps {
script {
// 使用凭证认证到私有仓库
docker.withRegistry("https://${DOCKER_REGISTRY}", 'registry-credentials') {
// 推送带版本标签的镜像
docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push()
// 同时推送 latest 标签
docker.image("${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG}").push('latest')
}
}
}
}
stage('Deploy') { // 阶段5:部署到生产环境
when {
branch 'main' // 仅在 main 分支执行
}
steps {
// SSH 远程连接到生产服务器执行部署命令
sh """
ssh deploy@prod-server '
docker pull ${DOCKER_REGISTRY}/${IMAGE_NAME}:${IMAGE_TAG} &&
docker-compose -f /opt/app/docker-compose.yml up -d
'
"""
}
}
}
}
Jenkinsfile 核心概念:
agent any:在任意可用节点执行流水线environment:定义全局环境变量,用于配置和敏感信息stages:流水线阶段,每个阶段执行特定任务when { branch 'main' }:条件执行,仅指定分支触发docker.withRegistry:认证到私有镜像仓库
13.2、GitLab CI 集成
GitLab CI 是 GitLab 自带的 CI/CD 功能,通过 .gitlab-ci.yml 文件定义流水线,配置文件放在项目根目录。
13.2.1、.gitlab-ci.yml 示例
stages: # 定义流水线阶段(按顺序执行)
- build # 构建阶段
- test # 测试阶段
- security # 安全扫描阶段
- push # 推送阶段
- deploy # 部署阶段
variables: # 全局环境变量
DOCKER_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA # GitLab 内置变量构建镜像名
build: # 作业1:构建
stage: build # 属于 build 阶段
image: docker:latest # 使用 Docker 镜像作为运行环境
services: # 附加服务(Docker in Docker)
- docker:dind # Docker daemon 服务
script: # 执行脚本
- docker build -t $DOCKER_IMAGE . # 构建镜像
- docker save $DOCKER_IMAGE > image.tar # 导出镜像为 tar 文件
artifacts: # 产物配置(传递给后续阶段)
paths:
- image.tar # 保存镜像文件供后续作业使用
test: # 作业2:测试
stage: test # 属于 test 阶段
image: docker:latest
services:
- docker:dind
script:
- docker load < image.tar # 加载上一阶段保存的镜像
- docker run --rm $DOCKER_IMAGE npm test # 运行测试
security: # 作业3:安全扫描
stage: security # 属于 security 阶段
image: aquasec/trivy:latest # 使用 Trivy 专用镜像
script:
- docker load < image.tar # 加载镜像
- trivy image --exit-code 1 --severity HIGH,CRITICAL $DOCKER_IMAGE # 扫描高危漏洞
push: # 作业4:推送到仓库
stage: push
image: docker:latest
services:
- docker:dind
script:
- docker load < image.tar # 加载镜像
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY # 登录仓库
- docker push $DOCKER_IMAGE # 推送镜像(使用 commit SHA 作为标签)
- docker tag $DOCKER_IMAGE $CI_REGISTRY_IMAGE:latest # 打 latest 标签
- docker push $CI_REGISTRY_IMAGE:latest # 推送 latest
only:
- main # 仅在 main 分支触发
deploy: # 作业5:部署(使用 Helm)
stage: deploy
image: alpine/helm:latest # 使用 Helm 镜像
script:
- helm upgrade --install myapp ./chart --set image.tag=$CI_COMMIT_SHA # 升级/安装应用
only:
- main # 仅在 main 分支触发
GitLab CI 核心概念:
stages:定义全局阶段顺序,所有作业按阶段分组执行image:作业使用的 Docker 镜像(运行时环境)services:附加服务,docker:dind启用 Docker-in-Docker 支持artifacts:作业产物,用于在同流水线内共享文件$CI_REGISTRY_IMAGE、$CI_COMMIT_SHA:GitLab 内置预定义变量only:限制作业触发的分支
13.3、GitHub Actions 集成
GitHub Actions 是 GitHub 提供的 CI/CD 功能,配置文件放在 .github/workflows/ 目录下,支持丰富的社区 Actions 生态。
13.3.1、.github/workflows/docker.yml
name: Docker Build and Push # 工作流名称
on: # 触发条件
push: # 代码推送时触发
branches: [main] # 仅 main 分支
pull_request: # PR 时也触发
branches: [main]
jobs: # 定义作业
build: # 作业名称
runs-on: ubuntu-latest # 运行在 Ubuntu 最新版虚拟机
steps: # 步骤列表
- uses: actions/checkout@v4 # 步骤1:拉取代码
- name: Set up Docker Buildx # 步骤2:设置 Docker Buildx(支持多平台构建)
uses: docker/setup-buildx-action@v3
- name: Build image # 步骤3:构建镜像
uses: docker/build-push-action@v5
with:
context: . # 构建上下文为当前目录
load: true # 加载镜像到本地(不推送)
tags: myapp:test # 镜像标签
- name: Run tests # 步骤4:运行测试
run: |
docker run --rm myapp:test npm test
- name: Run Trivy scanner # 步骤5:安全扫描
uses: aquasecurity/trivy-action@master
with:
image-ref: 'myapp:test' # 扫描的镜像
format: 'sarif' # 输出格式(可用于 GitHub 安全告警)
output: 'trivy-results.sarif'
- name: Login to Registry # 步骤6:登录镜像仓库
if: github.ref == 'refs/heads/main' # 仅 main 分支执行
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }} # GitHub Secrets 中的用户名
password: ${{ secrets.DOCKER_PASSWORD }} # GitHub Secrets 中的密码
- name: Push image # 步骤7:推送镜像
if: github.ref == 'refs/heads/main' # 仅 main 分支执行
uses: docker/build-push-action@v5
with:
context: .
push: true # 推送到仓库
tags: | # 多标签推送
${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }} # commit SHA 标签
${{ secrets.DOCKER_USERNAME }}/myapp:latest # latest 标签
cache-from: type=gha # 使用 GitHub Actions 缓存加速构建
cache-to: type=gha,mode=max
GitHub Actions 核心概念:
name:工作流名称,显示在 GitHub Actions 页面on:触发条件,支持 push、pull_request、schedule(定时)等jobs:作业定义,可以有多个作业并行执行runs-on:运行环境的虚拟机镜像steps:步骤列表,按顺序执行uses:使用社区维护的 Action(复用他人的工作流)run:执行 Shell 命令with:传递给 Action 或 step 的参数if:条件执行,控制是否运行该步骤secrets:加密存储的敏感信息,在 Settings -> Secrets 中配置
十四、调试与排障
容器问题排查流程图
flowchart TD
A["容器无法正常工作"] --> B{"docker ps -a<br/>容器存在?"}
B -->|否| C["容器未创建成功"]
C --> C1["检查镜像是否存在<br/>docker images"]
C1 --> C2["docker pull 拉取镜像"]
C2 --> C3["重新创建容器<br/>docker run"]
B -->|是| D{"容器状态?"}
D -->|Exited| E["容器已退出"]
E --> E1["查看退出码<br/>docker inspect"]
E1 --> E2["查看日志<br/>docker logs"]
E2 --> E3{"错误类型?"}
E3 -->|端口占用| E4["docker port 查看<br/>更改端口映射"]
E3 -->|权限不足| E5["添加 --privileged<br/>或调整用户权限"]
E3 -->|找不到文件| E6["检查路径挂载<br/>-v 参数"]
E3 -->|配置错误| E7["检查环境变量<br/>-e 参数"]
D -->|Running| F["容器在运行"]
F --> F1["检查服务是否正常"]
F1 --> F2["docker logs 查看日志"]
F2 --> F3["docker exec 进入容器<br/>进一步排查"]
D -->|Restarting| G["容器反复重启"]
G --> G1["OOM?<br/>检查内存限制"]
G1 --> G2["健康检查失败?<br/>检查 HEALTHCHECK"]
G2 --> G3["调整资源限制"]
style A fill:#ffcdd2
style E fill:#fff3e0
style F fill:#e8f5e9
style G fill:#fce4ec
14.1、容器启动问题排查
14.1.1、查看容器日志
# 实时查看日志
docker logs -f container_id
# 查看最近 100 行
docker logs --tail 100 container_id
# 查看特定时间范围
docker logs --since 2024-01-01T00:00:00 container_id
# 显示时间戳
docker logs -t container_id
14.1.2、检查容器状态
# 查看容器详细信息
docker inspect container_id
# 查看容器资源使用
docker stats container_id
# 查看容器进程
docker top container_id
# 查看容器端口映射
docker port container_id
# 查看容器退出码
docker inspect --format='{{.State.ExitCode}}' container_id
| 退出码 | 含义 |
|---|---|
| 0 | 正常退出 |
| 1 | 一般错误 |
| 137 (128+9) | 被 SIGKILL 强制终止 |
| 143 (128+15) | 被 SIGTERM 终止 |
| 255 | 未知错误 |
14.2、网络问题排查
14.2.1、容器网络诊断
# 进入容器执行网络诊断
docker exec -it container_id sh
# 或无需进入容器直接执行
docker exec container_id ping -c 3 google.com
docker exec container_id nslookup db
docker exec container_id netstat -tlnp
14.2.2、网络连通性测试
# 测试容器间通信
docker run --rm --network my_network busybox ping -c 3 other_container
# 查看网络详情
docker network inspect bridge
docker network inspect my_network
14.3、使用 nsenter 进入容器命名空间
当容器没有 shell 时,使用 nsenter 进入:
# 获取容器 PID
PID=$(docker inspect --format='{{.State.Pid}}' container_id)
# 进入容器网络命名空间
sudo nsenter -t $PID -n ip addr
# 进入所有命名空间
sudo nsenter -t $PID -m -u -i -n -p /bin/sh
14.4、常见问题排查清单
| 问题 | 排查步骤 |
|---|---|
| 容器无法启动 | 查看 docker logs → 检查 ExitCode → 验证配置 |
| 端口无法访问 | docker port → docker ps → 检查防火墙 → 验证端口映射 |
| 连接被拒绝 | docker network ls → docker network inspect → 测试连通性 |
| 权限不足 | 检查用户/组 → 查看 SELinux/AppArmor → 检查 volume 权限 |
| OOM 被杀死 | docker inspect 查看 OOMKilled → 增加内存限制 |
| 磁盘空间不足 | docker system df → docker system prune |
14.5、Docker 系统维护
# 查看磁盘使用
docker system df
# 清理未使用资源
docker system prune # 删除停止的容器、未使用的网络、悬挂镜像
docker system prune -a # 删除所有未使用的镜像(不只是悬挂)
docker system prune --volumes # 同时清理卷
# 清理特定资源
docker volume prune # 未使用的卷
docker image prune # 悬挂镜像
docker container prune # 停止的容器
docker network prune # 未使用的网络
十五、Kubernetes(K8s)
15.1、Kubernetes 简介
Kubernetes 是一个开源的容器编排平台,用于自动化容器化应用程序的部署、扩展和管理。Kubernetes 提供了丰富的功能,如服务发现、负载均衡、自动扩展、滚动更新和回滚等。
Kubernetes 架构图
%%{init: {'theme':'base'}}%%
graph TB
subgraph CP[Control Plane 控制平面]
API[API Server<br/>统一入口]
ETCD[etcd<br/>分布式存储]
Scheduler[Scheduler<br/>调度器]
Controller[Controller Manager<br/>控制器]
end
subgraph Node2[Node 2 工作节点]
N2_Kubelet[Kubelet]
N2_Proxy[Kube-Proxy]
N2_Pod3[Pod 3]
end
subgraph Node1[Node 1 工作节点]
N1_Kubelet[Kubelet]
N1_Proxy[Kube-Proxy]
N1_Pod1[Pod 1]
N1_Pod2[Pod 2]
end
User[用户] --> API
Scheduler -->|调度| N1_Pod1
Scheduler --> N2_Pod3
style CP fill:#fff3e0,stroke:#333,stroke-width:2px
style Node1 fill:#e3f2fd,stroke:#333,stroke-width:2px
style Node2 fill:#e3f2fd,stroke:#333,stroke-width:2px
架构说明:
- Control Plane:集群的大脑,负责整个集群的管理
- API Server:提供 REST API,是集群的统一入口
- etcd:高可用键值存储,保存集群所有数据
- Scheduler:监控未调度 Pod,分配到合适节点
- Controller Manager:运行控制器,维护集群期望状态
- Node:实际运行 Pod 的工作节点
- Kubelet:节点代理,确保容器在 Pod 中运行
- Kube-Proxy:维护网络规则,实现服务通信
在 1.20 版本之前,Control Plane 称为 Master(主节点),Node 称为 Worker Node(工作节点)。
15.2、核心概念
Kubernetes 的核心概念包括:
-
Pod:最小的部署单元,可以包含一个或多个容器。
- 每个 Pod 都有一个唯一的 IP 地址,容器之间可以通过 localhost 进行通信。
- 示例:一个Pod运行Nginx主容器和一个定期同步数据的辅助容器。
-
Deployment:用于管理 Pod 的副本集,可以自动扩缩容。
- Deployment 可以自动扩缩容,并支持滚动更新和回滚。
- 示例:一个 Deployment 运行 3 个 Nginx Pod 副本。
-
Service:用于定义 Pod 的网络访问策略,可以提供负载均衡和 DNS 解析。
- Service 可以提供负载均衡和 DNS 解析,使得外部流量可以访问 Pod。
- 示例:一个 Service 将流量路由到 3 个 Nginx Pod 副本。
-
Volume:用于持久化存储,可以在 Pod 之间共享数据。
- Volume 支持多种存储类型,如本地存储、网络存储和云存储。
- 示例:一个 Volume 用于存储 Nginx Pod 的静态文件。
-
Namespace:用于隔离资源,可以在不同的命名空间中运行不同的应用程序。
- Namespace 可以限制资源的可见性和访问权限,并支持多租户环境。
- 示例:开发环境 Namespace 和生产环境 Namespace。
-
ConfigMap:用于存储配置数据,可以在 Pod 之间共享配置。
- ConfigMap 可以在 Pod 之间共享配置,并支持热更新。
- 示例:一个 ConfigMap 用于存储 Nginx Pod 的配置文件。
-
Secret:用于存储敏感数据,例如密码和密钥。
- Secret 可以在 Pod 之间共享,并支持加密存储。
- 示例:一个 Secret 用于存储数据库的密码。
15.3、典型工作流程
- 定义 Kubernetes 资源文件(YAML 格式)。
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
template:
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
配置说明:
apiVersion:API 版本kind:资源类型(Deployment、Service 等)metadata.name:资源名称spec.replicas:Pod 副本数量spec.template.spec.containers:容器配置
- 使用
kubectl apply命令部署资源。
kubectl apply -f web-app-deployment.yaml
- 查看资源状态。
kubectl get deployments
kubectl get pods
kubectl get services
- 暴露服务以供外部访问。
kubectl expose deployment web-app --type=LoadBalancer --port=80 --target-port=80
- 扩展或缩减资源。
# 手动扩缩容
kubectl scale deployment web-app --replicas=5
# 自动扩缩容(基于 CPU)
kubectl autoscale deployment web-app --cpu-percent=50 --min=3 --max=10
15.4、快速上手环境
| 工具 | 特点 | 适用场景 |
|---|---|---|
| Minikube | 单节点集群,本地运行 | 学习和测试 |
| Kind | Docker 容器运行 K8s | 本地多节点测试 |
| kubeadm | 官方集群搭建工具 | 生产环境 |
# Minikube 快速启动
minikube start --driver=docker
# Kind 创建多节点集群
kind create cluster --config kind-config.yaml
15.5、学习路径建议
1. 基础阶段
- 掌握 kubectl 核心命令(get、describe、logs、exec)
- 了解 Pod、Deployment、Service 等核心资源
- 实践滚动更新、水平扩展、服务暴露、配置管理
2. 进阶阶段
- 持久化存储:PersistentVolume(PV)、PersistentVolumeClaim(PVC)
- 调度策略:nodeSelector、affinity、tains、tolerations
- 网络策略:Calico/Flannel
- 配置管理:ConfigMap、Secret、Helm
3. 高级阶段
- 监控:Prometheus、Grafana
- 日志:ELK Stack
- CI/CD:Jenkins、ArgoCD(GitOps)