Docker Compose 是 Docker 官方编排工具,它允许用户通过简洁的 YAML 文件定义多容器的 Docker 应用程序。无论是开发者、系统管理员还是 DevOps 工程师,Docker Compose 都能帮助轻松地管理复杂的服务堆栈。通过本文,将深入了解 Docker Compose 的强大功能和使用场景,探索如何利用它来简化开发、测试和部署流程。无论是初学者还是希望优化现有工作流的高级用户,本文都将为提供实用的指导和技巧。让我们开始这段精彩的 Docker Compose 实战之旅吧!
肖哥弹架构 跟大家“弹弹” 高并发锁, 关注公号回复 ‘mvcc’ 获得手写数据库事务代码
欢迎 点赞,关注,评论。
关注公号Solomon肖哥弹架构获取更多精彩内容
历史热点文章
- 解锁大语言模型参数:零基础掌握大型语言模型参数奥秘与实践指南
- 高性能连接池之HikariCP框架分析:高性能逐条分解(架构师篇)
- 缓存雪崩/穿透/击穿/失效原理图/14种缓存数据特征+10种数据一致性方案
- Java 8函数式编程全攻略:43种函数式业务代码实战案例解析(收藏版)
- 一个项目代码讲清楚DO/PO/BO/AO/E/DTO/DAO/ POJO/VO
- 17个Mybatis Plugs注解:Mybatis Plugs插件架构设计与注解案例(必须收藏)
1、docker-compose 架构设计
设计说明:
- 用户: 这是使用 Docker Compose 的用户。
- Docker Compose CLI: 这是 Docker Compose 的命令行界面,用户通过它来运行命令。
- docker-compose.yml: Docker Compose 的配置文件,定义了服务、网络、卷等。
- 服务1、服务2、服务3: 这些是配置文件中定义的服务。
- Docker Engine: Docker 的后台守护进程,负责管理 Docker 对象。
- 容器: Docker Engine 创建和管理容器。
- 网络: Docker Engine 管理网络,使容器可以相互通信。
- 卷: Docker Engine 管理卷,用于数据持久化。
- 镜像: Docker Engine 管理镜像,服务基于镜像启动。
2、docker-compose 工作流程
流程说明:
- 运行 docker-compose up: 用户在命令行中执行
docker-compose up
命令,开始整个工作流程。 - Docker Compose: Docker Compose 工具开始处理。
- 解析 docker-compose.yml: Docker Compose 解析位于当前目录的
docker-compose.yml
文件,理解服务、网络和卷的配置。 - 构建服务镜像: 根据配置文件中的指令,构建服务所需的 Docker 镜像。
- 每个服务: Docker Compose 逐个处理配置文件中定义的每个服务。
- 启动容器: 对于每个服务,Docker Compose 启动相应数量的容器实例。
- 容器运行中: 容器启动并运行服务。
- 服务健康检查: Docker Compose 对每个服务执行健康检查,确保服务正常运行。
- 服务健康? : Docker Compose 检查服务是否通过健康检查。
- 继续监视: 如果服务健康,Docker Compose 继续监视服务状态。
- 报告错误并退出: 如果服务不健康,Docker Compose 报告错误并退出。
- 所有服务运行完毕: 所有服务都成功启动并运行后,工作流程结束。
3、docker-compose 功能介绍
3.1. 服务定义
使用 YAML 文件定义多个服务(容器),每个服务可以基于不同的镜像或使用构建指令从 Dockerfile 构建。Docker Compose 允许通过 docker-compose.yml
文件定义服务。以下是定义服务时可以使用的所有主要语法选项
类别 | 选项 | 描述 |
---|---|---|
服务定义基础 | image | 使用指定的镜像来启动容器。 |
build | 指定一个上下文路径和 Dockerfile 来构建镜像。 | |
context | 构建镜像时的上下文路径(相对于 Compose 文件的路径)。 | |
dockerfile | 指定构建镜像的 Dockerfile 名称(在 build 指令下)。 | |
容器运行选项 | command | 覆盖容器启动后默认执行的命令。 |
entrypoint | 覆盖容器的入口点。 | |
environment | 设置环境变量。 | |
env_file | 从文件中读取环境变量。 | |
ports | 映射端口到宿主机。 | |
volumes | 挂载卷到容器。 | |
volumes_from | 挂载其他服务的卷。 | |
links | 链接到其他服务的容器(不推荐使用,建议使用网络)。 | |
网络和依赖 | networks | 指定服务连接的网络。 |
depends_on | 定义服务依赖,确保按顺序启动。 | |
存储和卷 | volumes | 定义要挂载的卷。 |
volume_driver | 指定卷的驱动。 | |
部署和扩展 | deploy | 使用 Docker Swarm 部署配置。 |
replicas | 设置服务的副本数(Swarm 模式)。 | |
健康检查 | healthcheck | 定义健康检查指令。 |
日志记录 | logging | 配置日志记录选项。 |
资源限制 | cpus | CPU 资源限制。 |
cpu_shares | CPU 共享权重。 | |
cpu_quota | CPU 配额(在 CPU 周期内运行的时间)。 | |
mem_limit | 内存限制。 | |
mem_reservation | 内存软限制。 | |
安全选项 | security_opt | 指定容器的安全选项。 |
构建时变量 | args | 构建镜像时传递的变量。 |
隔离模式 | isolation | 设置容器的隔离模式。 |
扩展 | extra_hosts | 添加额外的 host 映射。 |
容器间通信 | domainname | 为容器设置域名。 |
hostname | 设置容器的 hostname。 | |
ipc | 设置 IPC 模式。 | |
mac_address | 为容器设置 MAC 地址。 | |
shm_size | 设置 /dev/shm 的大小。 | |
sysctls | 为 Linux 容器设置内核参数。 | |
卷挂载 | bind_mounts | 挂载宿主机的文件或目录到容器内部。 |
tmpfs | 在容器内挂载临时文件系统。 | |
容器启动和停止 | init | 使用 tini 作为容器的 init 进程。 |
oom_score_adj | 设置容器的 OOM(Out Of Memory)分数。 | |
pids_limit | 限制容器内的 PID 数量。 | |
容器重启策略 | restart | 设置容器的重启策略。 |
容器清理策略 | stop_signal | 设置容器停止时发送的信号。 |
stop_grace_period | 设置容器停止前的宽限期。 | |
容器状态检查 | read_only | 将容器的文件系统设置为只读。 |
userns_mode | 设置用户命名空间模式。 | |
构建缓存 | cache_from | 构建镜像时使用缓存。 |
服务更新 | update_config | 定义服务更新的配置。 |
rollback_config | 定义服务回滚的配置。 | |
服务状态 | status | 设置服务的状态(如:inactive)。 |
服务资源限制 | cpuset | 设置容器可以使用的 CPU 核心。 |
服务隔离级别 | isolation | 设置容器的隔离级别。 |
服务扩展配置 | placement | 定义服务在 Swarm 集群中的放置策略。 |
服务配置选项 | configs | 挂载配置到服务容器。 |
服务网络配置 | network_mode | 设置网络模式。 |
networks | 连接到一个或多个网络。 | |
服务安全性 | cap_add | 添加 Linux 内核能力。 |
cap_drop | 移除 Linux 内核能力。 | |
security_opt | 设置容器的安全性选项。 | |
服务依赖 | x-* | 添加自定义服务配置。 |
以下是完整的 docker-compose.yml
文件:
version: '3.8' # 指定 docker-compose.yml 文件的版本
services: # 定义服务列表
webapp: # 服务名称,唯一
image: my-webapp:latest # 使用指定的镜像来启动容器
build: # 指定一个上下文路径和 Dockerfile 来构建镜像
context: ./dir # 构建镜像时的上下文路径
dockerfile: Dockerfile.dev # 指定构建镜像的 Dockerfile 名称
args: # 构建镜像时传递的变量
- buildno=1
command: python app.py # 覆盖容器启动后默认执行的命令
entrypoint: /code/entrypoint.sh # 覆盖容器的入口点
environment: # 设置环境变量
- DEBUG=1
env_file: # 从文件中读取环境变量
- env_vars.env
ports: # 映射端口到宿主机
- "5000:5000"
volumes: # 挂载卷到容器
- "/var/www:/var/www"
- "data_volume:/var/data"
networks: # 指定服务连接的网络
- webnet
depends_on: # 定义服务依赖,确保按顺序启动
- db
deploy: # 使用 Docker Swarm 部署配置
replicas: 3
resources: # 定义服务资源限制
limits:
cpus: '0.50'
memory: 50M
healthcheck: # 定义健康检查指令
test: ["CMD", "curl", "-f", "http://localhost"]
interval: 1m30s
timeout: 10s
retries: 3
logging: # 配置日志记录选项
driver: syslog
options:
tag: "webapp-{{.Name}}"
isolation: "hyperv" # 设置容器的隔离模式
extra_hosts: # 添加额外的 host 映射
- "host1:192.168.1.1"
- "host2:192.168.1.2"
domainname: webapp.example.com # 为容器设置域名
hostname: webapp # 设置容器的 hostname
ipc: "host" # 设置 IPC 模式
mac_address: 02:42:ac:11:00:04 # 为容器设置 MAC 地址
shm_size: '2gb' # 设置 /dev/shm 的大小
sysctls: # 为 Linux 容器设置内核参数
- net.core.somaxconn=1024
tmpfs: /run # 在容器内挂载临时文件系统
init: true # 使用 tini 作为容器的 init 进程
oom_score_adj: 500 # 设置容器的 OOM 分数
pids_limit: 50 # 限制容器内的 PID 数量
restart: on-failure:3 # 设置容器的重启策略
stop_signal: SIGINT # 设置容器停止时发送的信号
stop_grace_period: 1m # 设置容器停止前的宽限期
read_only: true # 将容器的文件系统设置为只读
userns_mode: "host" # 设置用户命名空间模式
cache_from: # 构建镜像时使用缓存
- my-base-image:latest
update_config: # 定义服务更新的配置
parallelism: 2
delay: 10s
failure_action: continue
order: start-first
rollback_config: # 定义服务回滚的配置
parallelism: 1
delay: 10s
failure_action: pause
order: stop-first
status: inactive # 设置服务的状态(如:inactive)
cpuset: "0,1" # 设置容器可以使用的 CPU 核心
placement: # 定义服务在 Swarm 集群中的放置策略
constraints: [node.role == manager]
configs: # 挂载配置到服务容器
- myconfig
network_mode: "host" # 设置网络模式
cap_add:
- ALL # 添加 Linux 内核能力
cap_drop:
- NET_ADMIN # 移除 Linux 内核能力
security_opt: # 设置容器的安全性选项
- label:user:USER
- label:role:ROLE
db:
image: postgres:latest # 使用指定的镜像来启动容器
volumes: # 定义要挂载的卷
- db_data:/var/lib/postgresql/data
volumes: # 定义卷
data_volume:
db_data:
networks: # 定义网络
webnet:
configs: # 定义配置
myconfig:
file: ./config.txt
name: my_config
2. 一键启动和停止
- 通过
docker-compose up
和docker-compose down
命令,可以一键启动和停止所有服务。
3. 依赖管理
可以定义服务之间的依赖关系,确保服务按照正确的顺序启动和停止。
图解释:
- docker-compose.yml: Docker Compose 的配置文件,定义了所有服务、网络和卷。
- 服务A、服务B、服务C: 这些是配置文件中定义的服务。
- 网络: 由 Docker Compose 管理的网络,用于连接所有服务,使它们能够互相通信。
- 依赖: 服务之间的依赖关系,确保服务按照正确的顺序启动和停止。例如,服务B 依赖于 服务C,服务C 依赖于 服务D。
version: '3.8' # 指定 Docker Compose 文件的版本
services:
db:
image: postgres:13 # 使用 PostgreSQL 13 镜像
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: dbname
volumes:
- db-data:/var/lib/postgresql/data # 定义一个卷,并挂载到容器的 PostgreSQL 数据目录
web:
image: nginx:alpine # 使用 Nginx 的 alpine 版本镜像
depends_on: # 定义依赖关系
- db # Web 服务依赖于 db 服务
ports:
- "80:80" # 将容器的 80 端口映射到宿主机的 80 端口
volumes:
db-data: # 定义一个命名卷
networks:
default: # 默认网络配置
driver: bridge # 使用桥接网络
配置说明
- db 服务:这是一个数据库服务,使用
postgres:13
镜像。环境变量POSTGRES_USER
、POSTGRES_PASSWORD
和POSTGRES_DB
用于初始化数据库配置。一个命名卷db-data
被挂载到容器的 PostgreSQL 数据目录,用于数据持久化。 - web 服务:这是一个 Web 服务,使用
nginx:alpine
镜像。它定义了对db
服务的依赖,使用depends_on
关键字。这意味着在启动 Web 服务之前,Docker Compose 会确保先启动数据库服务。 - volumes:
- db-data:这是一个命名卷,用于持久化数据库服务的数据。
- networks:
- default:定义了一个默认的桥接网络,所有服务都会连接到这个网络,从而实现服务间的通信。
如何工作
- 启动服务:运行
docker-compose up
命令时,Docker Compose 会根据depends_on
关键字来决定服务的启动顺序。在这个例子中,db
服务会首先启动。 - 服务发现:一旦
db
服务启动,web
服务就可以通过服务名称db
来访问数据库服务。 - 端口映射:
web
服务的 80 端口被映射到宿主机的 80 端口,使得可以通过宿主机的 IP 地址或域名来访问 Web 应用。
4. 网络管理
在 Docker Compose 中,网络管理是一个关键特性,它允许不同容器之间相互发现和通信。Docker Compose 提供了强大的网络功能,可以自动配置服务之间的网络,使得容器像在同一个主机上一样轻松通信。
4.1. 默认网络
当运行 Docker Compose 时,它会自动创建一个默认网络,所有服务都会连接到这个网络,除非明确指定了其他网络。默认网络允许服务之间通过服务名称进行通信。
4.2. 自定义网络
除了默认网络,还可以创建自定义网络,以实现更复杂的网络拓扑结构或隔离特定的服务。
创建自定义网络
在 docker-compose.yml
文件中,定义一个或多个网络:
version: '3.8' # 指定 Docker Compose 文件的版本
services:
web:
image: "nginx:alpine" # 使用 Nginx 的 Alpine 版本镜像
ports:
- "80:80" # 将容器的 80 端口映射到宿主机的 80 端口
networks:
- webnet # 将 Web 服务连接到 webnet 网络
db:
image: "postgres:alpine" # 使用 PostgreSQL 的 Alpine 版本镜像
environment:
POSTGRES_DB: mydatabase # 设置数据库名
POSTGRES_USER: user # 设置数据库用户
POSTGRES_PASSWORD: password # 设置数据库密码
networks:
- dbnet # 将 DB 服务连接到 dbnet 网络
networks:
webnet: # 定义 webnet 网络
dbnet: # 定义 dbnet 网络
此例子中,我们定义了两个网络 webnet
和 dbnet
。web
服务连接到了 webnet
网络,而 db
服务连接到了 dbnet
网络。
使用网络
服务可以通过网络名称来发现和访问其他服务。例如,如果 web
服务需要访问 db
服务,它可以通过网络名称来实现:
services:
web:
image: "nginx:alpine"
networks:
- webnet
- dbnet
# Web 服务可以使用 dbnet 网络来访问 db 服务
db:
image: "postgres:alpine"
networks:
- dbnet
networks:
webnet:
dbnet:
在这个修改后的例子中,web
服务同时连接到了 webnet
和 dbnet
网络,因此它可以通过 db
服务的名称来访问数据库。
DATABASE_URL=db:5432/mydatabase
这里的 db
是数据库服务的名称,5432
是 PostgreSQL 的默认端口,mydatabase
是数据库名。
4.3. 网络模式
Docker Compose 支持多种网络模式,包括桥接、宿主机、覆盖和 Macvlan。每种模式都有其特定的用例:
- 桥接(bridge) :默认模式,创建一个虚拟的网络环境,容器可以通过网络地址相互通信。
- 宿主机(host) :容器将使用宿主机的网络栈。
- 覆盖(overlay) :用于跨多个 Docker 守护进程的容器通信,常见于 Docker Swarm 模式。
- Macvlan:将容器直接连接到物理网络,使容器拥有物理网络上的真实 MAC 地址。
4.4. 网络的动态发现
Docker Compose 允许服务动态发现其他服务,只需通过服务名称即可实现通信。这种发现机制简化了服务间的连接和通信。
4.5. 网络的持久性
定义的网络在 Docker Compose 栈的生命周期内是持久的,即使容器停止或重启,网络依然存在。
其他内容在第二篇文章《图解Docker Compose 架构设计分析与全攻略:构建、扩展和综合案例(第二部分)》中。。。
原创不易,请给作者打赏,您的支持是我坚持原创和分享的最大动力! 文章有帮助的话,在看,转发吧。
谢谢支持哟 (__)