【问题标题】:How to start service only when other service had completed?如何仅在其他服务完成后才启动服务?
【发布时间】:2021-10-18 15:33:07
【问题描述】:

使用 compose 我只想在另一个服务以代码 0 退出后启动一个服务。

我对此功能有多种需求。基本需求是我所拥有的:

  • 数据库服务
  • 数据库迁移服务
  • 应用服务

数据库服务将启动一个空数据库。我的应用程序需要它在数据库中的架构设置,所以我有第二个服务,它将在它运行时执行此操作。完成后,该服务将成功退出 - 我可以在我的 docker compose 日志文件中看到:

webservices_kong-migration_1 以代码 0 退出

我不希望应用程序服务在数据库迁移完成之后启动。

我的应用程序服务的 docker-compose 文件中有以下内容:

depends_on:
  kong-database:
    condition: service_healthy
  kong-migration:
    condition: service_started

我知道这是错误的,因为我可以在我的 docker-compose 日志中看到应用程序在迁移开始之后但尚未完成之前启动,导致应用程序失败。

(我一直以https://github.com/Kong/docker-kong/blob/master/compose/docker-compose.yml为例)

docker-compose 是否具有执行此操作的功能,还是我应该考虑另一种方法?

【问题讨论】:

  • 我正在尝试使用开箱即用的图像,而不是构建自己的图像,这必须是可能的,因为 kong 是一个通用标准
  • 我认为这是不可能的,因为 docker 应该让容器保持运行,这与我认为的目的有点冲突。如何设置一个标志以向应用程序发出迁移正在进行中的信号,并让它向用户提供“服务迁移正在进行中”错误消息?

标签: docker docker-compose


【解决方案1】:

这是对@zooblin 答案的补充

由于docker-compose 1.29版,我们可以通过condition: service_completed_successfully来实现

在您的场景中,数据库服务启动会花费一些时间,所以迁移脚本应该在数据库完全启动后执行。

迁移脚本成功执行后,应用服务应该会启动。

docker-compose.yaml可能如下(这里我们以cassandra为例,对于其他数据库,你可以修改healthcheck命令):

version: '3.8'
services:
  applicaion-service:
    image: your-applicaion-service:0.0.1
    depends_on:
      cassandra-init-keyspace:
        condition: service_completed_successfully


  cassandra:
    image: cassandra:4.0.1
    ports:
      - "9042:9042"
    healthcheck:
      test: ["CMD", "cqlsh", "-u cassandra", "-p cassandra" ,"-e describe keyspaces"]
      interval: 15s
      timeout: 10s
      retries: 10

  cassandra-init-keyspace:
    image: cassandra:4.0.1
    depends_on:
      cassandra:
        condition: service_healthy
    volumes:
      - ./src/main/resources/cassandra/init.cql:/init.cql
    command: /bin/bash -c "echo loading cassandra keyspace && cqlsh cassandra -f /init.cql"

【讨论】:

    【解决方案2】:

    docker-compose 1.29 版附带build in functionalityservice_completed_successfully。 根据spec

    service_completed_successfully - 指定依赖项在启动依赖服务之前应运行到成功完成。

    depends_on:
      <service-name>:
        condition: service_completed_successfully
    

    【讨论】:

      【解决方案3】:

      Docker compose 没有任何开箱即用的解决方案。
      但是存在许多解决此问题的良好实现。

      更好的解决方案之一是使用服务发现作为在Joyent Containerpilot 中实现的ConsulAutopilot model

      即使在根本不存在服务依赖的 docker swarm 集群中,该模型也允许实现服务之间的依赖关系。

      Containerpilot 作业模型允许创建简单的脚本以使启动的服务保持正确的顺序。

      【讨论】:

        【解决方案4】:

        对于那些正在寻找答案的人来说,仍然没有现成的解决方案。

        解决方法是使用包装脚本:https://docs.docker.com/compose/startup-order/

        在 Robert 的例子中,您可以想象一个脚本循环并等待,直到无法再 ping 数据库服务(直到服务停止)。

        【讨论】:

          猜你喜欢
          • 2020-03-29
          • 1970-01-01
          • 1970-01-01
          • 2016-08-12
          • 1970-01-01
          • 2019-11-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多