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

axkjgtzd  于 2023-03-17  发布在  Docker
关注(0)|答案(6)|浏览(225)

docker-compose 2.1提供了用depends_on指定condition的好特性。
版本3不再支持depends_on的条件形式。
不幸的是,文档没有解释为什么condition表单被删除,也没有任何关于如何使用V3以上版本实现该行为的具体建议。

0yg35tkg

0yg35tkg1#

在composition中不再指定容器依赖项。它们只在启动时有效,并且在依赖容器在运行时重新启动时不起作用。每个容器都应该包含一个机制,当连接断开时,重试重新连接到依赖的服务。许多连接到数据库或API服务的库都有可配置的内置重试。我会研究这个问题。无论如何,生产代码都需要它。

7xllpg7q

7xllpg7q2#

1.27.0中,2.x和3.x与COMPOSE_SPEC架构合并。
version现在是可选的。因此,您只需删除它并像以前一样指定一个条件:

services:
  web:
    build: .
    depends_on:
      redis:
        condition: service_healthy
  redis:
    image: redis
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 1s
      timeout: 3s
      retries: 30
zaqlnxep

zaqlnxep3#

有一些外部工具可以让你模仿这种行为,例如,使用dockerize工具,你可以用dockerize -wait来 Package 你的CMDENTRYPOINT,这将阻止你的应用程序运行,直到指定的服务准备就绪。
如果您的Docker合成文件过去是这样的:

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

然后你可以在你的v3合成文件中使用dockerize,如下所示:

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
c6ubokkw

c6ubokkw4#

我只是想添加我的解决方案,当运行postgres和一个应用程序通过docker-compose,我需要应用程序等待init sql脚本完成,然后再开始。
dockerize似乎在等待db端口可用(端口5432),这与可以在docker 3中使用的depends_on是等价的:

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/

问题:

如果您有一个很大的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"

然后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
j2cgzkjk

j2cgzkjk5#

我到达此页是因为一个容器不等待依赖的容器,我必须运行docker system prune才能使其工作。出现orphaned container错误,提示我运行prune

628mspwn

628mspwn6#

如果有人正在寻找这个的docker stack版本:
它看起来像它是目前不可能定义的依赖关系时使用Docker堆栈:https://github.com/docker/cli/issues/3880

相关问题