Docker Compose配置的POSTGRES_USER环境变量无法在自定义Postgres镜像的初始化脚本中生效的问题
Docker Compose配置的POSTGRES_USER环境变量无法在自定义Postgres镜像的初始化脚本中生效的问题
这个问题的核心原因其实是构建阶段和运行阶段的变量上下文不一样,我来给你拆解清楚:
为什么$POSTGRES_USER是空的,而$MYDB能正常取值?
你在Dockerfile里用 heredoc 复制初始化脚本的时候,这个操作是在镜像构建阶段执行的。此时:
MYDB是你定义的ARG,构建镜像时你应该已经通过构建参数(比如docker-compose的build.args)传递了值,所以构建过程中shell会把脚本里的$MYDB替换成实际传入的内容,最终脚本里写的是具体的数据库名。- 而
POSTGRES_USER是你在docker-compose的environment里定义的容器运行时环境变量,构建镜像的时候这个变量根本不存在,所以构建过程中shell解析$POSTGRES_USER就会得到空字符串,最终生成的setup.sh里--username后面就是空的。
解决办法:让变量在运行时再解析
要让POSTGRES_USER在容器运行时(初始化脚本执行时)才被解析,你需要在Dockerfile的heredoc里转义这个变量,避免构建阶段的shell替换它。具体修改如下:
# near top of docker file ARG MYDB ... # later on in file COPY <<EOF /docker-entrypoint-initdb.d/setup.sh #!/bin/bash set -e # 注意这里的$POSTGRES_USER加了反斜杠转义 psql -v ON_ERROR_STOP=1 --username "\$POSTGRES_USER" --dbname "$MYDB" <<-EOSQL ... EOSQL EOF
这样修改后,构建阶段生成的setup.sh里,"\$POSTGRES_USER"会被保留成"$POSTGRES_USER",等到容器启动、Postgres的entrypoint脚本执行这个初始化脚本时,容器运行时的环境变量已经加载,$POSTGRES_USER就能正常取到docker-compose里传入的值了。
额外确认点
Postgres官方镜像的docker-entrypoint.sh脚本会在初始化数据库的时候,自动把POSTGRES_USER、POSTGRES_PASSWORD等环境变量暴露给docker-entrypoint-initdb.d下的脚本执行环境,所以只要你没在构建阶段把变量替换掉,运行时肯定能拿到值。
备注:内容来源于stack exchange,提问作者yen
相关产品推荐
相关产品推荐

