已配置环境变量但docker compose up仍持续出现警告
问题
我正在学习Docker,用Docker Compose搭建了PostgreSQL服务,数据库能正常访问,但执行docker compose up时一直出现警告。我已经在.env文件中设置了环境变量并在docker-compose.yml里正确引用,而且docker compose config能正常显示变量,可警告还是存在。
.env文件内容
DB_POSTGRES_FULL_URL=postgresql://${DB_POSTGRES_USER}:${DB_POSTGRES_PASSWORD}@${DB_POSTGRES_URL}:5434/${DB_POSTGRES_DB_NAME}?schema=public DB_POSTGRES_URL=****** DB_POSTGRES_USER=****** DB_POSTGRES_PASSWORD=****** DB_POSTGRES_DB_NAME=****** JWT_SECRET_KEY=******
docker-compose.yml内容
version: '3.8' services: dev-db: restart: always image: postgres:15 ports: - 5434:5432 environment: POSTGRES_USER: "${DB_POSTGRES_USER}" POSTGRES_PASSWORD: "${DB_POSTGRES_PASSWORD}" POSTGRES_DB: "${DB_POSTGRES_DB_NAME}" networks: - api volumes: - postgres-data:/var/lib/postgresql/data mem_limit: 1gb cpus: 0.5 command: ["postgres", "-c", "log_statement=all"] networks: api: volumes: postgres-data:
pnpm脚本
{ "db:dev:up": "docker compose --env-file .env up -d dev-db", "db:dev:rm": "docker compose rm dev-db -s -f -v", "db:dev:deploy": "pnpm db:dev:rm && pnpm db:dev:up && timeout 2 && pnpm prisma:dev:deploy" }
执行警告信息
time="2023-12-06T19:54:11+01:00" level=warning msg="The \"DB_POSTGRES_USER\" variable is not set. Defaulting to a blank string." time="2023-12-06T19:54:11+01:00" level=warning msg="The \"DB_POSTGRES_PASSWORD\" variable is not set. Defaulting to a blank string." time="2023-12-06T19:54:11+01:00" level=warning msg="The \"DB_POSTGRES_URL\" variable is not set. Defaulting to a blank string." time="2023-12-06T19:54:11+01:00" level=warning msg="The \"DB_POSTGRES_DB_NAME\" variable is not set. Defaulting to a blank string." time="2023-12-06T19:54:11+01:00" level=warning msg="The \"DB_POSTGRES_USER\" variable is not set. Defaulting to a blank string." time="2023-12-06T19:54:11+01:00" level=warning msg="The \"DB_POSTGRES_PASSWORD\" variable is not set. Defaulting to a blank string." time="2023-12-06T19:54:11+01:00" level=warning msg="The \"DB_POSTGRES_URL\" variable is not set. Defaulting to a blank string." time="2023-12-06T19:54:11+01:00" level=warning msg="The \"DB_POSTGRES_DB_NAME\" variable is not set. Defaulting to a blank string."
补充:当.env只保留PostgreSQL镜像用到的变量时,警告消失。看起来.env里包含未被Docker Compose使用但带变量插值的变量时会触发警告,而这个.env文件还要供主应用使用,请问这个行为的原因是什么?怎么在保留完整.env的同时消除警告?
原因分析
警告的核心原因是Docker Compose会解析.env文件中的变量插值语法:
- .env文件第一行
DB_POSTGRES_FULL_URL使用了${DB_POSTGRES_USER}这类占位符,Docker Compose加载.env时会尝试替换这些占位符。 - .env文件的变量解析是顺序敏感的,当解析第一行时,后面定义的
DB_POSTGRES_USER、DB_POSTGRES_PASSWORD等变量还未被加载,因此Docker Compose会判定这些变量未设置,抛出警告。 - 即使变量在后面定义,Docker Compose也不会回溯解析,所以顺序问题会导致占位符无法被正常替换,触发警告。
解决方法
方法1:调整.env变量顺序
把被引用的变量放在引用它们的变量前面,确保Docker Compose解析DB_POSTGRES_FULL_URL时,所需变量已经被加载:
DB_POSTGRES_URL=****** DB_POSTGRES_USER=****** DB_POSTGRES_PASSWORD=****** DB_POSTGRES_DB_NAME=****** DB_POSTGRES_FULL_URL=postgresql://${DB_POSTGRES_USER}:${DB_POSTGRES_PASSWORD}@${DB_POSTGRES_URL}:5434/${DB_POSTGRES_DB_NAME}?schema=public JWT_SECRET_KEY=******
方法2:用单引号包裹带插值的变量值
如果主应用需要自己解析DB_POSTGRES_FULL_URL中的占位符,可以用单引号把该变量的值包裹起来,让Docker Compose把它当作纯字符串处理,不解析内部的${}:
DB_POSTGRES_FULL_URL='postgresql://${DB_POSTGRES_USER}:${DB_POSTGRES_PASSWORD}@${DB_POSTGRES_URL}:5434/${DB_POSTGRES_DB_NAME}?schema=public' DB_POSTGRES_URL=****** DB_POSTGRES_USER=****** DB_POSTGRES_PASSWORD=****** DB_POSTGRES_DB_NAME=****** JWT_SECRET_KEY=******
方法3:拆分.env文件
为Docker Compose单独创建一个专用的环境文件(比如.env.compose),只放入它需要的变量:
# .env.compose DB_POSTGRES_USER=****** DB_POSTGRES_PASSWORD=****** DB_POSTGRES_DB_NAME=******
然后修改pnpm脚本,指定Docker Compose使用这个专用文件:
{ "db:dev:up": "docker compose --env-file .env.compose up -d dev-db" }
主应用继续使用完整的.env文件,两者互不干扰。
内容的提问来源于stack exchange,提问作者VGontier-cmd
相关产品推荐
相关产品推荐

