如何在Coolify中通过自定义初始化脚本正确初始化Docker化PostgreSQL数据库
问题分析与解决方案
核心原因
PostgreSQL官方镜像的/docker-entrypoint-initdb.d/目录下的脚本仅在数据目录首次初始化(为空)时执行一次。如果Coolify部署时复用了之前创建的db_data持久化卷(哪怕之前部署失败,卷内已有初始化残留数据),初始化脚本就会被跳过,导致数据库和用户未创建。
修复方案
方案1:让初始化脚本每次启动都执行(兼容已有数据卷)
修改脚本逻辑,使其不再依赖镜像的首次初始化机制,而是每次容器启动时都检查并补全数据库和用户:
- 修改
init.sh脚本:
#!/bin/bash set -e # 替换SQL文件中的环境变量 envsubst < /docker-entrypoint.d/init.sql > /docker-entrypoint.d/init-user-db.sql # 等待PostgreSQL服务完全启动 until pg_isready -U "$POSTGRES_USER" -h localhost; do echo "等待PostgreSQL服务启动..." sleep 2 done # 执行初始化SQL psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" -f /docker-entrypoint.d/init-user-db.sql
- 修改PostgreSQL的Dockerfile:
把脚本放到/docker-entrypoint.d/目录(该目录下的脚本会在每次容器启动时执行,而非仅首次):
FROM postgres:15 COPY db-init/init.sh /docker-entrypoint.d/init.sh COPY db-init/init.sql /docker-entrypoint.d/init.sql RUN chmod +x /docker-entrypoint.d/init.sh
方案2:修复原有初始化脚本的身份问题
原有脚本执行psql时使用了$POSTGRES_USER,但首次启动时该用户尚未创建,会导致权限错误。应改用默认的postgres超级用户执行初始化:
修改init.sh:
#!/bin/bash set -e envsubst < /docker-entrypoint-initdb.d/init.sql > /docker-entrypoint-initdb.d/init-user-db.sql # 用默认postgres超级用户执行初始化(此时自定义用户还不存在) psql -v ON_ERROR_STOP=1 --username "postgres" -f /docker-entrypoint-initdb.d/init-user-db.sql
方案3:强制重置Coolify的持久化卷
如果确认是旧数据卷导致脚本未执行,可在Coolify控制台中找到PostgreSQL服务的持久化存储配置,删除已有的db_data卷,重新触发部署,让初始化脚本重新执行。
额外优化建议
- 环境变量检查:确保Coolify部署环境中,
POSTGRES_USER、POSTGRES_PASSWORD、POSTGRES_DB等变量已正确配置并传递给容器。 - 生产环境卷配置:删除NestJS服务中的
- .:/app卷挂载,避免本地代码覆盖容器内的构建产物,导致版本不一致:
nest: build: . container_name: transfer_nest restart: always depends_on: - postgres - redis env_file: - .env ports: - '3000:3000' volumes: - /app/node_modules networks: - app_network
内容的提问来源于stack exchange,提问作者Bendito
相关产品推荐
相关产品推荐

