一、简介

服务是应用程序中计算资源的抽象定义,可以独立于其他组件进行扩展或替换。服务由一组容器支持,平台根据复制需求和放置约束运行这些容器。由于服务由容器支持,因此它们由 Docker 镜像和一组运行时参数定义。服务中的所有容器都是使用这些参数创建的相同实例。

一个 Compose 文件必须声明一个名为 services 的顶级元素,该元素是一个 map 映射,其键是服务名称的字符串表示,其值是服务定义。服务定义包含应用于每个服务容器的配置。

每个服务还可以包含一个 build 部分,该部分定义如何为服务创建 Docker 镜像。Compose 支持使用此服务定义来构建 Docker 镜像。如果不使用 build,它将被忽略,并且 Compose 文件仍然被视为有效。

每个服务定义了运行其容器的运行时约束和要求。deploy 部分将这些约束分组,并允许平台调整部署策略,以最好地匹配容器的需求和可用资源。部署是 Compose 规范的一个可选项,如果未实现,deploy 部分将被忽略,Compose 文件仍然被视为有效。

二、属性

1、image

image 属性指定了启动容器的镜像。

image 属性的值必须遵从一定的格式:[<registry>/][<project>/]<image>[:<tag>|@<digest>]

如果在本地没有找到镜像,Compose 程序将尝试基于 pull_policy 属性的配置来拉取镜像。如果你也在使用 Compose 构建规范,则可以使用其他选项来控制拉取镜像和从源代码构建镜像的优先级。然而,拉取镜像是默认行为。

只要声明了 build 属性,Compose 文件中就可以省略 image。如果你没有使用 Compose 构建规范,而 Compose 文件中又缺少 image,那么 Compose 将无法工作。

2、hostname

hostname 属性声明了一个用于服务容器的自定义主机名。它必须是有效的 RFC 1123 主机名。

3、environment

environment 属性定义了在容器中设置的环境变量。environment 可以使用数组或映射(map)。

任何布尔值(如 true, false, yes, no)应该用引号括起来,以确保它们不会被 YAML 解析器转换为 TrueFalse

环境变量可以通过单个键声明(等号后没有值)。在这种情况下,Compose 依赖于你来解析这个值。如果值没有被解析,变量将被取消设置,并从服务容器环境中移除。

Map 示例:

1
2
3
4
environment:
RACK_ENV: development
SHOW: "true"
USER_INPUT:

列表示例:

1
2
3
4
environment:
- RACK_ENV=development
- SHOW=true
- USER_INPUT

env_fileenvironment 属性都被指定时,environment 下指定的环境变量优先级是更高的。

4、expose

expose 定义了 Compose 从容器中暴露的(传入)端口或端口范围。这些端口必须对链接的服务可访问,但不应发布到主机机器上。只能指定内部容器端口。

将容器的端口仅暴露给同一 Compose 网络中的其他服务,而不会将端口映射到宿主机。主要用于服务间通信,确保其他服务可以通过网络访问该端口,但外部(宿主机或外部网络)无法直接访问该端口。

格式为 <portnum>/[<proto>]<startport-endport>/[<proto>] 。没有指定协议时,默认为 tcp。示例如下:

1
2
3
4
expose:
- "3000"
- "8000"
- "8080-8085/tcp"

如果镜像的 Dockerfile 文件中公开了端口(Dockerfile 中的 EXPOSE 指令),即使 Compose 文件中没有设置为公开,网络上的其他容器也可以访问到。

5、restart

restart 属性定义了容器的重启策略。重启策略控制 Docker 守护进程在退出后是否重启容器。

可选项如下:

  • no:默认的重启策略。在任何情况下都不会重启容器。
  • always:会一直重启容器,直到其被移除。
  • on-failure[:max-retries]:会在退出出现错误时重启容器。可选项 max-retrire,限制 Docker 守护程序尝试重启的次数。
  • unless-stopped:重新启动容器,除非容器被停止或 Docker 本身被停止或重新启动。

示例如下:

1
2
3
4
5
restart: "no"
restart: always
restart: on-failure
restart: on-failure:3
restart: unless-stopped

6、env_file

env_file 属性被用来指定一个或多个包含要传递给容器的环境变量的文件。

1
env_file: .env

其也可以是一个列表。列表中的文件是从上到下进行处理的,如果两个文件中有同一个变量,该变量的值取自后一个文件。

1
2
3
env_file:
- a.env
- b.env

列表元素也可以声明为 map,用 map 来指定一个参数 required,默认为 true。当 required 赋值为 false 且 env 文件缺失时,Compose 将会默认忽略该条目。

如果 env 文件指定为相对路径,则是基于 Compose 文件的相对路径。

由于绝对路径会妨碍 Compose 文件的可移植性,因此当使用绝对路径来设置 env_file 时,Compose 会发出警告。

另外,不同途径指定环境变量是有优先级的,使用 env_file 指定的环境变量,将会被 environment 指定的环境变量覆盖。请参考:[[环境变量#环境变量优先级]]

7、newtorks

networks 属性定义了服务容器所连接的网络,引用了 networks 顶级元素下的条目。networks 属性有助于管理容器的网络,控制服务在 Docker 环境中的交互方式。它用于指定该服务的容器应该连接到哪些网络。这对于定义容器之间以及容器与外部的通信方式非常重要。

1
2
3
4
5
services:
some-service:
networks:
- some-network
- other-network

7.1 aliases

aliases 声明服务在网络中的别名。相同网络中的其他容器可以通过服务名或别名连接到该服务的容器之一。

由于别名是以自定义的网络范围内的,同一个服务在不同的网络中可以拥有不同的别名。

注意:一个网络范围的别名可以被多个容器共享,甚至可以被多个服务共享。如果多个容器或服务共享同一个别名,则无法保证该别名解析到具体哪个容器。

示例:

1
2
3
4
5
6
7
8
9
10
services:
some-service:
networks:
some-network:
aliases:
- alias1
- alias3
other-network:
aliases:
- alias2

在下列示例中,frontend 服务可以通过主机名 backenddatabase 连接到 back-tier 网络中的 backend 服务。monitoring 服务可以通过 backendmysql 连接到 admin 网络中的相同 backend 服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
services:
frontend:
image: example/webapp
networks:
- front-tier
- back-tier

monitoring:
image: example/monitoring
networks:
- admin

backend:
image: example/backend
networks:
back-tier:
aliases:
- database
admin:
aliases:
- mysql

networks:
front-tier:
back-tier:
admin:

7.2 ipv4_address 和 ipv6_address

当容器加入网络时,为服务中的容器指定静态 IP 地址。

顶层 networks 部分中的相应网络配置必须具有包含每个静态地址的 ipam 属性和子网配置。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
services:
frontend:
image: example/webapp
networks:
front-tier:
ipv4_address: 172.16.238.10
ipv6_address: 2001:3984:3989::10

networks:
front-tier:
ipam:
driver: default
config:
- subnet: "172.16.238.0/24"
- subnet: "2001:3984:3989::/64"

在此示例中,frontend 服务容器在加入 front-tier 网络时将被分配指定的 IPv4 和 IPv6 地址。

link_local_ips 配置指定了一个链路本地 IP 列表。链路本地 IP 是属于一个众所周知的子网的特殊 IP,它们由操作员管理,通常取决于它们部署的架构。

示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
services:
app:
image: busybox
command: top
networks:
app_net:
link_local_ips:
- 57.123.22.11
- 57.123.22.13
networks:
app_net:
driver: bridge

在此示例中,app 服务通过 link_local_ips 配置了两个链路本地 IP 地址,app_net 网络使用了 bridge 驱动。

7.4 priority

priority 配置指定了 Compose 将服务中的容器连接到网络的顺序。如果未指定,默认值为 0。

在以下示例中,由于 app_net_1 的优先级最高,app 服务会首先连接到 app_net_1,然后依次连接到 app_net_3app_net_2(其默认优先级为 0)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
services:
app:
image: busybox
command: top
networks:
app_net_1:
priority: 1000
app_net_2:
app_net_3:
priority: 100
networks:
app_net_1:
app_net_2:
app_net_3:

8、volumes

volumes 属性定义了可由服务容器访问的挂载主机路径或命名卷。您可以使用 volumes 来定义多种类型的挂载,包括 volumebindtmpfsnpipe

如果挂载的是主机路径并且仅由单个服务使用,则可以在服务定义中声明该挂载。要在多个服务之间重用卷,必须在 volumes 顶级元素中声明一个命名卷。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
services:
backend:
image: example/backend
volumes:
- type: volume
source: db-data
target: /data
volume:
nocopy: true
subpath: sub
- type: bind
source: /var/run/postgres/postgres.sock
target: /var/run/postgres/postgres.sock

volumes:
db-data:

8.1 短格式语法

短语法使用一个带有冒号分隔的字符串来指定装载卷(VOLUME:CONTAINER_PATH)或访问模式(VOLUME:CONTAINER_PATH:ACCESS_MODE

  • VOLUME:可以是容器所在平台的主机路径或卷名
  • CONTAINER_PATH:容器中安装卷的路径。
  • ACCESS_MODE:逗号分隔的选项列表
    • rw:读写权限,默认选项
    • ro:只读
    • z:SELinux 选项,指示绑定装载主机内容在多个容器之间共享。
    • Z:SELinux 选项,指示绑定装载主机内容是私有的,对于其他容器是不共享的。

注意:在没有 SELinux 的平台上,忽略 SELinux 重新标记绑定挂载选项。

8.2 长格式语法

长语法允许配置无法用短格式表示的其他字段。

  • type:挂载类型,volumebindtmpfsnpipecluster
  • source:挂载源路径,可以是一个路径,也可以是在 volumes 顶级元素中定义的卷。tmpfs 类型的挂载中此属性不生效。
  • target:挂载目标路径,容器内的路径。
  • read_only:是否是只读
  • bind:额外的 bind 选项
    • propagation
    • create_host_path
    • selinux
  • volume:配置额外的 volume 选项
    • nocopy:禁止在创建卷时从容器复制数据。
    • subpath:卷内要装载的路径,而不是卷根目录
  • tmpfs:配置额外的 tmpfs 选项
    • size
    • mode
  • consistency

9、depends_on

使用 depends_on 属性,你可以控制服务启动和关闭的顺序。如果服务是耦合的并且启动顺序会影响应用程序的功能时这个属性是非常有用的。

9.1 简短语法

简短语法仅指定依赖服务的名称。服务依赖关系会产生以下行为:

  • Compose 按照顺序创建服务。下面的示例中,dbredis 会在 web 服务之前被创建。
  • Compose 按照顺序删除服务。下面的示例中,web 服务会在 dbredis 服务之前被删除。
1
2
3
4
5
6
7
8
9
10
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres

9.2 复杂语法

复杂语法支持无法通过简短语法指定的其他字段。

  • restart:当该属性设置为 true 时,Compose 会在更新依赖关系服务后重新启动此服务。适用于由 Compose 操作控制的显示重启,不包括容器死亡后容器运行时的自动重启。
  • condition:设置满足依赖关系的条件
    • service_started
    • service_healthy
    • service_completed_successfully
  • required

注意:该属性在 Docker 新版本中不推荐使用了。

external_links 将服务容器链接到由你的 Compose 应用程序之外管理的服务。external_links 定义要使用平台查找机制检索的现有服务的名称。可以指定形式为 SERVICE:ALIAS 的别名。

1
2
3
4
external_links:
- redis
- database:mysql
- database:postgresql

external_links 用于将服务容器链接到您的 Compose 应用之外管理的服务。external_links 定义了使用平台查找机制检索的现有服务的名称。可以指定形式为 SERVICE:ALIAS 的别名。

external_links 允许当前 Docker Compose 应用程序中的服务与其他不在该 Compose 文件中定义的服务(比如其他 Compose 堆栈中的服务或直接在 Docker 宿主机上运行的容器)进行通信。通过指定 external_links,可以为这些外部服务定义一个别名(可选),从而在 Compose 应用中通过该别名来引用它们,就好像它们是 Compose 应用内部的一部分一样。

例如,如果当前 Compose 应用需要与名为 database_1 的外部数据库服务进行通信,并且想在 Compose 应用中通过别名 db 来引用它,可以在 Compose 文件的 external_links 部分添加如下配置:

1
2
3
4
5
services: 
myapp:
image: myappimage
external_links:
- database_1:db

像上面这样,在 myapp 服务中,就可以通过别名 db 来访问名为 database_1 的外部服务了。

需要注意的是,external_links 主要用于 Docker 的旧版本或某些特定场景,而在较新的 Docker 版本和 Compose 文件中,推荐使用更现代的连接和发现机制,如 Docker 网络(特别是 networks 关键字)来实现服务间的通信。

11、ports

端口映射用于定义主机和容器之间的端口对应关系,这对于允许外部访问运行在容器内部的服务至关重要。可以通过简短语法或长语法来定义端口映射,其中长语法包括额外的选项,如协议类型和网络模式。

当使用 network_mode: host 时,不应使用端口映射,否则会导致运行时错误。

简短语法

简短语法是一种用冒号分隔的字符串,用于设置主机 IP、主机端口和容器端口,格式如下:

1
[HOST:]CONTAINER[/PROTOCOL]

其中:

  • HOST:可选,格式为 [IP:] 后跟端口号或端口范围。
  • CONTAINER:必填,指定容器内的端口号或端口范围。
  • PROTOCOL:用于限制端口到特定的协议。支持的协议包括 tcpudp,这些是由规范定义的;Compose 还提供对平台特定协议名称的支持。

如果未设置主机 IP,则绑定到所有网络接口。端口可以是单个值或一个范围。主机和容器必须使用等效的端口范围。

你可以指定两个端口(HOST:CONTAINER),或者只指定容器端口。在后一种情况下,容器运行时会自动分配主机上的任何未分配端口。

HOST:CONTAINER 应始终作为(带引号的)字符串指定,以避免与 YAML 的 base-60 浮点数产生冲突。参考 Floating-Point Language-Independent Type for YAML™ Version 1.1

1
2
3
4
5
6
7
8
9
10
ports:
- "3000"
- "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"

注意:如果容器引擎不支持主机 IP 映射,Compose 会拒绝该 Compose 文件并忽略指定的主机 IP。

长语法

长语法允许配置一些在简短语法中无法表达的额外字段,可配置的属性如下:

  • target:容器内的端口。
  • published:公开暴露的端口。定义为字符串,可以使用 start-end 的格式设置为一个范围。这意味着实际端口将被分配一个在指定范围内的可用端口。
  • host_ip:主机 IP 映射,未指定表示绑定到所有网络接口(即 0.0.0.0)。
  • protocol:端口协议(tcpudp)。默认为 tcp
  • app_protocol:该端口使用的应用层协议(TCP/IP 第4层 / OSI 第7层)。这是可选的,可以用作提示,使 Compose 对它理解的协议提供更丰富的行为。此选项从 Docker Compose 版本 2.26.0 开始引入。
  • mode:发布模式。host 表示在每个节点上发布一个主机端口;ingress 表示端口将被负载均衡。默认为 ingress
  • name:端口的人类可读名称,用于在服务内部记录其用途。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
ports:
- name: web
target: 80
host_ip: 127.0.0.1
published: "8080"
protocol: tcp
app_protocol: http
mode: host

- name: web-secured
target: 443
host_ip: 127.0.0.1
published: "8083-9000"
protocol: tcp
app_protocol: https
mode: host

12、command

command 属性中声明的命令会覆盖容器镜像中默认声明的命令(比如 Dockerfile 的 CMD 指令)。

command 属性使用示例如下:

1
command: bundle exec thin -p 3000

该值也可以是类似于 Dockerfile 的列表格式:

1
command: [ "bundle", "exec", "thin", "-p", "3000" ]

如果 command 属性的值为 null,则使用镜像中的默认命令。

如果 command 属性的值为 [](空列表)或 ''(空字符串),则默认命令将被忽略,相当于覆盖为空命令。

13、privileged

privileged 配置选项允许容器服务以更高的权限运行。

该配置是否受支持以级实际上产生的影响因平台而异。在一些平台上,这可能意味着容器将拥有更多权限,类似于宿主机上的 root 用户权限,可以访问所有设备并忽略某些安全限制。

1
2
3
services:
service-1:
privileged: true

14、user

user 配置项用于覆盖用于运行容器进程的用户。默认值由镜像设置(即 Dockerfile 中的 USER 指令)。

如果未设置,则默认是 root 用户。

另外,此属性的值可以是用户名称,也可以是用户 ID,即 UID。查看 WSL ubuntu 的 /etc/passwd 文件,内容如下:

1
2
3
root:x:0:0:root:/root:/bin/bash
ubuntu:x:1000:1001:Ubuntu:/home/ubuntu:/bin/bash
z2huo:x:1002:1002:,,,:/home/z2huo:/bin/bash

每一行的七个字段代表的含义为:用户名:密码占位符:用户ID:用户组ID:用户全名或注释:用户Home目录:Shell

可以看到,root 用户的 UID 为 0

15、network_mode

network_mode 属性设置服务容器的网络模式。

该属性的取值如下:

  • none:关闭所有容器的网络功能。
  • host:让容器直接访问主机的网络接口。
  • service:{name}:仅允许容器访问指定的服务。

示例如下:

1
2
3
network_mode: "host"
network_mode: "none"
network_mode: "service:[service name]"

当设置了 network_mode 时,不允许使用 networks 属性,Compose 会拒绝包含这两个属性的 Compose 文件。

16、内存配置

mem_limit

mem_limit 配置了容器可以分配的内存量上限,设置为表示字节值的字符串。

当设置了 mem_limit 时,它必须与部署规范 (Deploy Specification) 中的 limits.memory 属性保持一致。

mem_reservation

mem_reservation 配置了容器可以分配的内存预留量,同样设置为表示字节值的字符串。

当设置了 mem_reservation 时,它必须与部署规范中的 reservations.memory 属性保持一致。

mem_swappiness

mem_swappiness 定义了一个百分比值(0 到 100 之间),用于控制主机内核将容器使用的匿名内存页面交换到磁盘的行为。

  • 0:关闭匿名页面交换。
  • 100:将所有匿名页面设置为可交换。
  • 默认值:取决于平台。

memswap_limit

memswap_limit 定义了容器允许交换到磁盘的内存量。这是一个修饰属性,只有在设置了 memory 属性时才有意义。使用交换可以让容器在耗尽所有可用内存后将多余的内存需求写入磁盘,但这会对频繁交换内存的应用程序性能产生负面影响。

  • 如果 memswap_limit 设置为正整数,则 memorymemswap_limit 必须同时设置。memswap_limit 表示可以使用的总内存和交换空间量,而 memory 控制非交换内存的使用量。例如,如果 memory="300m"memswap_limit="1g",那么容器可以使用 300 MB 的内存和 700 MB (1 GB - 300 MB) 的交换空间。
  • 如果 memswap_limit 设置为 0,该设置将被忽略,视为未设置。
  • 如果 memswap_limitmemory 设置相同的正值,则容器无法访问交换空间。
  • 如果 memswap_limit 未设置且 memory 已设置,则容器可以根据主机配置使用与 memory 设置等量的交换空间。例如,如果 memory="300m"memswap_limit 未设置,则容器总共可以使用 600 MB 的内存和交换空间。
  • 如果 memswap_limit 明确设置为 -1,则容器可以使用主机系统上可用的所有交换空间,即不限制交换空间的使用。

17、CPU 配置

cpu_count

cpu_count 定义服务容器可使用的 CPU 数量。

cpu_percent

cpu_percent 定义可用 CPU 的使用百分比。

cpu_shares

cpu_shares 以整数值形式定义服务容器的相对 CPU 权重,相对于其他容器的优先级。

cpu_period

cpu_period 配置 Linux 内核平台上 CPU 完全公平调度器(CFS, Completely Fair Scheduler)的周期。

cpu_quota

cpu_quota 配置 Linux 内核平台上 CPU 完全公平调度器(CFS)的配额。

cpu_rt_runtime

cpu_rt_runtime 配置支持实时调度器的平台的 CPU 分配参数。可以是使用微秒为单位的整数值,或是持续时间格式。

示例

1
2
3
cpu_rt_runtime: '400ms'

cpu_rt_runtime: '95000'

cpu_rt_period

cpu_rt_period 配置支持实时调度器的平台的 CPU 分配周期参数。可以是使用微秒为单位的整数值,或是持续时间格式。

示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
cpu_rt_period: '1400us'

cpu_rt_period: '11000'
```

#### cpus

cpus 定义分配给服务容器的 CPU 数量(可能是虚拟 CPU)。这是一个小数值,例如:0.000 表示没有限制。

当设置时,cpus 必须与部署规范中的 cpus 属性一致。

#### cpuset

cpuset 定义容器允许执行的具体 CPU。可以是范围(例如 0-3)或列表(例如 0,1)。

### 18、entrypoint

`entrypoint` 声明服务容器的默认入口点。这会覆盖服务 Dockerfile 中的 `ENTRYPOINT` 指令。

如果 `entrypoint` 非空,Compose 将忽略镜像中的任何默认命令,例如 Dockerfile 中的 `CMD` 指令。

`command` 属性,用于设置或覆盖入口点进程要执行的默认命令。

在其简写形式中,值可以定义为字符串

```yml
entrypoint: /code/entrypoint.sh

或者,值也可以是一个列表,方式类似于 Dockerfile:

1
2
3
4
5
6
7
entrypoint:
- php
- -d
- zend_extension=/usr/local/lib/php/extensions/no-debug-non-zts-20100525/xdebug.so
- -d
- memory_limit=-1
- vendor/bin/phpunit

如果值为 null,则使用映像中的默认入口点。

如果值为 [](空列表)或 ''(空字符串),则忽略映像声明的默认入口点,即将其覆盖为空。

相关链接

Services top-level elements | Docker Docs

Floating-Point Language-Independent Type for YAML™ Version 1.1

Compose Deploy Specification | Docker Docs

[[环境变量#环境变量优先级]]

[[Linux 系统中 etc 目录中 passwd 文件内容解析]]

OB tags

#Docker #未完待续