Docker Compose中的profiles和depends_on之间的交互

44次阅读
没有评论

问题描述

在使用Docker Compose时,遇到了一个问题。在下面的docker-compose.yml文件中,服务”bar”依赖于服务”foo”,但它们位于不同的profiles中。现在,当我只激活”profile bar”而不激活”profile foo”时,我希望服务”foo”也会启动,但实际上并没有发生。这是一个bug还是预期的行为?如果是预期的行为,原因是什么?是否有其他方法可以自动确保所有依赖项也会启动,或者我必须手动确保所选的profiles不会违反我的依赖关系?我使用的是Docker版本20.10.17和Docker Compose版本2.10.0。

services:
  foo:
    build: ./foo
    profiles: ["foo"]
  bar:
    build: ./bar
    profiles: ["bar"]
    depends_on:
      foo:
        condition: service_completed_successfully

P.S.:正如@larsks所指出的,官方文档中提到:

但请记住,docker compose仅会自动启用命令行上的服务的profiles,而不会自动启用任何依赖项的profiles。这意味着目标服务所依赖的所有服务必须具有与之相同的profile,始终启用(通过省略profiles)或显式启用匹配的profile。

然而,示例代码中包含了以下内容:

# this will fail because profile "dev" is disabled
$ docker compose up phpmyadmin

“fail”这个词对我来说意味着docker compose up bar将无法启动,或者至少会打印出错误或警告,但实际上这两者都没有发生。

以下是一个最小化的示例:

services:
  foo:
    image: hello-world
    profiles: ["foo"]
  bar:
    image: hello-world
    depends_on:
      foo:
        condition: service_completed_successfully
$ docker compose up

日志显示它并没有失败,它只是静默地执行了bar而没有执行foo,也没有失败或打印任何消息。

P.P.S.:我在https://github.com/docker/compose/issues/9795上创建了一个问题。

解决方案

请注意以下操作注意版本差异及修改前做好备份。

方案1

根据Docker Compose的文档,服务的profiles只有在命令行上启用时才会自动启用,而不会自动启用任何依赖项的profiles。这就是为什么在你的情况下,即使你只激活了”profile bar”,”foo”服务也不会自动启动的原因。

为了解决这个问题,你可以考虑将依赖关系与profiles分离,以确保它们始终启动。以下是一种可能的解决方案:

  1. 将”foo”服务的profile设置为空,这样它将始终启动。
  2. 在”bar”服务的depends_on部分,删除condition属性,这样它将始终依赖于”foo”服务。

下面是修改后的docker-compose.yml文件的示例:

services:
  foo:
    build: ./foo
    profiles: []
  bar:
    build: ./bar
    depends_on:
      - foo

通过这样的修改,无论你激活哪个profile,”foo”服务都将始终启动,并且”bar”服务将始终依赖于”foo”服务。

方案2

另一种解决方案是使用脚本或工具来管理容器的启动顺序。你可以编写一个脚本来手动控制容器的启动顺序,或者使用一些第三方工具来管理容器的依赖关系。

以下是一个简单的bash脚本示例,可以在容器”foo”启动后启动容器”bar”:

#!/bin/bash
# 启动容器foo
docker-compose up -d foo
# 等待容器foo完全启动
while ! docker-compose exec foo echo "Container foo is ready"; do
  sleep 1
done
# 启动容器bar
docker-compose up -d bar

在这个示例中,我们首先使用docker-compose up命令启动容器”foo”。然后,使用一个循环来等待容器”foo”完全启动(这里是通过在容器内运行echo命令来测试)。一旦容器”foo”就绪,我们再使用docker-compose up命令启动容器”bar”。

通过使用这样的脚本,你可以手动控制容器的启动顺序,并确保依赖关系得到满足。

请注意,这只是一种解决方案,你可以根据自己的需求进行调整和修改。

总结

在Docker Compose中,当服务的profiles被激活时,只有该服务的profiles会自动启用,而不会自动启用任何依赖项的profiles。为了确保所有依赖项也会启动,你可以将依赖关系与profiles分离,或者使用脚本或工具来管理容器的启动顺序。以上是两种可能的解决方案,你可以根据自己的需求选择适合的方法。

正文完