.env文件就是一个纯文本文件,每行定义一个变量,格式为KEY=VALUE,例如:
# 数据库配置
DB_HOST=mysql
DB_PORT=3306
DB_PASSWORD=mySecret123
# 应用配置
APP_ENV=production
APP_VERSION=1.2.0
语法规则:
=前后不能有空格(KEY = VALUE是错的)#开头的行是注释这是最容易踩坑的地方。Compose文件中的${}语法和env_file配置项的加载机制完全不同,必须区分清楚:
${}语法的变量查找顺序当你在Compose文件中写${DB_PASSWORD}时,Compose只会从以下两个地方查找(优先级从高到低):
export的变量).env文件
注意:
env_file配置项指定的文件不会被${}语法读取。env_file只是把变量注入到容器内部,不影响Compose文件本身的变量替换。
services:
web:
image: nginx
env_file:
- ./env/production.env # 这些变量只注入到容器内部
environment:
- APP_PORT=${PORT:-80} # 这个 ${PORT} 从 .env 文件或 shell 中取值
同一个变量在多个地方定义时,优先级从高到低为:
Shell环境变量(export)> .env 文件 > 默认值
示例
假设.env文件中写了DB_PORT=3306,但你在终端中执行了:
export DB_PORT=3307
docker compose up -d
那么Compose会取到3307,而不是.env中的3306。
在Compose文件中使用.env变量时,支持以下几种写法:
| 写法 | 含义 | 变量不存在时的行为 |
|---|---|---|
${VAR} | 直接取值 | 替换为空字符串,并输出警告 |
${VAR:-default} | 取值,提供默认值 | 使用default |
${VAR-default} | 取值,提供默认值 | 使用default(仅变量完全未定义时) |
${VAR:?error} | 取值,要求必须存在 | 报错并显示error,Compose拒绝启动 |
${VAR?error} | 取值,要求必须存在 | 报错并显示error,Compose拒绝启动 |
$$ | 转义符号 | 输出字面量$ |
.env文件路径默认情况下,Compose 只读取项目根目录下的 .env 文件。如果你想用其他路径的文件,有两种方式:
docker compose --env-file ./config/prod.env up -d
services:
web:
image: nginx
env_file:
- ./config/prod.env
在.env文件中,引号的使用会影响变量解析:
# 双引号:会解析内部的 ${} 变量
NAME="Hello ${USER}"
# 单引号:原样保留,不解析 ${}
NAME='Hello ${USER}'
# 无引号:普通字符串
NAME=Hello
在Compose文件中同理:
environment:
- MSG1="User is ${USER}" # 双引号,${USER} 会被替换
- MSG2='User is ${USER}' # 单引号,${USER} 保持原样
坑一:变量替换后是空的
ports:
- "${PORT}:80" # 如果 .env 中没有定义 PORT,结果变成 ":80",报错
解决:始终使用默认值语法${PORT:-8080}。
坑二:.env文件中=前后有空格
# 错误
DB_HOST = mysql
# 正确
DB_HOST=mysql
如果写了 DB_HOST = mysql,Compose 会把变量名解析为 DB_HOST (带空格),导致 ${DB_HOST} 取不到值。
坑三:修改 .env 后没生效
修改 .env 文件后,必须重启容器才能生效:
docker compose down
docker compose up -d
仅docker compose restart不会重新读取.env。