首页 > 解决方案 > Docker 等到服务完全准备好

问题描述

我正在对接我现有的Django应用程序。

我有一个entrypoint.sh脚本,由Dockerfile作为入口点运行

ENTRYPOINT ["/app/scripts/docker/entrypoint.sh"]

它的内容包含当环境变量设置为迁移时运行迁移的脚本

#!/bin/sh
#set -e

# Run the command and exit with the custom message when the comamnd fails to run
safeRunCommand() {
  cmnd="$*"
  echo cmnd="$cmnd"
  eval "$cmnd"
  ret_code=$?
  if [ $ret_code != 0 ]; then
    printf "Error : [code: %d] when executing command: '$cmnd'\n" $ret_code
    exit $ret_code
  else
    echo "Command run successfully: $cmnd"
  fi
}

runDjangoMigrate() {
  echo "Migrating database"
  cmnd="python manage.py migrate --noinput"
  safeRunCommand "$cmnd"
  echo "Done: Migrating database"
}

# Run Django migrate command.
# The command is run only when environment variable `DJANGO_MANAGE_MIGRATE` is set to `on`.
if [ "x$DJANGO_MANAGE_MIGRATE" = 'xon' ] && [ ! "x$DEPLOYMENT_MODE" = 'xproduction' ]; then
  runDjangoMigrate
fi

# Accept other commands
exec "$@"

现在,在docker-compose文件中,我有类似的服务

version: '3.7'

services:
  database:
    image: mysql:5.7
    container_name: 'qcg7_db_mysql'
    restart: always

  web:
    build: .
    command: ["./wait_for_it.sh", "database:3306", "--", "./docker_start.sh"]
    volumes:
      - ./src:/app
    depends_on:
      - database
    environment:
      DJANGO_MANAGE_MIGRATE: 'on'

但是当我使用构建图像时

docker-compose up --build

它无法从入口点脚本运行迁移命令并出现错误

(2002, "Can't connect to MySQL server on 'database' (115)")

这是因为数据库服务器还没有启动。

如何让web服务等到database服务完全启动并准备好接受连接?

标签: dockerdocker-compose

解决方案


不幸的是,在 Django Web 应用程序尝试连接之前,Docker 中没有本地方式来等待数据库服务准备好。Depends_on 将仅确保启动数据库容器后启动 Web 应用程序。

由于此限制,您需要解决容器运行方式的问题。最简单的解决方案是将 entrypoint.sh 修改为休眠 10-30 秒,以便您的数据库有时间在执行任何其他命令之前进行初始化。 这个官方的 MySQL entrypoint.sh展示了如何在数据库准备好之前进行阻塞的示例。


推荐阅读