在docker-compose版本3中,depends_on的条件形式的替代方法是什么?

m o*_*m o 38 docker docker-compose

泊坞窗,撰写2.1提供了很好的功能,以指定conditiondepends_on.当前的docker-compose文档说明:

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

不幸的是,文档没有解释,为什么condition表单被删除,并且缺乏关于如何使用V3向上实现该行为的任何具体建议.

Jak*_*kul 16

有一些外部工具可以让您模仿这种行为。例如,使用dockerize 工具,您可以包装您的CMDENTRYPOINTdockerize -wait这将阻止运行您的应用程序,直到指定的服务准备就绪。

如果您的 docker-compose 文件以前看起来像这样:

version: '2.1'
services:
  kafka:
    image: spotify/kafka
    healthcheck:
      test: nc -z localhost 9092
  webapp:
     image: foo/bar # your image
     healthcheck:
       test: curl -f http://localhost:8080
  tests:
     image: bar/foo # your image
     command: YOUR_TEST_COMMAND
     depends_on:
       kafka:
         condition: service_healthy
       webapp:
         condition: service_healthy
Run Code Online (Sandbox Code Playgroud)

然后你可以dockerize在你的v3撰写文件中使用这样的:

version: '3.0'
services:
  kafka:
    image: spotify/kafka
  webapp:
     image: foo/bar # your image
  tests:
     image: bar/foo # your image
     command: dockerize -wait tcp://kafka:9092 -wait web://webapp:8080 YOUR_TEST_COMMAND
Run Code Online (Sandbox Code Playgroud)


Ber*_*ard 13

在compose中指定容器依赖关系已经有了一步之遥.它们仅在启动时有效,并且在运行时重新启动相关容器时不起作用.相反,每个容器应包括在删除连接时重试重新连接到从属服务的机制.许多连接到数据库或REST API服务的库都具有可配置的内置重试.我会调查一下.无论如何,生产代码都需要它.

  • 他们雇用了Lennart Poettering或其他人吗?他们为什么要为我们做出这样的决定?在实际的有效用例中,您要在启动时进行测试,然后重试与从属服务的连接不是用例。 (17认同)
  • “它们仅在启动时有效”这对于健康检查和“depends_on:service:service-healthy”来说不是这样,对吧? (2认同)

qua*_*nta 11

1.27.0 开始,2.x 和 3.x 与COMPOSE_SPEC架构合并。

版本现在是可选的。因此,您可以删除它并像以前一样指定条件

services:
  web:
    build: .
    depends_on:
      redis:
        condition: service_healthy
  redis:
    image: redis
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 1s
      timeout: 3s
      retries: 30
Run Code Online (Sandbox Code Playgroud)

  • 它不适用于 docker-compose 1.29 和 docker stack deploy (5认同)
  • 并补充一点:“docker-compose”无论如何都不是最先进的。去掉它。`docker compose` 就是你想去的地方。如果没有安装,例如`apt-get install docker-compose-plugin`来启用它。考虑了所有选项后,我认为“healthcheck”加上“depends_on”和“service_healthy”条件似乎是最好的!如果没有“service_healthy”条件,健康检查将被完全忽略。同样让我困惑的是:compose 文件格式 v2/v3 与 docker-compose 版本 2 没有任何关系(目前没有 3)。上述合并是最先进的,docker-compose 目前处于 2 (2认同)

Muj*_*uji 6

只是想我会在通过 docker-compose 运行 postgres 和应用程序时添加我的解决方案,我需要应用程序在开始之前等待 init sql 脚本完成。

dockerize 似乎等待 db 端口可用(端口 5432),这是depends_on可以在 docker 3 中使用的等效端口:

version: '3'

services:
  app:
    container_name: back-end
    depends_on:
      - postgres
  postgres:
    image: postgres:10-alpine
    container_name: postgres
    ports:
      - "5432:5432"
    volumes:
      - ./docker-init:/docker-entrypoint-initdb.d/
Run Code Online (Sandbox Code Playgroud)

问题:

如果您有一个大的 init 脚本,该应用程序将在该脚本完成之前启动,因为depends_on它只等待 db 端口。

尽管我确实同意应该在应用程序逻辑中实现解决方案,但我们遇到的问题仅适用于我们想要运行测试并使用测试数据预填充数据库时,因此像我倾向于的那样在代码之外实现解决方案更有意义不像引入代码“使测试工作”

解决方案:

对 postgres 容器实施健康检查。对我来说,这意味着检查 pid 1 的命令是postgres因为当 init db 脚本正在运行时它将在 pid 1 上运行不同的命令

在应用程序端编写一个脚本,等待postgres成为healthy. 该脚本如下所示:

#!/bin/bash
function check {
  STATUS=\`curl -s --unix-socket /var/run/docker.sock http:/v1.24/containers/postgres/json | python -c 'import sys, json; print json.load('sys.stdin')["State"]["Health"]["Status"]'\`

  if [ "$STATUS" = "healthy" ]; then
    return 0
  fi
  return 1
}

until check; do
  echo "Waiting for postgres to be ready"
  sleep 5
done

echo "Postgres ready"
Run Code Online (Sandbox Code Playgroud)

然后 docker-compose 应该挂载脚本的目录,这样我们就不会编辑应用程序的 Dockerfile,如果我们使用自定义 postgres 图像,这样我们就可以继续使用 docker 文件来发布图像。

我们还覆盖了应用程序的 docker 文件中定义的入口点,以便我们可以在应用程序启动之前运行等待脚本

version: '3'

services:
  app:
    container_name: back-end
    entrypoint: ["/bin/sh","-c","/opt/app/wait/wait-for-postgres.sh && <YOUR_APP_START_SCRIPT>"]
    depends_on:
      - postgres
    volumes:
      - //var/run/docker.sock:/var/run/docker.sock
      - ./docker-scripts/wait-for-postgres:/opt/app/wait
  postgres:
    image: postgres:10-alpine
    container_name: postgres
    ports:
      - "5432:5432"
    volumes:
      - ./docker-init:/docker-entrypoint-initdb.d/
      - ./docker-scripts/postgres-healthcheck:/var/lib
    healthcheck:
      test: /var/lib/healthcheck.sh
      interval: 5s
      timeout: 5s
      retries: 10
Run Code Online (Sandbox Code Playgroud)