如何控制docker-compose构建的顺序?

36

我需要构建三个服务,A、B和C。A应该是第一个构建的,因为B和C依赖于A(它们把A作为镜像导入)。我原本以为它们应该按顺序构建,但我发现它们是以随机顺序构建的?

那么,在docker-compose.yml中如何控制构建顺序呢?


寻求更清晰的解释,你是在说docker-compose build来构建镜像,还是说docker-compose up -d来构建/运行容器? - Arthur Weborg
我不确定这会有多大的改变,但我可能会提出一个不同的问题/参考此问题,或者建议添加/编辑一些措辞,并根据所引用的内容添加赏金或自己进行一些挖掘。 - Arthur Weborg
请查看这个解决方案。它对我有效。 - СанЁк Баглай
5个回答

21

以上被接受的答案似乎不正确。

根据文档所示:

使用 depends_on 时需注意以下几点:

depends_on 不会等待 db 和 redis “就绪”后才启动 web - 只要它们已经启动便可。 如果您需要等待服务就绪,请查看控制启动顺序以了解此问题并获取解决方案的策略。

版本3不再支持 depends_on 的条件形式。

在使用版本3 Compose文件部署堆栈模式时,depends_on选项将被忽略。


我认为这个答案在某种程度上是有道理的,我遇到了一个问题,它源于这个特定文档的一部分 - 在另一个容器运行之后才能构建其中一个容器。这就是所谓的“depends_on在启动web之前不等待db和redis准备就绪”。然而,与采纳的答案不同意是错误的。OP问的是关于控制构建顺序而已,而这条评论则涉及容器运行顺序。 - netchkin
3
根据docker-compose的文档,使用depends_ondocker-compose build中不是预期的用法。我同意,它似乎会影响构建阶段,但不能保证。 - Arthur Weborg
1
@ArthurWeborg 自从我写下第一条评论以来,Docker 和 Docker Compose 已经有足够的变化,最新版本支持 多阶段构建。这个功能解决了很多问题;至少,我不再使用 depends_on 从相同的基础镜像构建自定义镜像。 - maxkoryukov
@maxkoryukov,你能详细说明一下吗?多阶段构建是否也会影响运行顺序? - Quinten Scheppermans
@maxkoryukov,多阶段构建是这里的解决方案吗?我认为您无法从一个构建中标记多个映像。 - rgov
显示剩余3条评论

15

更新:最近的实践中,我发现我的回答仅与运行顺序有关。
请参考Quinten Scheppermans的回答和Authur Weborg关于 dobi 的评论。

您可以使用depends_on指令控制构建顺序。

services:
  ...

  B:
    depends_on:
      - A
  C:
    depends_on:
      - A

17
depends_on 对构建阶段有影响吗?我查看了文档,似乎只对启动阶段有影响。 - Kim
3
可以的。不确定为什么没有记录。 - Oluwafemi Sule
19
我在 GitHub 上联系了 Docker Compose。他们的回复是:depends_on 不是 docker-compose build 的预期用法 - Arthur Weborg
1
谢谢你让我知道这个。我之前不知道 dobi。如果我没记错的话,基于服务依赖关系的有序构建行为已经改变了;正如你所指出的,现在只与有序运行有关。我会编辑答案并引用你的评论。 - Oluwafemi Sule
2
在大多数情况下,多阶段构建更为合适。 - maxkoryukov
显示剩余4条评论

4
自从使用compose v2版本以来,默认启用了BuildKit,它可以并行构建镜像。
如果禁用BuildKit,则可以按照docker-compose.yml文件中的顺序构建镜像。请注意保留HTML标记。
DOCKER_BUILDKIT=0 docker-compose build

如果您仍然希望并行构建镜像,可以考虑在多个docker-compose.yml文件中定义services进行构建,然后在另一个docker-compose.yml文件中进行部署。


3
如果你需要在另一个服务之前运行一个服务,可以在docker-compose.yml文件中设置depends_on: - foo,然后使用docker-compose run bar命令。
例如:
# docker-compose.yml

  services:
    foo:
        . . . 
    bar:
         . . . 
      depends_on:
        - foo

然后运行,

# terminal

user@Name Docker % docker-compose run bar

然而,根据文档,这只能控制进程启动的顺序,并不能控制它们完成的顺序。这往往会导致依赖服务未能正确启动。可能的解决方案包括使用wait-for-itwait-forDockerise。在实施上述任何解决方案之前,建议先阅读文档,因为存在一些注意事项。

0

https://github.com/docker/compose/blob/e9220f45df07c1f884d5d496507778d2cd4a1687/compose/project.py#L182-L183所述:

尽可能保留self.services的原始顺序,根据需要重新排序以解决依赖关系。

因此,对我而言,通过手动将依赖服务排在前面,然后按照其他服务使用的顺序进行排序,最后是其他服务,这种方法可以实现。

示例

version: '3'
services:
    mydb:
        image: mydb
    serviceA:
        build: 
            dockerfile: DockerfileA
        depends_on:
            - mydb
    serviceB:
        build:
            dockerfile: DockerfileB # which contains 'FROM serviceA'
        depends_on:
            - mydb

来源:https://github.com/docker/compose/issues/5228#issuecomment-565469948


由于构建是并行运行的,因此这不再起作用。 - minnow

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接