前言
本章,您将学习 Docker Compose 的相关内容。
Docker Compose:Docker 公司官方的开源项目之一,负责并实现对 Docker 容器集群的快速编排,其作用类似于现实生活中管理项目的项目经理。
您可以使用 Docker Compose 管理多个容器实例,让它们组成一个大型应用或项目。在使用 Docker Compose 之前,您需要定义一个 YAML 格式的配置文件,其内容为 容器之间的调用关系,后续使用单个命令就能快速启动或关闭这些容器实例。
Q:什么是容器编排?
「对多个容器实例进行部署、管理、监控的一种自动化流程技术」
由这门技术衍生出相关的容器编排工具,常见的有:
- Kubermetes - 对于那些大型的复杂项目,K8S 是一个不错的选择
- Docker Compose 或 Docker Swarm - 对于单个主机的、简单的、小型的开发环境而言,它是一个不错的选择
- Mesos
了解 YAML 格式的语法规范
语法规范有:
- 在规范写法上,开头行以 "---" 开头,结尾行以 "…" 结尾。有时,开头行的 "---" 与结尾行的 "..." 可以被省略,但推荐不要省略它们。
- "#" 开头的代表注释行
- 缩进不能用 TAB 键(因文本编辑器的不同,一个 TAB 等于两个或四个空格,所以并不是说完全不能使用 TAB 键);
- 相同级别的缩进必须一样或者说对齐;
- 文本内容严格区分大小写,键值对(key/value)也是一样的要求;
- 文件的扩展名为 yml 或者 yaml;
- 键值对用 ":" 表示,在":"后面需要加一个空格;
- 数组(列表)用 "-" 表示,也需要在 "-" 后面加一个空格;
- 单引号不转义特殊字符,即只会输出字符串本身,例如
text: 'line1 \n line2'这样的书写并不会换行,双引号会对一些特殊的字符进行转义,例如text: "line1 \n line2"会换行
YAML 数据类型
对象 - 也被称为字典(Dictionary)或映射(mapping),它是键值对的集合
数组 - 也被称为列表(list),一组按照次序排列的值
纯量(scalars) - 单个且不可再分的值
不同的数据类型之间可以相互嵌套混用。
对象的写法:
---
# 第一种写法
key1: value1
key2: value2
key3: value3
# 第二种写法
{key1: "value1",key2: "value2",key3: "value3"}
...
数组的写法:
---
# 第一种写法
- value1
- value2
- value3
# 第二种写法
[value1,value2,value3]
...
YAML 在线语法检测工具 —— https://onlineyamltools.com/validate-yaml
Docker Compose
安装 Docker Compose
当初使用官方的 Docker 存储库已经安装了 Docker Compose(dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin)。
Shell > docker compose version
Docker Compose version v2.27.0
Docker Compose 中的概念
配置文件 - 通常为 compose.yaml 或 docker-compose.yaml,对配置文件的名称没有特别的要求
服务(service) - 指一个又一个的容器实例
项目(project) - 由一组关联的容器实例组成的完整业务单元,需要在 YAML 配置文件中定义
Docker Compose 使用步骤
- 首先通过 Dockerfile 构建出实际需要的镜像,请参阅前面的内容
- 编写 YAML 配置文件,定义所需要的容器实例以及它们的关联关系
- 使用
docker compose up命令创建并启动所有的容器实例
docker compose 命令
该命令的用法为 —— docker compose [option] COMMAND
COMMAND 可以是:
- build - 构建或重新构建 service
- config - 检查 YAML 配置文件的语法
- cp - 在本地文件系统与 service 之间复制文件或目录
- create - 针对 servcie 创建容器
- down - 停止并移除由
docker compose up命令创建的容器、网络和数据卷,相当于刷新。 - events - 从容器中接受实时事件
- exec - 进入到容器实例的内部
- images - 列出创建容器所使用的镜像
- kill - 用于停止正在运行中的 service 容器
- logs - 查看 service 容器的日志输出
- ls - 列出正在运行的 compose 项目
- pause - 暂停运行中的 service 容器
- port - 显示某个容器端口所映射的公共端口
- ps - 列出所有被管理容器实例的状态
- pull - 拉取 service 所依赖的镜像
- push - 推送 service 所依赖的镜像
- restart - 重启项目中的 service
- rm - 删除所有停止状态的 service 容器,默认情况下,不会删除容器挂载的数据卷。
- run - 在指定的 service 上执行一个命令
- scale - 扩大或缩小 service 容器实例的数量
- start - 启动管理的 service 容器
- stats - 查看 service 容器占用资源的情况
- stop - 停止项目中的 service
- top - 显示正在运行的进程
- up - 创建并启动 service 容器
- version - 查看版本
针对单个 COMMAND,您也可以使用 docker compose COMMAND --help 查阅更多的帮助信息,比如 —— docker compose up --help
Compose 书写规范
前面提到,我们需要定义一个 YAML 格式的配置文件,这只是格式上的要求,但对于具体文件内容而言,需要使用各种各样的 元素(有些中文资料中也称 关键字 或 字段 或 参数 或 属性)。
名称顶层元素(Name top-level element)
元素有:
name- 定义项目的名称
服务顶层元素(Services top-level elements)
常见元素有:
-
services- 定义所有的 service 信息,其下一级的 key 即表示第一个 service 的名称。 -
attach- 是否收集 services 的日志,默认值为 true -
cgroup- 指定要加入哪一个 cgroup 命名空间,值可以是:- host
- private
-
command- 使用该元素的值来覆盖镜像中的默认命令(例如 Dockerfile 当中的 CMD 指令) -
container_name- 使用自定义的容器实例名称,其值为字符串。请注意!该字符串需要唯一 -
depends_on- 指定 servcie 之间的启动顺序与依赖关系 -
dns- 容器实例要使用的自定义 DNS,可以是单个值,也可以是列表值,例如dns: 8.8.8.8 dns: - 8.8.8.8 - 9.9.9.9 -
env_file- 指定环境变量文件并向容器传递变量。变量文件的说明:- 文件名称以 .env 后缀作为文件标识
- 变量文件应该为相对路径
- 以 # 开头的表示注释行
- 格式为
VAR=value,变量名称需要大写 - 双引号值支持常见的特殊字符转义,包括
\t、\r、\n
-
environment- 指定环境变量。当为容器同时使用变量文件与environment元素时,enviriment 元素优先生效。支持两种语法:--- # 映射语法 environment: RACK_ENV: development SHOW: "true" USER_INPUT: # 数组语法 environment: - RACK_ENV=development - SHOW=true - USER_INPUT ... -
group_add- 指定 service 运行的容器应该加入的一个或多个预先存在的组,比如:services: myservice: image: myimage group_add: - mail该元素仅针对 GNU/Linux 生效,需要注意的是该组必须预先存在于 docker 容器上。
-
hostname- 设置容器的主机名 -
image- 指定镜像 -
init- 是否在容器内运行一个 init 进程(PID 为1),该进程可以转发信号并获取子进程的状态。 -
labels- 为 service 设置 docker 容器的元数据。书写形式可以是数组或映射,例如:# 数组 labels: - "com.example.description=Accounting webapp" - "com.example.department=Finance" - "com.example.label-with-empty-value" # 映射 labels: com.example.description: "Accounting webapp" com.example.department: "Finance" com.example.label-with-empty-value: "" -
logging- 配置 service 的日志。例如:services: myweb: image: nginx:latest logging: driver: json-file options: max-size: "20m" max-file: "3"driver 可以是 json-file、syslog、journald 等,不同的 driver 可以使用不同的 options,参阅这里 —— https://docs.docker.com/config/containers/logging/configure/#configure-the-default-logging-driver
-
network_mode- 设置 service 容器的网络模式,关于 docker 网络,请参阅上一篇文章 -
networks- 定义 service 容器添加到的网络,网络部分参阅下面的 网络顶层元素(Networks top-level elements) -
aliases- 为 service 设置别名,您可以为同一个 service 设置多个别名,但是请注意!别名仅在同一个网络中生效,另外,不能为不同的 service 设置相同的别名。 -
ports- 建立宿主机与容器实例之间的端口映射关系,与docker run命令中的 -p 选项相同(冒号左边为宿主机的端口或端口范围,冒号右边为容器实例的端口或端口范围)。示例写法:ports: - "3000" # 暴露容器实例的 3000 端口 - "3000-3005" # 暴露容器实例的 3000 到 3005 端口 - "8000:8000" - "9090-9091:8080-8081" - "49100:22" - "8000-9000:80" - "127.0.0.1:8001:8001" - "127.0.0.1:5000-5010:5000-5010" - "6060:6060/udp" -
privileged- 与docker run中的--privileged=true一样,表示容器内的 root 是真正意义上 root 用户。 -
read_only- 设置容器数据卷的权限,关于数据卷的基础内容,请参阅前面的文章 -
restart- 设置容器实例的重启策略,与docker run中的--restart选项一样,其值可以是 no、always、on-failure[:max-retries]、unless-stoppedrestart: "no" restart: always restart: on-failure restart: on-failure:3 restart: unless-stopped -
sysctls- 与docker run中的--sysctl选项一样,用来给容器实例设置 Linux 内核的参数。比如您要在容器实例中开启 ipv4 的转发功能。services: my_service: image: my_image sysctls: - net.ipv4.ip_forward=1 -
volumes- 设置数据卷(数据卷:一种将容器内的数据持久化备份到宿主机的方式,也就是目录映射或文件映射)。services: backend: image: example/backend volumes: - type: bind source: /var/run/postgres/postgres.sock target: /var/run/postgres/postgres.sock - type: bind source: /host/dir/ target: /container/dir/ read_only: false -
volumes_from- 继承来自于其他容器的数据卷规则,也就是docker run当中的--volumes-from选项
网络顶层元素(Networks top-level elements)
网络能够使 service 相互之间进行通信。默认情况下,compose 会为您的应用程序设置一个单独的网络,service 的每个容器都会加入该默认网络,加入之后,各个容器既可以通过网络进行相互访问,也可以通过 service 的名称进行发现。
基本示例如下所示,在这里我们定义了 mynetwork 这个网络,并且 service1 和 service2 都加入或连接到了该网络中。
---
services:
service1:
image: service1image
networks:
- mynetwork
service2:
image: service2image
networks:
- mynetwork
networks:
mynetwork:
...
高级示例如下所示,我们还可以定义网络相关的 driver 、子网等。
---
services:
service1:
image: service1image
networks:
mynetwork:
aliases:
- alias1
- alias2
networks:
mynetwork:
driver: customdriver
ipam:
config:
- subnet: 172.16.0.0/24
...
在这个例子中,service1 使用了 mynetwork 这个网络,且该网络在该 service 上有两个别名。
相关的元素(属性):
driver- 值可以是 bridge、host、none 等driver_opts- driver 相关的选项enable_ipv6- 是否开启 IPv6ipam- 自定义网络配置管理,这是一个由具有多个可选属性的键值对组成。driverconfig- 配置元素列表subnet- 定义子网(网段)ip_rangegateway- IPv4 或 IPv6 的网关aux_addresses- 主机名与 IP 地址的映射关系
options
---
networks:
mynet1:
ipam:
driver: default
config:
- subnet: 172.28.0.0/16
ip_range: 172.28.5.0/24
gateway: 172.28.5.254
aux_addresses:
host1: 172.28.1.5
host2: 172.28.1.6
host3: 172.28.1.7
options:
foo: bar
baz: "0"
...
数据卷顶层元素(Volumes top-level elements)
示例如下所示:
---
services:
webapp:
image: my-webapp:latest
volumes:
- type: volume
source: my_data_volume
target: /app/data
volumes:
my_data_volume:
...
数据类型为 volume 而不是 bind ,Docker Compose 会自动管理管理名称为 my_data_volume 的卷。
相关的元素(属性):
driver- 指定应该使用哪个数据卷驱动driver_opts- 相关数据卷驱动的选项
配置顶层元素(Configs top-level elements)
我们可以为相应的 service 引入外部的配置文件
相关元素(属性):
file- 指定配置文件,必须为相对路径external- 表示这个配置文件是外部管理的,它不由 Docker Compose 创建、管理或删除
通过相对路径的方式查找配置文件:
---
services:
myhttpd:
image: httpd:latest
configs:
- http_config
configs:
http_config:
file: ./httpd.conf
...
机密底层元素(Secrets top-level elements)
这部分主要定义一些安全相关的内容,比如用户的凭证(密码和令牌等)。
---
services:
myservice:
image: myimage
secrets:
- my_secret
secrets:
my_secret:
file: ./my_secret.txt
...










