在 Docker Compose 中,depends_on
是一个用于定义服务之间依赖关系的关键字。它允许您指定一个或多个服务依赖于其他服务,以确保在启动或重新创建容器时,所依赖的服务先于依赖它们的服务启动。
以下是一些关于 depends_on
的详解:
depends_on
,您可以告诉 Docker Compose 在启动容器时按照指定的顺序启动服务。例如,如果服务 A 依赖于服务 B 和服务 C,则在启动时,Docker Compose 会先启动服务 B 和服务 C,然后才会启动服务 A。depends_on
只表示依赖关系,而不会等待依赖的服务完全可用。它只确保在依赖的服务启动后再启动当前服务。因此,依赖的服务可能仍在进行初始化或准备阶段,而不一定已经完全可用。如果需要等待服务完全可用,可以结合使用其他工具或技术,例如健康检查或等待脚本。depends_on
并不能保证依赖的服务在启动后处于健康状态。它只负责在启动时按照指定顺序启动服务,但并不检查服务的健康状态或等待服务变为可用状态。对于检查服务健康状态,可以使用其他机制,例如使用健康检查命令或工具。depends_on
指定的依赖关系顺序启动。这是因为 Docker Compose 会尝试最大化容器的并发启动,以提高启动效率。如果需要强制按照依赖关系顺序启动,请使用 depends_on
结合 restart
关键字的 condition: ["service_started"]
选项。综上所述,depends_on
关键字允许您定义 Docker Compose 服务之间的依赖关系,但它并不能保证服务的可用性或健康状态。
docker-compose.yml
样例文件
version: '3'
services:
rabbitmq:
hostname: rabbitmq_host
container_name: 'mq'
image: rabbitmq:3.9.11-management
restart: always
ports:
- "5772:5672" # AMQP
- "15772:15672" # Web UI
networks:
- app-network
environment:
RABBITMQ_DEFAULT_USER: root
RABBITMQ_DEFAULT_PASS: pwd
RABBITMQ_DEFAULT_VHOST: /
volumes:
- rabbitmq_data:/var/lib/rabbitmq/mnesia
healthcheck:
test: [ "CMD", "rabbitmq-diagnostics", "ping" ]
interval: 50s
timeout: 5s
retries: 3
selenium:
container_name: 'selenium'
image: selenium/standalone-chrome
restart: always
ports:
- "4444:4444"
networks:
- app-network
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:4444/wd/hub/status" ]
interval: 30s
timeout: 5s
retries: 3
db:
container_name: 'mysql8'
image: mysql:8.0.32
# hostname: mysql_host
user: root
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
environment:
LANG: C.UTF-8
MYSQL_ROOT_PASSWORD: pwd
MYSQL_DATABASE: yinlian
ports:
- "3306:3306"
volumes:
- "./data/db/data:/var/lib/mysql"
- "./data/db/mysql-files:/var/lib/mysql-files"
- "./build/docker/mysqldb/my.cnf:/etc/my.cnf"
networks:
- app-network
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
interval: 30s
timeout: 5s
retries: 3
app-producer:
container_name: 'producer'
build:
context: .
dockerfile: Dockerfile
ports:
- "8001:8001"
command: ['echo','hello world, Frank']
depends_on:
- db
- rabbitmq
- selenium
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
rabbitmq_data:
driver: local
上面的 文件中定义了 rabbitmq , db, selenium ,以及 app-producer , 其中 app-producer 服务 依赖于 其他三个服务, 这个时候如何进行配置呢?
depends_on
只能保证启动的顺序.
那么如何解决 保证 服务启动后,才启动app-producer 服务呢? 为此需要 使用长定义模式
The long form syntax enables the configuration of additional fields that can’t be expressed in the short form.
restart
: When set to true
Compose restarts this service after it updates the dependency service. This applies to an explicit restart controlled by a Compose operation, and excludes automated restart by the container runtime after the container dies.condition
: Sets the condition under which dependency is considered satisfied
service_started
: An equivalent of the short syntax described aboveservice_healthy
: Specifies that a dependency is expected to be “healthy” (as indicated by healthcheck) before starting a dependent service.service_completed_successfully
: Specifies that a dependency is expected to run to successful completion before starting a dependent service.required
: When set to false
Compose only warns you when the dependency service isn’t started or available. If it’s not defined the default value of required
is true
.下面的文件中 我定义了一个web , db 服务, 此时 web 服务 启动就需要等待 db启动 并且成功后,才能启动.
condition 的含义 service_healthy
做健康检查
service_completed_successfully
表示 容器正常退出了, 之后 才进行启动.
service_started
只保证启动顺序, 并不做任何检查.
services:
web:
build: .
depends_on:
db:
condition: service_healthy
db:
image: mysql:latest
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 5s
timeout: 3s
retries: 3
service_completed_successfully
参数是长定义语法中的一个字段,用于指定依赖服务在成功完成后,才启动相关的服务。
当将 service_completed_successfully
设置为 true
时,它表示依赖服务必须完全运行并成功完成(即退出状态码为 0),才能启动相关的服务。
让我们通过一个示例来说明该参数的含义。假设我们有一个应用程序,其中包含一个 worker
服务和一个 db_migration
服务。我们希望在启动 worker
服务之前,先运行 db_migration
服务,并确保 db_migration
服务成功完成数据库迁移操作。
使用长定义语法,我们可以将 depends_on
部分扩展为以下形式:
services:
worker:
build: .
depends_on:
db_migration:
condition: service_completed_successfully
db_migration:
build: .
command: ./run_migration.sh
在上述示例中,我们在 worker
服务的 depends_on
部分使用长定义语法来定义 db_migration
服务的依赖。通过将 condition
字段设置为 service_completed_successfully
,我们指定了 worker
服务依赖于 db_migration
服务成功完成。
当我们使用 Docker Compose 启动应用程序时,Compose 将先运行 db_migration
服务,并等待其成功完成(即退出状态码为 0)。一旦 db_migration
服务成功完成,Compose 将启动 worker
服务。
通过使用 service_completed_successfully
参数,我们可以确保依赖服务在成功完成后,再启动相关的服务。这对于需要在依赖服务成功完成后才能进行后续操作的场景非常有用,如数据库迁移、初始化脚本等。
service_started
这个只是表示启动顺序,并不能保证健康状态.
service_healthy
和 service_completed_successfully
是长定义语法中用于定义依赖服务的两个不同条件。
service_healthy
:这个条件要求依赖服务处于健康状态(由健康检查指定),才会启动相关的服务。通过设置 condition: service_healthy
,Compose 将等待依赖服务的健康状态后再启动相关服务。健康状态通常是通过在容器中运行健康检查命令或脚本来确定的,例如检查 HTTP 响应或数据库连接等。service_completed_successfully
:这个条件要求依赖服务成功完成(即退出状态码为 0),才会启动相关的服务。通过设置 condition: service_completed_successfully
,Compose 将等待依赖服务成功完成后再启动相关服务。这通常用于需要确保特定操作或任务在依赖服务完成后才能进行的情况,例如数据库迁移、初始化脚本等。总结一下它们的区别:
service_healthy
关注依赖服务的健康状态,它要求依赖服务处于健康状态才能启动相关服务。service_completed_successfully
关注依赖服务的成功完成,它要求依赖服务在成功完成后(即退出状态码为 0)才能启动相关服务。在长定义语法中,required
字段用于指定依赖服务是否是必需的。它控制了当依赖服务未启动或不可用时的行为。
required
设置为 true
(默认值),如果依赖服务未启动或不可用,Compose 将阻止启动相关的服务,并显示警告信息。required
设置为 false
,Compose 仍会显示警告信息,但不会阻止启动相关的服务。相当于它是可选的,即使依赖服务未启动或不可用,相关服务仍会尝试启动。services:
web:
build: .
depends_on:
database:
required: false
database:
image: mysql:latest
下面看看一个完整的例子 docker-compose-test.yml
:
version: '3'
services:
rabbitmq:
hostname: rabbitmq_host
container_name: 'mq'
image: rabbitmq:3.9.11-management
restart: always
ports:
- "5772:5672" # AMQP
- "15772:15672" # Web UI
networks:
- app-network
environment:
RABBITMQ_DEFAULT_USER: root
RABBITMQ_DEFAULT_PASS: pwd
RABBITMQ_DEFAULT_VHOST: /
volumes:
- rabbitmq_data:/var/lib/rabbitmq/mnesia
healthcheck:
test: [ "CMD", "rabbitmq-diagnostics", "ping" ]
interval: 50s
timeout: 5s
retries: 3
selenium:
container_name: 'selenium'
image: selenium/standalone-chrome
restart: always
ports:
- "4444:4444"
networks:
- app-network
healthcheck:
test: [ "CMD", "curl", "-f", "http://localhost:4444/wd/hub/status" ]
interval: 30s
timeout: 5s
retries: 3
db:
container_name: 'mysql8'
image: mysql:8.0.32
# hostname: mysql_host
user: root
command:
--default-authentication-plugin=mysql_native_password
--character-set-server=utf8mb4
--collation-server=utf8mb4_unicode_ci
environment:
LANG: C.UTF-8
MYSQL_ROOT_PASSWORD: pwd
MYSQL_DATABASE: yinlian
ports:
- "3306:3306"
volumes:
- "./data/db/data:/var/lib/mysql"
- "./data/db/mysql-files:/var/lib/mysql-files"
- "./build/docker/mysqldb/my.cnf:/etc/my.cnf"
networks:
- app-network
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
interval: 30s
timeout: 5s
retries: 3
app-producer:
container_name: 'producer'
build:
context: .
dockerfile: Dockerfile
ports:
- "8001:8001"
command: ['echo','hello world, Frank']
depends_on:
db:
condition: service_healthy
rabbitmq:
condition: service_healthy
selenium:
condition: service_healthy
networks:
- app-network
networks:
app-network:
driver: bridge
volumes:
rabbitmq_data:
driver: local
如果 依赖服务启动失败了, app-producer
就不会启动 ,直接退出了