在Docker中运行其他服务之前先等待服务数据库运行

时间:2020-01-21 09:32:12

标签: postgresql docker docker-compose

我正在尝试在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正在运行?

2 个答案:

答案 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"]

还有documentationdocumentationwait-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实用程序脚本-我们在项目中使用了它,并且效果很好。

相关问题