You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Docker-Compose部署带.env初始化脚本的PostgreSQL并执行node-pg-migrate

解决PostgreSQL initdb脚本中环境变量占位符替换问题

以下是几种经过验证的可行方案,解决你遇到的${PGDATABASE}这类占位符无法替换的问题:

方案1:通过docker-compose command预替换脚本再启动PostgreSQL

官方PostgreSQL镜像不会自动处理initdb脚本中的环境变量占位符,我们可以在容器启动前先完成替换操作:

# docker-compose.yml
services:
  postgres:
    image: postgres:15
    env_file: .env  # 加载.env中的数据库配置
    volumes:
      - ./initdb.d:/initdb-templates  # 将带占位符的脚本挂载到临时目录
      - postgres-data:/var/lib/postgresql/data  # 持久化数据库数据
    command: >
      sh -c '
        # 创建官方镜像默认的initdb目录(若不存在)
        mkdir -p /docker-entrypoint-initdb.d
        # 复制模板脚本并替换环境变量
        for file in /initdb-templates/*.sql; do
          envsubst < "$file" > "/docker-entrypoint-initdb.d/$(basename "$file")"
        done
        # 执行官方PostgreSQL启动命令
        exec postgres
      '
    ports:
      - "5432:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${PGUSER} -d ${PGDATABASE}"]
      interval: 5s
      timeout: 5s
      retries: 5

  app:
    build: .
    env_file: .env
    depends_on:
      postgres:
        condition: service_healthy  # 等待PostgreSQL完全就绪
    command: >
      sh -c '
        npm run migrate up
        npm start
      '

volumes:
  postgres-data:

方案2:自定义PostgreSQL镜像,在entrypoint中处理替换

如果需要更固化的镜像配置,可以自定义镜像并内置替换逻辑:

# Dockerfile.postgres
FROM postgres:15

# 安装envsubst依赖(官方镜像默认无此工具)
RUN apt-get update && apt-get install -y --no-install-recommends gettext-base && rm -rf /var/lib/apt/lists/*

# 将带占位符的脚本复制到模板目录
COPY ./initdb.d /initdb-templates

# 重写entrypoint,先替换脚本再启动服务
ENTRYPOINT ["/bin/sh", "-c", "\
  mkdir -p /docker-entrypoint-initdb.d && \
  for file in /initdb-templates/*.sql; do \
    envsubst < \"$file\" > \"/docker-entrypoint-initdb.d/$(basename \"$file\")\"; \
  done && \
  exec docker-entrypoint.sh postgres \
"]

然后在docker-compose中使用这个自定义镜像:

services:
  postgres:
    build:
      context: .
      dockerfile: Dockerfile.postgres
    env_file: .env
    volumes:
      - postgres-data:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    # 健康检查和其他配置同方案1

关键注意事项

  • 确保.env文件中的变量名与SQL脚本中的占位符完全匹配(比如PGDATABASE对应${PGDATABASE})
  • 官方PostgreSQL镜像的docker-entrypoint-initdb.d目录只会在容器首次启动(数据卷为空)时执行脚本,后续重启不会重复执行
  • 必须通过env_file或environment字段将环境变量传递到PostgreSQL容器,否则envsubst无法获取到值

内容的提问来源于stack exchange,提问作者Richard

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 02:35:21