docker 对接器-合成:如何等待其他服务准备就绪?

vdgimpew  于 2022-11-28  发布在  Docker
关注(0)|答案(7)|浏览(183)

我有下面的docker-compose,我需要等待服务jhipster-registry启动并接受连接,然后再启动myprogram-app
我尝试了healtcheck方法,遵循官方文档https://docs.docker.com/compose/compose-file/compose-file-v2/

version: '2.1'
services:
    myprogram-app:
        image: myprogram
        mem_limit: 1024m
        environment:
            - SPRING_PROFILES_ACTIVE=prod,swagger
            - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/eureka
            - SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config
            - SPRING_DATASOURCE_URL=jdbc:postgresql://myprogram-postgresql:5432/myprogram
            - JHIPSTER_SLEEP=0
            - SPRING_DATA_ELASTICSEARCH_CLUSTER_NODES=myprogram-elasticsearch:9300
            - JHIPSTER_REGISTRY_PASSWORD=53bqDrurQAthqrXG
            - EMAIL_USERNAME
            - EMAIL_PASSWORD
        ports:
            - 8080:8080
        networks:
          - backend
        depends_on:
          - jhipster-registry:
              "condition": service_started
          - myprogram-postgresql
          - myprogram-elasticsearch
    myprogram-postgresql:
        image: postgres:9.6.5
        mem_limit: 256m
        environment:
            - POSTGRES_USER=myprogram
            - POSTGRES_PASSWORD=myprogram
        networks:
          - backend
    myprogram-elasticsearch:
        image: elasticsearch:2.4.6
        mem_limit: 512m
        networks:
          - backend
    jhipster-registry:
        extends:
            file: jhipster-registry.yml
            service: jhipster-registry
        mem_limit: 512m
        ports:
            - 8761:8761
        networks:
          - backend
        healthcheck:
          test: "exit 0"
networks:
  backend:
    driver: "bridge"

但在运行docker-compose up时出现以下错误:

ERROR: The Compose file './docker-compose.yml' is invalid because:
services.myprogram-app.depends_on contains {"jhipster-registry": {"condition": "service_started"}}, which is an invalid type, it should be a string

是我做错了什么,还是这个功能不再受支持?如何在服务之间实现这种同步?

更新版本

version: '2.1'
services:
    myprogram-app:
        image: myprogram
        mem_limit: 1024m
        environment:
            - SPRING_PROFILES_ACTIVE=prod,swagger
            - EUREKA_CLIENT_SERVICE_URL_DEFAULTZONE=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/eureka
            - SPRING_CLOUD_CONFIG_URI=http://admin:$${jhipster.registry.password}@jhipster-registry:8761/config
            - SPRING_DATASOURCE_URL=jdbc:postgresql://myprogram-postgresql:5432/myprogram
            - JHIPSTER_SLEEP=0
            - SPRING_DATA_ELASTICSEARCH_CLUSTER_NODES=myprogram-elasticsearch:9300
            - JHIPSTER_REGISTRY_PASSWORD=53bqDrurQAthqrXG
            - EMAIL_USERNAME
            - EMAIL_PASSWORD
        ports:
            - 8080:8080
        networks:
          - backend
        depends_on:
          jhipster-registry:
            condition: service_healthy
          myprogram-postgresql:
            condition: service_started
          myprogram-elasticsearch:
            condition: service_started
        #restart: on-failure
    myprogram-postgresql:
        image: postgres:9.6.5
        mem_limit: 256m
        environment:
            - POSTGRES_USER=myprogram
            - POSTGRES_PASSWORD=tuenemreh
        networks:
          - backend
    myprogram-elasticsearch:
        image: elasticsearch:2.4.6
        mem_limit: 512m
        networks:
          - backend
    jhipster-registry:
        extends:
            file: jhipster-registry.yml
            service: jhipster-registry
        mem_limit: 512m
        ports:
            - 8761:8761
        networks:
          - backend
        healthcheck:
          test: ["CMD", "curl", "-f", "http://jhipster-registry:8761", "|| exit 1"]
          interval: 30s
          retries: 20
          #start_period: 30s
networks:
  backend:
    driver: "bridge"

更新后的版本出现了不同的错误,

ERROR: for myprogram-app  Container "8ebca614590c" is unhealthy.
ERROR: Encountered errors while bringing up the project.

说jhipster-registry的容器不健康,但可以通过浏览器访问。如何修复healthcheck中的命令使其正常工作?

tp5buhyn

tp5buhyn1#

最佳方法-弹性应用启动

虽然docker * 确实 * 支持启动依赖项,但他们正式建议更新应用启动逻辑,以测试外部依赖项的可用性并重试。这对于可以在运行中重新启动的健壮应用来说有很多好处,除了避免docker compose up中的争用条件

  • 编写1.27.0+
    depends_on重新出现在构成规范的docker compose v1.27.0+(在v3中已弃用)中
    每个服务还应该实现一个service_healthy检查,以便能够报告它是否已完全设置并准备好接受下游依赖项。
version: '3.0'
services:
  php:
    build:
      context: .
      dockerfile: tests/Docker/Dockerfile-PHP
    depends_on:
      redis:
        condition: service_healthy
  redis:
    image: redis
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 1s
      timeout: 3s
      retries: 30

wait-for-it.sh

Docker根据他们关于Control startup and shutdown order in Compose的文档推荐的方法是下载wait-for-it.sh,它接受domain:port进行轮询,如果成功,则执行下一组命令。

version: "2"
services:
  web:
    build: .
    ports:
      - "80:8000"
    depends_on:
      - "db"
    command: ["./wait-for-it.sh", "db:5432", "--", "python", "app.py"]
  db:
    image: postgres

注意:这需要覆盖映像的启动命令,因此请确保您知道要传递什么以维护默认启动的奇偶性。

进一步阅读

3j86kqsm

3j86kqsm2#

文档建议,* 特别是在Docker Compose版本2文件中 *,depends_on:可以是一个字符串列表,或者是一个Map,其中键是服务名称,值是条件。对于没有(或需要)健康检查的服务,有一个service_started条件。

depends_on:
  # notice: these lines don't start with "-"
  jhipster-registry:
    condition: service_healthy
  myprogram-postgresql:
    condition: service_started
  myprogram-elasticsearch:
    condition: service_started

根据您对程序及其库的控制程度,如果您可以安排服务能够在其依赖项不一定可用的情况下启动,则会更好(相当于在服务运行时其依赖关系消失时仍能正常工作),并且不使用depends_on:选项。如果数据库关闭,则可能会返回HTTP 503服务不可用错误。如果依赖项不可用,则立即退出,但使用restart: on-error之类的设置来请求编排器重新启动服务。

agxfikkp

agxfikkp3#

更新至版本3+.

请遵循版本3的文档:
使用depends_on时,有几点需要注意:
depends_on在启动web之前不等待db和redis“就绪”-仅在它们已经启动之前。
如果您需要等待服务就绪,请参阅控制启动顺序以了解有关此问题的详细信息以及解决此问题的策略。

版本3不再支援depends_on的条件格式。

使用版本3合成文件在群模式下部署堆栈时,将忽略depends_on选项.
我会考虑使用restart_policy选项来配置 myprogram-app,使其在 jhipster-registry 启动并接受连接之前重新启动:

restart_policy:
        condition: on-failure
        delay: 3s
        max_attempts: 5
        window: 60s
oo7oh9g9

oo7oh9g94#

虽然你已经得到了一个答案,但应该提到的是,你试图实现的目标有一些令人讨厌的风险。
理想情况下,服务应该能够自我满足,并且足够智能地重试并等待相关性可用(在关闭之前)。否则,您将更容易受到一个故障传播到其他服务的影响。另外,与手动启动不同,系统重新引导可能会忽略相关性顺序。
如果一个服务崩溃导致整个系统瘫痪,您可能有一个工具来重新启动所有的东西,但最好有能抵抗这种情况的服务。

zf2sa74q

zf2sa74q5#

我发现最好的方法是在入口点检查所需的端口。有不同的方法可以做到这一点,例如wait-for-it,但我喜欢使用这个解决方案,它是apline和bash映像之间的跨平台解决方案,并且不从GitHub下载自定义脚本:
安装netcat-openbsd(适用于aptapk)。然后在入口点(适用于#!/bin/bash#!/bin/sh)中:

#!/bin/bash

wait_for()
{
  echo "Waiting $1 seconds for $2:$3"
  timeout $1 sh -c 'until nc -z $0 $1; do sleep 0.1; done' $2 $3 || return 1
  echo "$2:$3 available"
}

wait_for 10 db 5432
wait_for 10 redis 6379

如果您不想打印任何内容,也可以将其设置为1行。

2lpgd968

2lpgd9686#

在尝试了几种方法后,IMO最简单和最优雅的选择是使用带有-wait标志的jwilder/dockerize实用程序映像。下面是一个简单的例子,我需要在启动应用之前准备好PostgreSQL数据库:

version: "3.8"
services:
  # Start Postgres.
  db:
    image: postgres

  # Wait for Postgres to be joinable.
  check-db-started: 
    image: jwilder/dockerize:0.6.1
    depends_on:
      - db
    command: 'dockerize -wait=tcp://db:5432'
  
  # Only start myapp once Postgres is joinable.
  myapp:
    image: myapp:latest
    depends_on:
      - check-db-started
yzuktlbb

yzuktlbb7#

有了新的docker compose API,我们现在可以使用新的--wait选项:

docker compose up --wait

如果您的服务进行了健康检查,Docker会一直等到它处于“健康”状态;否则,它会等待服务启动。这就是为什么对所有服务进行相关的健康检查是至关重要的。
请注意,此选项会自动激活--detach选项。

相关问题