Docker-Compose:如何等待其他服务准备就绪?

时间:2018-09-13 22:57:33

标签: docker docker-compose wait

我有以下 docker-compose ,我需要在启动 myprogram-app之前等待服务 jhipster-registry 启动并接受连接

我按照官方文档https://docs.docker.com/compose/compose-file/compose-file-v2/

尝试了healtcheck方法
 var strA = 
"%7Bid%22%3A1001%2C%22name%22%3A%22The+Antique+Store%22%7D%2C%7B%22id%22%3A1010%2C%22name%22%3A%22Clothes%22%7D%2C%7B%22id%22%3A1349%2C%22name%22%3A%22Old+Store%22%7D";

    var strB = "%7Bid%22%3A1001%2C%22name%22%3A%22The+Modern+Store%22%7D%2C%7B%22id%22%3A1010%2C%22name%22%3A%22Clothes%22%7D%2C%7B%22id%22%3A1349%2C%22name%22%3A%22New+Store%22%7D";

    var arrA = JSON.parse(decodeURIComponent(',{""' + strA + '",:""}'));

    var arrB = JSON.parse(decodeURIComponent(',{""' + strB + '",:""}'));

console.log(arrA)
console.log(arrB)

var res = Object.assign(arrA, arrB);

console.log(encodeURIComponent(JSON.stringify(res)))

但是运行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"

认为jhipster-registry的容器不健康,但是可以通过浏览器访问。如何在运行状况检查中修复该命令以使其起作用?

5 个答案:

答案 0 :(得分:5)

documentation建议,特别是在Docker Compose版本2文件中, depends_on:可以是字符串列表,也可以是键为服务名称和值是条件。对于您没有(或不需要)健康检查的服务,有一个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这样使用a setting来要求协调器重新启动服务。

答案 1 :(得分:5)

更新到版本3 +。

请遵循版本3中的documents

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

depends_on不会等待db和redis处于“就绪”状态 启动网络-仅在启动之前。
如果您需要等待 要准备好服务,请参阅控制启动顺序以获取更多信息。 这个问题和解决它的策略。
版本3不再 支持depends_on的条件格式。
depends_on选项是 在群模式下使用版本3 Compose部署堆栈时忽略 文件。

我会考虑使用restart_policy选项将您的 myprogram-app 配置为重新启动,直到 jhipster-registry 启动并接受连接:

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

答案 2 :(得分:0)

尽管您已经得到了答案,但应该指出的是,您要实现的目标存在一些令人讨厌的风险。

理想情况下,服务应具有足够的自我能力和智能,可以重试并等待依赖项可用(在中断之前)。否则,您将更容易遭受传播到其他服务的一种失败。还请注意,与手动启动不同,系统重新启动可能会忽略依赖关系顺序。

如果一个服务崩溃导致您的所有系统崩溃,则您可能具有重新启动所有内容的工具,但是最好的方法是抵抗这种情况。

答案 3 :(得分:0)

最佳方法-弹性应用启动

虽然Docker支持启动依赖项,但他们正式建议更新您的应用启动逻辑以测试外部依赖项的可用性并重试。除了规避docker compose up

中的竞争条件外,这对于健壮的应用程序具有很多好处,这些健壮的应用程序可能在运行中立即重启。

Docker方法-wait-for-it.sh

码头工人根据其在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

注意:这需要覆盖映像的启动命令,因此请确保您知道要传递的内容以保持默认启动的奇偶校验。

历史方法-depends_on - service_healthy(不推荐3 +)

从历史上看,您可以定义一个healthcheck(仍然是一种很好的做法),然后将depends_on的条件设置为service_healthy,但是在3.0中不推荐使用depends的条件方差

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

进一步阅读

答案 4 :(得分:0)

我发现的最佳方法是检查入口点中的所需端口。有不同的方法可以做到这一点,例如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-liner。