我正在尝试在Docker中运行depends_on
我的Postgresql的应用程序
假设我的数据库PostgreSQL现在没有运行
并在我的docker-compose.yml
中:
version: "3"
services:
myapp:
depends_on:
- db
container_name: myapp
build:
context: .
dockerfile: Dockerfile
restart: on-failure
ports:
- "8100:8100"
db:
container_name: postgres
restart: on-failure
image: postgres:10-alpine
ports:
- "5555:5432"
environment:
POSTGRES_USER: myuser
POSTGRES_PASSWORD: 12345678
POSTGRES_DB: dev
当我尝试docker-compose up -d
时,它会创建postgres
,然后创建该myapp
服务
但似乎我的Postgresql尚未运行,完成安装并运行myapp
后,
它说:
my database server not running yet
如何使myapp
运行,直到该db
服务知道我的db
正在运行?
答案 0 :(得分:0)
depends_on
的{{3}}说:
depends_on
在启动db
之前不等待myapp
处于“就绪”状态-仅在启动之前。
因此,在运行应用程序之前,您必须自己检查数据库是否已准备就绪。
Docker有一个Grafana,解释了如何编写包装器脚本来做到这一点:
#!/bin/sh
# wait-for-postgres.sh
set -e
host="$1"
shift
cmd="$@"
until PGPASSWORD=$POSTGRES_PASSWORD psql -h "$host" -U "postgres" -c '\q'; do
>&2 echo "Postgres is unavailable - sleeping"
sleep 1
done
>&2 echo "Postgres is up - executing command"
exec $cmd
然后,您可以在运行docker-compose文件中的应用之前先调用此脚本:
command: ["./wait-for-postgres.sh", "db", "python", "app.py"]
还有documentation,documentation或wait-for-it之类的工具。
但是这些解决方案有一些局限性,Docker表示:
最好的解决方案是在启动时以及由于某种原因而断开连接时都在应用程序代码中执行此检查。
此方法将更具弹性。
这是我在javascript中使用重试策略的方式:
async ensureConnection () {
let retries = 5
const interval = 1000
while (retries) {
try {
await this.utils.raw('SELECT \'ensure connection\';')
break
} catch (err) {
console.error(err)
retries--
console.info(`retries left: ${retries}, interval: ${interval} ms`)
if (retries === 0) {
throw err
}
await new Promise(resolve => setTimeout(resolve, interval))
}
}
}
答案 1 :(得分:0)
请查看:https://docs.docker.com/compose/startup-order/。
Docker-compose不会等待您的数据库,您需要一种从外部检查它的方法(通过脚本或按照Mickael B.的建议重试连接)。上面链接中提出的解决方案之一是wait-for.sh
实用程序脚本-我们在项目中使用了它,并且效果很好。