What is the alternative to condition form of depends_on in docker-compose Version 3?
docker-compose 2.1提供了很好的功能,可以用
Version 3 no longer supports the condition form of depends_on.
不幸的是,文档没有说明为什么删除了
与在compose中指定容器依赖项有所不同。它们仅在启动时有效,而在运行时重新启动从属容器时无效。而是,每个容器都应包含在断开连接后重试重新连接到相关服务的机制。许多用于连接数据库或REST API服务的库都具有可配置的内置重试。我会调查一下。无论如何,生产代码都需要它。
有些外部工具可让您模仿此行为。例如,使用dockerize工具,您可以将
如果您的docker-compose文件以前看起来像这样:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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 |
然后可以在
1 2 3 4 5 6 7 8 9 | 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 |
从1.27.0起,将2.x和3.x与COMPOSE_SPEC架构合并。
版本现在是可选的。因此,您只需删除它并像以前一样指定一个条件即可:
1 2 3 4 5 6 7 8 9 10 11 12 13 | services: web: build: . depends_on: redis: condition: service_healthy redis: image: redis healthcheck: test: ["CMD","redis-cli","ping"] interval: 1s timeout: 3s retries: 30 |
我只是想在通过docker-compose运行postgres和一个应用程序时添加我的解决方案,因此我需要该应用程序等待初始化sql脚本完成后再开始。
dockerize似乎正在等待db端口可用(端口5432),这与
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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/ |
问题:
如果您的启动脚本较大,则该应用程序将在完成之前启动,因为
尽管我确实同意应在应用程序逻辑中实现该解决方案,但我们遇到的问题仅是当我们要运行测试并用测试数据预填充数据库时,因此在代码外实施解决方案更有意义因为我倾向于不喜欢引入代码"使测试有效"
解决方案:
对postgres容器执行健康检查。
对我来说,这意味着检查pid 1的命令是否为
在应用程序端编写一个脚本,该脚本将等待
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/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文件中定义的入口点,以便我们可以在应用程序启动之前运行等待脚本。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | 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 |
不要依赖于另一个容器来启动,而应尝试从一个容器化的应用程序中退出,如果在尝试访问一个未处于就绪状态的容器时收到连接错误。这种策略与适用于您的容器的重新启动策略一起使用将重新启动您的应用程序容器,直到连接可用或满足其他条件为止