基于Docker与PostgreSQL的数据库强制初始化及脚本执行问题
解决PostgreSQL Docker Compose初始化的两个问题
问题1:按月自动重新拉取CSV并重建表导入数据
PostgreSQL官方镜像的docker-entrypoint-initdb.d目录仅在数据卷首次初始化时执行脚本,要实现按月更新,需自定义启动逻辑,每次容器启动时检查是否需要执行全量更新:
- 创建自定义启动脚本
db/startup.sh:
#!/bin/bash # 启动PostgreSQL服务并后台运行 docker-entrypoint.sh postgres & POSTGRES_PID=$! # 等待数据库完全就绪 until pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}; do echo "等待数据库启动..." sleep 2 done # 检查当前月份与上次更新月份是否一致 CURRENT_MONTH=$(date +%Y-%m) LAST_UPDATE_MARK="/var/lib/postgresql/data/.last_update_month" if [ ! -f "$LAST_UPDATE_MARK" ] || [ "$(cat $LAST_UPDATE_MARK)" != "$CURRENT_MONTH" ]; then echo "开始执行月度数据更新..." # 按顺序执行拆分的脚本/命令 psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -f /docker-entrypoint-initdb.d/drop_tables.sql /docker-entrypoint-initdb.d/download_csv.sh psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -f /docker-entrypoint-initdb.d/create_tables.sql /docker-entrypoint-initdb.d/import_csv.sh # 更新月份标记文件 echo "$CURRENT_MONTH" > "$LAST_UPDATE_MARK" else echo "本月已完成数据更新,跳过执行" fi # 等待PostgreSQL主进程结束 wait $POSTGRES_PID
- 修改db/Dockerfile:
FROM postgres:latest # 复制所有拆分的脚本和SQL文件到初始化目录 COPY download_csv.sh create_tables.sql import_csv.sh drop_tables.sql /docker-entrypoint-initdb.d/ # 复制自定义启动脚本 COPY startup.sh /usr/local/bin/ # 赋予所有脚本执行权限 RUN chmod +x /usr/local/bin/startup.sh /docker-entrypoint-initdb.d/*.sh # 设置自定义启动脚本为容器入口点 ENTRYPOINT ["startup.sh"]
问题2:确保拆分的Shell脚本全部执行
默认docker-entrypoint-initdb.d目录的脚本会按文件名排序执行,但如果脚本存在阻塞或进程替换问题,会导致后续脚本终止。采用以下两种方案:
方案1:自定义启动脚本显式调用(推荐)
如问题1中的startup.sh,直接按业务顺序调用所有拆分脚本,完全控制执行流程,避免依赖镜像的默认执行逻辑。
方案2:修复默认初始化目录的脚本执行问题
- 给脚本按执行顺序命名,比如
01_download_csv.sh、02_create_tables.sh、03_import_csv.sh,确保镜像按顺序执行。 - 确保每个Shell脚本开头声明
#!/bin/bash,并赋予执行权限。 - 避免在脚本中使用
exec命令替换当前进程,否则会终止后续脚本的执行。例如:
错误写法:
正确写法:exec psql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -f create_tables.sqlpsql -U ${POSTGRES_USER} -d ${POSTGRES_DB} -f create_tables.sql
内容的提问来源于stack exchange,提问作者davidvera
相关产品推荐
相关产品推荐

