Docker Compose 顶级元素 Services
一、简介
服务是应用程序中计算资源的抽象定义,可以独立于其他组件进行扩展或替换。服务由一组容器支持,平台根据复制需求和放置约束运行这些容器。由于服务由容器支持,因此它们由 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 解析器转换为 True
或 False
。
环境变量可以通过单个键声明(等号后没有值)。在这种情况下,Compose 依赖于你来解析这个值。如果值没有被解析,变量将被取消设置,并从服务容器环境中移除。
Map 示例:
1 | environment: |
列表示例:
1 | environment: |
当 env_file
和 environment
属性都被指定时,environment
下指定的环境变量优先级是更高的。
4、expose
expose
定义了 Compose 从容器中暴露的(传入)端口或端口范围。这些端口必须对链接的服务可访问,但不应发布到主机机器上。只能指定内部容器端口。
将容器的端口仅暴露给同一 Compose 网络中的其他服务,而不会将端口映射到宿主机。主要用于服务间通信,确保其他服务可以通过网络访问该端口,但外部(宿主机或外部网络)无法直接访问该端口。
格式为 <portnum>/[<proto>]
或 <startport-endport>/[<proto>]
。没有指定协议时,默认为 tcp
。示例如下:
1 | expose: |
如果镜像的 Dockerfile 文件中公开了端口(Dockerfile 中的 EXPOSE
指令),即使 Compose 文件中没有设置为公开,网络上的其他容器也可以访问到。
5、restart
restart
属性定义了容器的重启策略。重启策略控制 Docker 守护进程在退出后是否重启容器。
可选项如下:
no
:默认的重启策略。在任何情况下都不会重启容器。always
:会一直重启容器,直到其被移除。on-failure[:max-retries]
:会在退出出现错误时重启容器。可选项max-retrire
,限制 Docker 守护程序尝试重启的次数。unless-stopped
:重新启动容器,除非容器被停止或 Docker 本身被停止或重新启动。
示例如下:
1 | restart: "no" |
6、env_file
env_file 属性被用来指定一个或多个包含要传递给容器的环境变量的文件。
1 | env_file: .env |
其也可以是一个列表。列表中的文件是从上到下进行处理的,如果两个文件中有同一个变量,该变量的值取自后一个文件。
1 | env_file: |
列表元素也可以声明为 map,用 map 来指定一个参数 required
,默认为 true。当 required 赋值为 false 且 env 文件缺失时,Compose 将会默认忽略该条目。
如果 env 文件指定为相对路径,则是基于 Compose
文件的相对路径。
由于绝对路径会妨碍 Compose 文件的可移植性,因此当使用绝对路径来设置 env_file 时,Compose 会发出警告。
另外,不同途径指定环境变量是有优先级的,使用 env_file 指定的环境变量,将会被 environment 指定的环境变量覆盖。请参考:[[环境变量#环境变量优先级]]
7、newtorks
networks
属性定义了服务容器所连接的网络,引用了 networks
顶级元素下的条目。networks
属性有助于管理容器的网络,控制服务在 Docker 环境中的交互方式。它用于指定该服务的容器应该连接到哪些网络。这对于定义容器之间以及容器与外部的通信方式非常重要。
1 | services: |
7.1 aliases
aliases
声明服务在网络中的别名。相同网络中的其他容器可以通过服务名或别名连接到该服务的容器之一。
由于别名是以自定义的网络范围内的,同一个服务在不同的网络中可以拥有不同的别名。
注意:一个网络范围的别名可以被多个容器共享,甚至可以被多个服务共享。如果多个容器或服务共享同一个别名,则无法保证该别名解析到具体哪个容器。
示例:
1 | services: |
在下列示例中,frontend
服务可以通过主机名 backend
或 database
连接到 back-tier
网络中的 backend
服务。monitoring
服务可以通过 backend
或 mysql
连接到 admin
网络中的相同 backend
服务。
1 | services: |
7.2 ipv4_address 和 ipv6_address
当容器加入网络时,为服务中的容器指定静态 IP 地址。
顶层 networks
部分中的相应网络配置必须具有包含每个静态地址的 ipam
属性和子网配置。
示例如下:
1 | services: |
在此示例中,frontend
服务容器在加入 front-tier
网络时将被分配指定的 IPv4 和 IPv6 地址。
7.3 link_local_ips
link_local_ips
配置指定了一个链路本地 IP 列表。链路本地 IP 是属于一个众所周知的子网的特殊 IP,它们由操作员管理,通常取决于它们部署的架构。
示例如下:
1 | services: |
在此示例中,app
服务通过 link_local_ips
配置了两个链路本地 IP 地址,app_net
网络使用了 bridge
驱动。
7.4 priority
priority
配置指定了 Compose 将服务中的容器连接到网络的顺序。如果未指定,默认值为 0。
在以下示例中,由于 app_net_1
的优先级最高,app
服务会首先连接到 app_net_1
,然后依次连接到 app_net_3
和 app_net_2
(其默认优先级为 0)。
1 | services: |
8、volumes
volumes
属性定义了可由服务容器访问的挂载主机路径或命名卷。您可以使用 volumes
来定义多种类型的挂载,包括 volume
、bind
、tmpfs
或 npipe
。
如果挂载的是主机路径并且仅由单个服务使用,则可以在服务定义中声明该挂载。要在多个服务之间重用卷,必须在 volumes
顶级元素中声明一个命名卷。
1 | services: |
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
:挂载类型,volume
、bind
、tmpfs
、npipe
或cluster
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 按照顺序创建服务。下面的示例中,
db
和redis
会在web
服务之前被创建。 - Compose 按照顺序删除服务。下面的示例中,
web
服务会在db
和redis
服务之前被删除。
1 | services: |
9.2 复杂语法
复杂语法支持无法通过简短语法指定的其他字段。
restart
:当该属性设置为 true 时,Compose 会在更新依赖关系服务后重新启动此服务。适用于由 Compose 操作控制的显示重启,不包括容器死亡后容器运行时的自动重启。condition
:设置满足依赖关系的条件service_started
service_healthy
service_completed_successfully
required
10、external_links
注意:该属性在 Docker 新版本中不推荐使用了。
external_links
将服务容器链接到由你的 Compose 应用程序之外管理的服务。external_links
定义要使用平台查找机制检索的现有服务的名称。可以指定形式为 SERVICE:ALIAS
的别名。
1 | external_links: |
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 | services: |
像上面这样,在 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:用于限制端口到特定的协议。支持的协议包括
tcp
和udp
,这些是由规范定义的;Compose 还提供对平台特定协议名称的支持。
如果未设置主机 IP,则绑定到所有网络接口。端口可以是单个值或一个范围。主机和容器必须使用等效的端口范围。
你可以指定两个端口(HOST:CONTAINER
),或者只指定容器端口。在后一种情况下,容器运行时会自动分配主机上的任何未分配端口。
HOST:CONTAINER
应始终作为(带引号的)字符串指定,以避免与 YAML 的 base-60 浮点数产生冲突。参考 Floating-Point Language-Independent Type for YAML™ Version 1.1
1 | ports: |
注意:如果容器引擎不支持主机 IP 映射,Compose 会拒绝该 Compose 文件并忽略指定的主机 IP。
长语法
长语法允许配置一些在简短语法中无法表达的额外字段,可配置的属性如下:
target
:容器内的端口。published
:公开暴露的端口。定义为字符串,可以使用start-end
的格式设置为一个范围。这意味着实际端口将被分配一个在指定范围内的可用端口。host_ip
:主机 IP 映射,未指定表示绑定到所有网络接口(即0.0.0.0
)。protocol
:端口协议(tcp
或udp
)。默认为tcp
。app_protocol
:该端口使用的应用层协议(TCP/IP 第4层 / OSI 第7层)。这是可选的,可以用作提示,使 Compose 对它理解的协议提供更丰富的行为。此选项从 Docker Compose 版本 2.26.0 开始引入。mode
:发布模式。host
表示在每个节点上发布一个主机端口;ingress
表示端口将被负载均衡。默认为ingress
。name
:端口的人类可读名称,用于在服务内部记录其用途。
1 | ports: |
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 | services: |
14、user
user
配置项用于覆盖用于运行容器进程的用户。默认值由镜像设置(即 Dockerfile 中的 USER
指令)。
如果未设置,则默认是 root 用户。
另外,此属性的值可以是用户名称,也可以是用户 ID,即 UID。查看 WSL ubuntu 的 /etc/passwd
文件,内容如下:
1 | root:x:0:0:root:/root:/bin/bash |
每一行的七个字段代表的含义为:用户名:密码占位符:用户ID:用户组ID:用户全名或注释:用户Home目录:Shell
可以看到,root 用户的 UID 为 0
15、network_mode
network_mode
属性设置服务容器的网络模式。
该属性的取值如下:
none
:关闭所有容器的网络功能。host
:让容器直接访问主机的网络接口。service:{name}
:仅允许容器访问指定的服务。
示例如下:
1 | network_mode: "host" |
当设置了 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
设置为正整数,则memory
和memswap_limit
必须同时设置。memswap_limit
表示可以使用的总内存和交换空间量,而memory
控制非交换内存的使用量。例如,如果memory="300m"
且memswap_limit="1g"
,那么容器可以使用 300 MB 的内存和 700 MB (1 GB - 300 MB) 的交换空间。 - 如果
memswap_limit
设置为 0,该设置将被忽略,视为未设置。 - 如果
memswap_limit
与memory
设置相同的正值,则容器无法访问交换空间。 - 如果
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 | cpu_rt_runtime: '400ms' |
cpu_rt_period
cpu_rt_period 配置支持实时调度器的平台的 CPU 分配周期参数。可以是使用微秒为单位的整数值,或是持续时间格式。
示例:
1 | cpu_rt_period: '1400us' |
或者,值也可以是一个列表,方式类似于 Dockerfile:
1 | entrypoint: |
如果值为 null
,则使用映像中的默认入口点。
如果值为 []
(空列表)或 ''
(空字符串),则忽略映像声明的默认入口点,即将其覆盖为空。
相关链接
Services top-level elements | Docker Docs
Floating-Point Language-Independent Type for YAML™ Version 1.1
Compose Deploy Specification | Docker Docs
OB links
[[环境变量#环境变量优先级]]
[[Linux 系统中 etc 目录中 passwd 文件内容解析]]
OB tags
#Docker #未完待续