如何让Docker等待/docker-entrypoint-initdb.d目录下的SQL脚本执行完成
解决方案
问题本质是Postgres官方镜像的启动逻辑导致的:Postgres会先启动数据库实例、打开5432端口,之后才执行
/docker-entrypoint-initdb.d/下的初始化脚本,而默认的depends_on仅判断数据库容器是否处于运行状态,不会等待内部初始化逻辑完成,因此仅等待端口可用无法满足需求。
方案1:使用Docker Compose健康检查(推荐,无需修改业务启动脚本)
给docker-compose.yml中的数据库服务添加健康检查规则,直接判断初始化是否完成,再将web服务的启动条件绑定到数据库的健康状态:- 数据库服务配置新增健康检查项:
services: db: image: postgres:11.12-alpine # 原有配置(环境变量、卷挂载等)保持不变 healthcheck: # 检查逻辑可自定义:如果dump会创建指定库,直接检查该库是否可连接即可;需要更严格校验可替换为查询dump中必然存在的表 test: ["CMD-SHELL", "psql -U 你的数据库用户名 -d 你的目标数据库名 -c 'SELECT 1' || exit 1"] interval: 3s timeout: 5s retries: 10- 修改web服务的
depends_on配置,指定等待数据库健康:
services: web: # 原有配置保持不变 depends_on: db: condition: service_healthy方案2:修改web服务的等待逻辑,直接校验数据库初始化状态
如果不想使用健康检查,可以将原有的仅等待端口的wait-for-it逻辑,替换为直接校验数据库是否可以正常执行业务查询:- 先在web服务的Dockerfile中安装Postgres客户端工具:
RUN apt-get update && apt-get install -y --no-install-recommends postgresql-client \ && rm -rf /var/lib/apt/lists/*- 替换原启动命令中的等待逻辑:
CMD composer install ; \ until psql -h db -U "$DB_USER" -d "$DB_NAME" -c "SELECT 1" > /dev/null 2>&1; do sleep 3; done ; \ bin/console doctrine:migrations:migrate ; \ apache2-foreground其中
$DB_USER、$DB_NAME替换为实际使用的数据库环境变量即可。
内容的提问来源于stack exchange,提问作者Lilia Martins
相关产品推荐
相关产品推荐

