Compose
编排功能,是复杂系统是否具有灵活可操作性的关键。
特别在 Docker 应用场景中,编排意味着用户可以灵活地对各种容器资源实现定义和管理。
Compose 作为 Docker 官方编排工具,其重要性不言而喻,它可以让用户通过编写一个简单的模板文件,快速地创建和管理基于 Docker 容器的应用集群。
https://github.com/docker/compose/
https://docs.docker.com/compose/
https://github.com/docker/awesome-compose
安装
依赖 python3
1 2 |
|
Compose 简介
Compose 项目是 Docker 官方的开源项目,负责实现对基于 Docker 容器的多应用服务的快速编排。
Compose 定位是“定义和运行多个 Docker 容器的应用”,其前身是开源项目 Fig,目前仍然兼容 Fig 格式的模板文件
我们已经知道使用一个 Dockerfile 模板文件,可以让用户很方便地定义一个单独的应用容器。
然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。
例如要实现一个 Web 项目,除了 Web 服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括前端的负载均衡容器等。
Compose 恰好满足了这样的需求。
它允许用户通过一个单独的docker-compose.yml
模板文件(YAML 格式)来定义一组相关联的应用容器为一个服务栈。
Compose 中有几个重要的概念:
- 任务(task): 一个容器被称为一个任务。任务拥有独一无二的 ID,在同一个服务中的多个任务序号依次递增。
- 服务(service): 某个相同应用镜像的容器副本集合,一个服务可以横向扩展为多个容器实例
- 服务栈(stack): 由多个服务组成,相互配合完成特定业务,如 Web 应用服务、数据库服务共同构成 Web 服务栈,一般由一个
docker-compose.yml
文件定义
Compose 的默认管理对象是服务栈,通过子命令对栈中的多个服务进行便捷的生命周期管理。
Compose 项目由 Python 编写,实现上调用了 Docker 服务提供的 API 来对容器进行管理。
因此,只要所操作的平台支持 Docker API,就可以在其上利用 Compose 来进行编排管理
Compose 模板文件
模板文件是使用 Compose 的核心,涉及的指令关键字也比较多。
但是不用担心,这里的大部分指令与 docker [container] create | run 相关参数的含义都是类似的
默认的模板文件名称为docker-compose.yml
,格式为 YAML 格式
版本 1 的 Compose 文件结构十分简单,每个顶级元素为服务名称,次级元素为服务容器的配置信息,例如:
1 2 3 4 5 6 |
|
版本 2 和 3 扩展了 Compose 的语法,同时尽量保持跟旧版本的兼容,除了可以声明网络和存储信息外,最大的不同一是添加了版本信息,另一个是需要将所有的服务放到 services
根下面
例如,上面例子改写为版本 3,并启动资源限制,内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
注意每个服务都必须通过 image 指令指定镜像或 build 指令(需要 Dockerfile)等来自动构建生成镜像
如果使用 build 指令,在 Dockerfile 中设置的选项(例如:CMD、EXPOSE、VOLUME、ENV 等)将会自动被获取,无须在docker-compose.yml
中再次设置
Compose 模板文件主要命令
命令 | 功能 |
---|---|
build | 指定 Dockerfile 所在文件夹的路径 |
cap_add, cap_drop | 指定容器的内核能力(capacity)分配 |
command | 覆盖容器启动后默认执行的命令 |
cgroup_parent | 指定父 cgroup 组,意味着将继承该组的资源限制。目前不支持 Swarm 模式 |
container_name | 指定容器名称。目前不支持 Swarm 模式 |
devices | 指定设备映射关系。不支持 Swarm 模式 |
depends_on | 指定多个服务之间的依赖关系 |
dns | 自定义 DNS 服务器 |
dns_search | 配置 DNS 搜索域 |
dockerfile | 指定格外的编译镜像的 Dockerfile 文件 |
entrypoint | 覆盖容器中默认的入口命令 |
env_file | 从文件中获取环境变量 |
enviroment | 设置环境变量 |
expose | 暴露端口,但不映射到宿主机,只被连接的服务访问 |
extends | 基于其他模板文件进行扩展 |
external_links | 链接到 docker-compose.yml 外部的容器 |
extra_hosts | 指定额外的 host 名称映射信息 |
healthcheck | 指定检测应用健康状态的机制 |
image | 指定为镜像名称或镜像 ID |
isolation | 配置容器隔离的机制v |
labels | 为容器添加 Docker 元数据信息 |
links | 链接到其他服务中的容器 |
logging | 根日志相关的配置 |
network_mode | 设置网络模式 |
networks | 所加入的网络 |
pid | 根主机系统共享进程命名空间 |
ports | 暴露端口信息 |
secrets | 配置应用的秘密数据 |
security_opt | 指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等) |
stop_grace_period | 指定应用停止时,容器的优雅停止期限。过期后则通过 SIGKILL 强制退出。默认为 10s |
stop_signal | 指定停止容器的信号 |
sysctls | 配置容器内的内核参数。目前不支持 Swarm 模式 |
ulimits | 指定容器的 ulimits 限制值 |
userns_mode | 指定用户命名空间模式。目前不支持 Swarm 模式 |
volumes | 数据卷所挂载路径设置 |
restart | 指定重启策略 |
deploy | 指定部署和运行时的容器相关配置。该命令只在 Swarm 模式下生效,且只支持 dokcer stack deploy 命令部署 |
下面介绍部分指令的用法。
build
指定 Dockerfile 所在文件夹的路径(可以是绝对路径,或者相对docker-compose.yml
文件的路径)。
Compose 将会到用它自动构建应用镜像,然后使用这个镜像,例如:
1 2 3 4 |
|
build 指令还可以指定创建镜像的上下文、Dockerfile 路径、标签、Shm 大小、参数和缓存来源等,例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
cap_add, cap_drop
指定容器的内核能力(capacity)分配。
例如,让容器拥有所有能力可以指定为:
1 2 |
|
去掉 NET_ADMIN 能力可以指定为:
1 2 |
|
command
覆盖容器启动后默认执行的命令,可以为字符串格式或 JSON 数组格式。例如:
1 |
|
或者:
1 |
|
configs
在 Docker Swarm 模式下,可以通过 configs 来管理和访问非敏感的配置信息。支持从文件读取或外部读取。例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
cgroup_parent
指定父 cgroup 组,意味着将继承该组的资源限制。目前不支持 Swarm 模式中使用。
例如,创建了一个 cgroup 组名称为 cgroups_1:
1 |
|
container_name
指定容器名称。默认将会使用“项目名称_服务名称_序号”这样的格式。
目前不支持在 Swarm 模式中使用。例如:
1 |
|
需要注意,指定容器名称后,该服务将无法进行扩展,因为 Docker 不允许多个容器实例重名
devices
指定设备映射关系,不支持 Swarm 模式,例如:
1 2 |
|
depends_on
指定多个服务之间的依赖关系。启动时,会先启动被依赖服务。例如,可以指定依赖于 db 服务
1 |
|
dns
自定义 DNS 服务器。可以是一个值,也可以是一个列表。例如:
1 2 3 4 |
|
dns_search
配置 DNS 搜索域。可以是一个值,可以是一个列表。例如:
1 2 3 4 |
|
dockerfile
如果需要,指定额外的编译镜像的 Dockerfile 文件,可以通过该指令来指定。例如:
1 |
|
注意:该指令不能跟 image 同时使用,否则 Compose 将不知道根据哪个指令来生成最终的服务镜像。
entrypoint
覆盖容器中默认的入口命令。注意,也会取消掉镜像中指定的入口命令和默认启动命令。
例如,覆盖为新的入口明林:
1 |
|
env_file
从文件中获取环境变量,可以为单独的文件路径或列表。
如果通过 docker-compose -f FILE 方式来指定 Compose 模板文件,则 env_file 中变量的路径会基于模板文件路径。
如果有变量名称与 environment 指令冲突,则按照惯例,以后者为准。例如:
1 2 3 4 5 |
|
环境变量文件中每一行必须符合格式,支持#
开头的注释行,例如:
1 2 |
|
enviroment
设置环境变量,可以使用数组或字典两种格式。
只给定名称的变量会自动获取运行 Compose 主机上对应变量的值,可以用来防止泄漏不必要的数据。例如:
1 2 3 |
|
或者:
1 2 3 |
|
注意,如果变量名称或者值中用到 true|false,yes|no 等表达布尔含义的词汇,最好放到引号里,避免 YAML 自动解析某些内容为对应的布尔语义
expose
暴露端口,但不映射宿主机,只被连接的服务访问。
仅可以指定内部端口为参数,如下所示:
1 2 3 |
|
extends
基于其他模板文件进行扩展。
例如,我们已经有了一个 webapp 服务,定义一个基础模板文件为 common.yml,如下所示:
1 2 3 4 5 6 |
|
再编写一个新的 development.yml 文件,使用 common.yml 中的 webapp 服务进行扩展:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
后者会自动继承 common.yml 中的 webapp 服务及环境变量定义。使用 extends 需要注意以下两点:
- 要避免出现循环依赖,例如 A 依赖 B,B 依赖 C,C 反过来依赖 A 的 情况。
- extends 不会继承 links 和 volumes_from 中定义的容器和数据卷资源
一般情况下,推荐在基础模板中只定义一些可以共享的镜像和环境变量,在扩展模板中具体指定应用变量、链接、数据卷等信息。
external_links
链接到 docker-compose.yml 外部的容器,甚至并非 Compose 管理的外部容器。参数格式跟 links 类似
1 2 3 4 |
|
extra_hosts
类似 Docker 中的 --add-host 参数,指定额外的 host 名称映射信息。
例如:
1 2 3 |
|
会在启动后的服务容器中/etc/hosts
文件中添加如下两条条目。
1 2 |
|
healthcheck
指定检测应用健康状态的机制,包括检测方法(test)、间隔(interval)、超时(timeout)、重试次数(retries)、启动等待时间(start_period)等。
例如,指定检测方法为访问 8080 端口,间隔为 30 秒,超时为 15 秒,重试 3 次,启动后等待 30 秒再做检查
1 2 3 4 5 |
|
image
指定为镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试去拉取这个镜像。
例如:
1 2 3 |
|
isolation
配置容器隔离的机制,包括 default、process 和 hyperv
labels
为容器添加 Docker 元数据(metadata)信息。例如可以为容器添加辅助说明信息
1 2 3 4 |
|
links
注意:links 命令属于旧的用法,可能在后续版本中被移除
链接到其他服务中的容器。使用服务名称(同时作为别名)或服务名称:服务别名(SERVICE:ALIAS)格式都可以
1 2 3 4 |
|
使用的别名将会自动在服务容器中的/etc/hosts
里创建。例如:
1 2 3 |
|
被链接容器中相应的环境变量也将被创建
logging
跟日志相关的配置,包括一些列子配置
logging.driver: 类似于 Docker 中的 --log--driver 参数,指定日志驱动类型。
目前支持三种日志驱动类型:
1 2 3 |
|
logging.options: 日志驱动的相关参数,例如:
1 2 3 4 |
|
或:
1 2 3 4 5 |
|
network_mode
设置网络模式。使用和 docker client 的 --net 参数一样的值。
1 2 3 4 5 |
|
networks
所加入的网络。需要在顶级的 networks 字段中定义具体的网络信息。
例如,指定 web 服务的网络为 web_net,并添加服务在网络中别名为 web_app
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
pid
跟主机系统共享进程命名空间。
打开该选项的容器之间,以及容器和宿主系统之间可以通过进程 ID 来相互访问和操作。
1 |
|
ports
暴露端口信息。
使用宿主:容器(HOST:CONTAINER)格式,或者仅仅指定容器的端口(宿主将会随机选择端口)都可以
1 2 3 4 5 |
|
或者:
1 2 3 4 5 |
|
注意:
当使用 HOST:CONTAINER 格式来映射端口时,如果你使用的容器端口小于 60 并且没放到引号里,可能会得到错误结果,因为 YAML 会自动解析 xx:yy 这种数字格式为 60 进制。
为避免出现这种问题,建议数字串都采用引号包括起来的字符串格式
secrets
配置应用的秘密数据。
可以指定来源秘密、挂载后名称、权限等。
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
security_opt
指定容器模板标签(label)机制的默认属性(用户、角色、类型、级别等)
例如,配置标签的用户名和角色名
1 2 3 |
|
stop_grace_period
指定应用停止时,容器的优雅停止期限。过期后则通过 SIGKILL 强制退出。
默认值为 10s
stop_signal
指定停止容器的信号,默认为 SIGTERM
sysctls
配置容器内的内核参数。Swarm 模式中不支持
例如,指定连接数为 4096 和开启 TCP 的 syncookies:
1 2 3 |
|
ulimits
指定容器的 ulimits 限制值
例如,指定最大进程数为 65535,指定文件句柄数为 20000(软限制,应用可以随时修改,不能超过硬限制)和 40000(系统硬限制,只能 root 用户提高)
1 2 3 4 5 |
|
userns_mode
指定用户命名空间模式。Swarm 模式不支持。例如,使用主机上的用户命名空间:
1 |
|
volumes
数据卷所挂载路径设置。
可以设置宿主机路径(HOST:CONTAINER)或加上访问模式(HOST:CONTAINER:ro)
支持 driver、derver_opts、external、labels、name 等子配置
该指令中路径支持相对路径。例如
1 2 3 4 |
|
或者可以使用更详细的语法格式:
1 2 3 4 5 6 7 8 |
|
restart
指定重启策略,可以为 no(不重启)、always(总是)、on-failure(失败时)、unless-stopped(除非停止)
注意 Swarm 模式下要使用 restart_policy。在生产环境中推荐配置为 always 或者 unless-stopped
例如,配置除非停止:
1 |
|
deploy
指定部署和运行时的容器相关配置。该命令只在 Swarm 模式下生效,且只支持 docker stack deploy 命令部署
例如:
1 2 3 4 5 6 7 8 9 10 11 |
|
deploy 命令中包括 endpoint_mode、labels、mode、placement、replicas、resources、restart_policy、update_config 等配置项
(1) endpoint_mode
指定服务端点模式。包括两种类型:
- vip:Swarm 分配一个前段的虚拟地址,客户端通过给地址访问服务,而无须关心后端的应用容器个数
- dnsrr:Swarm 分配一个域名给服务,用户访问域名时候会按照轮流顺序返回容器地址
例如:
1 2 3 4 5 6 7 8 |
|
(2) labels
指定服务的标签。注意标签信息不会影响到服务内的容器
例如:
1 2 3 4 5 6 7 |
|
(3) mode
定义容器副本模式,可以为
- global: 每个 Swarm 节点上只有一个该应用容器
- replicated: 整个集群中存在指定份数的应用容器副本,默认值
例如,指定集群中 web 应用保持 3 个副本:
1 2 3 4 5 6 7 |
|
(4) placement
定义容器放置的限制(constraints)和配置(preferences)。
限制可以指定只有符合要求的节点上才能运行该应用容器;配置可以指定容器的分配策略。
例如,指定集群中 web 应用容器只存在于高安全的节点上,并且在带有 zone 标签的节点上均匀分配
1 2 3 4 5 6 7 8 9 10 |
|
(5) replicas
容器副本模式为默认的 replicated 时,指定副本的个数
(6) resources
指定使用资源的限制,包括 CPU、内存资源等。
例如,指定应用使用的 CPU 份额为 10% 到 25%,内存为 200 MB 到 500 MB
1 2 3 4 5 6 7 8 9 10 11 12 |
|
(7) restart_policy
指定容器重启的策略。例如,指定重启策略为失败时重启,等待 2s,重启最多尝试 3 次,检测状态的等待时间为 10s
1 2 3 4 5 6 7 8 9 10 |
|
(8) update_config
有些时候需要对容器内容进行更新,可以使用该配置指定升级的行为。
包括每次升级多少个容器(parallelism)、升级的延迟(delay)、升级失败后的行动(failure_action)、检测升级后状态的等待时间(monitor)、升级后容忍的最大失败比例(max_failure_ratio)、升级顺序(order)等。
例如,指定每次更新两个容器、更新等待 10s、先停止就容器再升级
1 2 3 4 5 6 7 8 9 10 |
|
其他指令
此外,还有包括 domainname、hostname、ipc、mac_address、privileged、read_only、shm_size、stdin_open、tty、user、working_dir 等指令,基本跟 docker-run 中对应参数的功能一致。
例如,指定容器中工作目录:
1 |
|
指定容器中搜索域名、主机名、mac 地址等:
1 2 3 |
|
允许容器中运行一些特权命令:
1 |
|
读取环境变量
从 1.5.0 版本开始,Compose 模板文件支持动态读取主机的系统环境变量。
例如,下面的 Compose 文件将从运行它的环境中读取变量 ${MONGO_VERSION}
的值(不指定时则采用默认值 3.2),并写入执行的指令中。
1 2 |
|
如果直接执行 docker-compose up 则会启动一个 mongo:3.2 镜像的容器;
如果执行 MONGO_VERSION=2.8 docker-compose up 则会启动一个 mongo:2.8 镜像的容器
扩展特性
从 3.4 开始,Compose 还支持用户自定义的扩展字段。
利用 YAML 语法里的锚点引用功能来引用自定义字段内容。例如:
1 2 3 4 5 6 7 8 9 10 11 |
|
Compose 命令说明
对于 Compose 来说,大部分命令的对象既可以是项目本身,也可以指定为项目中的服务或容器。
网络
https://docs.docker.com/compose/networking/
links
Links allow you to define extra aliases by which a service is reachable from another service.
They are not required to enable services to communicate - by default, any service can reach any other service at that service’s name.
In the following example, db
is reachable from web
at the hostnames db
and database
:
1 2 3 4 5 6 7 8 9 |
|