ishane.cn

了解Docker Compose中的 .ENV 文件

2026/01/04
4
0

一、基本语法

.env文件就是一个纯文本文件,每行定义一个变量,格式为KEY=VALUE,例如:

# 数据库配置
DB_HOST=mysql
DB_PORT=3306
DB_PASSWORD=mySecret123

# 应用配置
APP_ENV=production
APP_VERSION=1.2.0

语法规则:

  • 每行一个变量,=前后不能有空格(KEY = VALUE是错的)
  • 值不需要加引号,但如果值包含特殊字符或空格,建议加引号:APP_NAME="My App"
  • 单引号和双引号效果不同(下面会讲)
  • #开头的行是注释
  • 空行会被忽略

二、文件加载机制

这是最容易踩坑的地方。Compose文件中的${}语法和env_file配置项的加载机制完全不同,必须区分清楚:

2.1 ${}语法的变量查找顺序

当你在Compose文件中写${DB_PASSWORD}时,Compose只会从以下两个地方查找(优先级从高到低):

  • Shell环境变量(即在终端中export的变量)
  • 项目根目录下的.env文件

    注意:env_file配置项指定的文件不会被${}语法读取。env_file只是把变量注入到容器内部,不影响Compose文件本身的变量替换。

services:
  web:
    image: nginx
    env_file:
      - ./env/production.env   # 这些变量只注入到容器内部
    environment:
      - APP_PORT=${PORT:-80}   # 这个 ${PORT} 从 .env 文件或 shell 中取值

2.2 变量优先级规则

同一个变量在多个地方定义时,优先级从高到低为:

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拒绝启动
$$转义符号输出字面量$

2.2 指定自定义.env文件路径

默认情况下,Compose 只读取项目根目录下的 .env 文件。如果你想用其他路径的文件,有两种方式:

方式一:命令行指定

docker compose --env-file ./config/prod.env up -d

方式二:在 Compose 文件中声明

services:
  web:
    image: nginx
    env_file:
      - ./config/prod.env

2.3 单引号 vs 双引号

.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