Docker: healthcheck 和 depends_on

序言

本文主要包括 Docker healthcheck 的机制、语法,以及 Docker compose 的 depends_on 机制、语法。本文可以视作一个 cheat sheet。

healthcheck 机制

When a container has a healthcheck specified, it has a health status in addition to its normal status. This status is initially starting. Whenever a health check passes, it becomes healthy (whatever state it was previously in). After a certain number of consecutive failures, it becomes unhealthy.

healthcheck 有如下参数:

参数 默认值 说明
--interval=DURATION 30s 间隔多久执行一次 healthcheck。
--timeout=DURATION 30s 每一次 healthcheck 最多执行多久。如果超过该时间,视为失败。
--retries=N 3 如果连续 retries 次失败,则容器状态变为 unhealthy
--start-period=DURATION 0s 在这段时间内,如果 healthcheck 失败了,不会记录到累计 retries 次数中。但是,只要 healthcheck 成功了,容器视作启动成功,start period 自动结束。
--start-interval=DURATION 5s 在 start period 内,间隔多久执行一次 healthcheck。

容器启动后,它处于 starting 状态,也就是处于 start period。start period 内,容器只可能变为 healthy 状态,不可能变为 unhealthy 状态。

healthcheck 语法

语法

本文不考虑 dockerfile 和 cli 中的语法,只考虑 compose 中的语法。

compose 内的 healthcheck 会覆盖 dockerfile 中的 healthcheck 。

例子:

1
2
3
4
5
6
7
healthcheck:
test: curl -f https://localhost || exit 1
interval: 1m30s
timeout: 10s
retries: 3
start_period: 40s
start_interval: 5s

test defines the command Compose runs to check container health. It can be either a string or a list.

If it’s a list, the first item must be either NONE, CMD or CMD-SHELL.

If it’s a string, it’s equivalent to specifying CMD-SHELL followed by that string.

以下两种形式等价:

1
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"]
1
test: curl -f https://localhost || exit 1

显然,第二种更方便。

debug test 命令

常用的 test 命令模板见之前的文章。如何 debug 自己写的 test 命令?—— 使用 docker inspect。healthcheck 信息在 State.Health 中,可以直接用以下命令获得:

1
docker inspect --format='{{json .State.Health}}' 容器

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
"Status": "healthy",
"FailingStreak": 0,
"Log": [
{
"Start": "2024-06-02T13:45:22.110841425+08:00",
"End": "2024-06-02T13:45:22.178282083+08:00",
"ExitCode": 0,
"Output": "mysqladmin: [Warning] Using a password on the command line interface can be insecure.\nmysqld is alive\n"
},
{
"Start": "2024-06-02T13:45:27.208737778+08:00",
"End": "2024-06-02T13:45:27.261481813+08:00",
"ExitCode": 0,
"Output": "mysqladmin: [Warning] Using a password on the command line interface can be insecure.\nmysqld is alive\n"
}
]
}

Log 元素的属性的含义:

  • Output :执行命令后的输出,用来 debug。
  • Exitcode0 表示容器健康,1 表示不健康。

禁用 healthcheck

1
2
healthcheck:
disable: true

depends_on 机制

You can control the order of service startup and shutdown with the depends_on attribute. Compose always starts and stops containers in dependency order.

It is useful if services are closely coupled, and the startup sequence impacts the application’s functionality.

要注意,depends_on 只是表示启动顺序,不代表先启动的容器准备好了。

On startup, Compose does not wait until a container is “ready”, only until it’s running.

通过设置 depends_oncondition 属性,可以指定依赖 A 的容器 B 何时启动。该属性有如下值:

说明
service_started 默认值,只要 A 启动了 B 就启动。
service_healthy 只有 A 变为 healthy 状态,B 才能启动。
service_completed_successfully 当 A 成功执行完它的 command 命令,B 才能启动。这里 A 通常用来执行一个命令/脚本(而不是作为一个服务),执行完毕后 A 停止。命令/脚本退出码为 0 表示成功。可以看这个具体的例子

因此,如果要求 compose 中作为服务启动的多个容器实现真正的有序启动,需要利用 healthcheck 机制,同时设置 conditionservice_healthy


需要注意的是,利用 depends_on 只是在使用 docker compose up|start 启动时有效。如果容器的 restart 设置为 unless-stopped 或者 always,那么在服务器重启后,这些容器不会按照 depends_on 的顺序启动。

depends_on 语法

简单配置

1
2
3
4
5
6
7
8
9
10
services:
web:
build: .
depends_on:
- db
- redis
redis:
image: redis
db:
image: postgres

此时 condition 默认为 service_started

详细配置

这种配置可以指定 condition

1
2
3
4
5
6
7
8
9
10
11
12
services:
web:
build: .
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
redis:
image: redis
db:
image: postgres

参考