docker-compose 2.1提供了使用depends_on
指定condition
的不错功能。当前的Docker-Compose文档指出:
版本3不再支持依赖的条件形式。
不幸的是,文档没有解释,为什么要删除condition
表格,并且缺乏有关如何使用V3向上实施该行为的任何特定建议。
远离指定组合中的容器依赖性的转变。它们仅在启动时有效,并且在运行时重新启动依赖容器时不工作。相反,每个容器应包括重试的机制,以重新连接连接连接时。许多可以连接到数据库或REST API服务的库具有可配置的内置重试。我会调查。无论如何,生产代码都需要。
来自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
有一些外部工具让您模仿此行为。例如,使用Dockerize工具,您可以将CMD
或ENTRYPOINT
与dockerize -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
然后,您可以在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
只是以为我会在运行postgres和通过docker-compose应用程序时添加解决方案>
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/
问题:
如果您有一个大初始脚本,则应用程序将在完成之前开始,因为depends_on
仅等待DB端口。
尽管我确实同意应在应用程序逻辑中实现该解决方案,但我们遇到的问题仅在于我们要运行测试并使用测试数据对数据库进行预填充,因此在代码之外实现解决方案是更有意义的因为我倾向于不喜欢引入"使测试工作"
引入代码解决方案:
在Postgres容器上实现健康检查。对我来说,这意味着检查pid 1的命令是 postgres
,因为它将在init db脚本运行
在应用程序侧写一个脚本,该脚本将等待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 image,那么我们可以继续为您的Docker文件使用Docker文件已发表的图像。
我们还覆盖了应用程序的Docker文件中定义的输入点,以便我们可以在应用程序启动之前运行WAIT脚本
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
如果正在寻找以下 docker stack
版本:
使用Docker堆栈时,目前似乎无法定义依赖项:https://github.com/docker/cli/issues/3880
我到达了此页面,因为一个容器不会等待一个,具体取决于一个容器,我不得不运行docker system prune
才能使其正常工作。有一个orphaned container
错误,促使我运行prune
。