使用插值在 Compose 文件中设置、使用和管理变量
Compose 文件可以使用变量来提供更大的灵活性。如果您想要快速地在镜像标签之间切换以测试多个版本,或者想要调整卷源以适应您的本地环境,则无需每次都编辑 Compose 文件,只需设置在运行时将值插入 Compose 文件的变量即可。
插值还可以用于在运行时将值插入 Compose 文件中,然后用于将变量传递到容器的环境中
以下是一个简单的示例
$ cat .env
TAG=v1.5
$ cat compose.yml
services:
web:
image: "webapp:${TAG}"
当您运行 docker compose up
时,Compose 文件中定义的 web
服务将在 .env
文件中设置的 webapp:v1.5
镜像中进行 插值。您可以使用 config 命令 来验证这一点,该命令会将已解析的应用程序配置打印到终端
$ docker compose config
services:
web:
image: 'webapp:v1.5'
插值语法
插值适用于未加引号和双引号的值。支持带大括号 (${VAR}
) 和不带大括号 ($VAR
) 的表达式。
对于带大括号的表达式,支持以下格式
- 直接替换
${VAR}
->VAR
的值
- 默认值
${VAR:-default}
-> 如果VAR
已设置且不为空,则为VAR
的值,否则为default
${VAR-default}
-> 如果VAR
已设置,则为VAR
的值,否则为default
- 必需值
${VAR:?error}
-> 如果VAR
已设置且不为空,则为VAR
的值,否则退出并显示错误${VAR?error}
-> 如果VAR
已设置,则为VAR
的值,否则退出并显示错误
- 替代值
${VAR:+replacement}
-> 如果VAR
已设置且不为空,则为replacement
,否则为空${VAR+replacement}
-> 如果VAR
已设置,则为replacement
,否则为空
有关详细信息,请参阅 Compose 规范中的 插值。
使用插值设置变量的方法
Docker Compose 可以从多个来源将变量插值到您的 Compose 文件中。
请注意,当多个来源声明了相同的变量时,会应用优先级
- 来自 shell 环境的变量
- 如果未设置
--env-file
,则为本地工作目录 (PWD
) 中的.env
文件设置的变量 - 由
--env-file
设置的文件或项目目录中的.env
文件设置的变量
您可以通过运行 docker compose config --environment
来查看 Compose 用于插值 Compose 模型的变量和值。
.env
文件
Docker Compose 中的 .env
文件是一个文本文件,用于定义在运行 docker compose up
时应提供用于插值的变量。此文件通常包含变量的键值对,它允许您在一个位置集中和管理配置。如果您需要存储多个变量,则 .env
文件非常有用。
.env
文件是设置变量的默认方法。.env
文件应放置在项目目录的根目录中,与您的 compose.yaml
文件并排。有关格式化环境文件的更多信息,请参阅 环境文件语法。
基本示例
$ cat .env
## define COMPOSE_DEBUG based on DEV_MODE, defaults to false
COMPOSE_DEBUG=${DEV_MODE:-false}
$ cat compose.yaml
services:
webapp:
image: my-webapp-image
environment:
- DEBUG=${COMPOSE_DEBUG}
$ DEV_MODE=true docker compose config
services:
webapp:
environment:
DEBUG: "true"
其他信息
如果您在
.env
文件中定义了一个变量,则可以使用environment
属性 在compose.yml
中直接引用它。例如,如果您的.env
文件包含环境变量DEBUG=1
,并且您的compose.yml
文件如下所示services: webapp: image: my-webapp-image environment: - DEBUG=${DEBUG}
Docker Compose 会将
${DEBUG}
替换为.env
文件中的值重要事项
请注意,当在
.env
文件中使用变量时,请注意 环境变量优先级,这些变量作为容器环境中的环境变量。您可以将
.env
文件放置在项目目录根目录以外的位置,然后使用 CLI 中的--env-file
选项,以便 Compose 可以导航到它。如果 使用
--env-file
替换,则.env
文件可以被另一个.env
覆盖。
重要事项
从
.env
文件进行替换是 Docker Compose CLI 的一项功能。在运行
docker stack deploy
时,Swarm 不支持它。
.env
文件语法
以下语法规则适用于环境文件
- 以
#
开头的行将被视为注释并被忽略。 - 空白行将被忽略。
- 未加引号和双引号 (
"
) 的值将应用插值。 - 每行表示一个键值对。值可以可选地用引号引起来。
VAR=VAL
->VAL
VAR="VAL"
->VAL
VAR='VAL'
->VAL
- 未加引号值的内联注释必须以空格开头。
VAR=VAL # comment
->VAL
VAR=VAL# not a comment
->VAL# not a comment
- 带引号值的内联注释必须紧跟在结束引号之后。
VAR="VAL # not a comment"
->VAL # not a comment
VAR="VAL" # comment
->VAL
- 单引号 (
'
) 值将按字面意思使用。VAR='$OTHER'
->$OTHER
VAR='${OTHER}'
->${OTHER}
- 可以使用
\
对引号进行转义。VAR='Let\'s go!'
->Let's go!
VAR="{\"hello\": \"json\"}"
->{"hello": "json"}
- 在双引号值中支持常见的 shell 转义序列,包括
\n
、\r
、\t
和\\
。VAR="some\tvalue"
->some value
VAR='some\tvalue'
->some\tvalue
VAR=some\tvalue
->some\tvalue
使用 --env-file
替换
您可以在 .env
文件中设置多个环境变量的默认值,然后将该文件作为参数传递给 CLI。
这种方法的优点是您可以将文件存储在任何位置并适当地命名它,例如,此文件路径相对于执行 Docker Compose 命令的当前工作目录。通过 --env-file
选项传递文件路径
$ docker compose --env-file ./config/.env.dev up
其他信息
- 如果您想要临时覆盖
compose.yml
文件中已引用的.env
文件,则此方法非常有用。例如,您可能对生产 (.env.prod
) 和测试 (.env.test
) 有不同的.env
文件。在以下示例中,有两个环境文件,.env
和.env.dev
。两者都为TAG
设置了不同的值。如果命令行中未使用$ cat .env TAG=v1.5 $ cat ./config/.env.dev TAG=v1.6 $ cat compose.yml services: web: image: "webapp:${TAG}"
--env-file
,则会默认加载.env
文件传递$ docker compose config services: web: image: 'webapp:v1.5'
--env-file
参数将覆盖默认文件路径当传递无效的文件路径作为$ docker compose --env-file ./config/.env.dev config services: web: image: 'webapp:v1.6'
--env-file
参数时,Compose 会返回错误$ docker compose --env-file ./doesnotexist/.env.dev config ERROR: Couldn't find env file: /home/user/./doesnotexist/.env.dev
- 您可以使用多个
--env-file
选项来指定多个环境文件,Docker Compose 会按顺序读取它们。后面的文件可以覆盖前面的文件中的变量。$ docker compose --env-file .env --env-file .env.override up
- 您可以在启动容器时从命令行覆盖特定的环境变量。
$ docker compose --env-file .env.dev up -e DATABASE_URL=mysql://new_user:new_password@new_db:3306/new_database
本地 .env
文件与.env
文件
.env
文件.env
文件还可以用于声明 预定义的环境变量,这些变量用于控制 Compose 行为和要加载的文件。
在没有显式 --env-file
标志的情况下执行时,Compose 会在您的工作目录 ( PWD) 中搜索 .env
文件,并加载自配置和插值的变量。如果此文件中的值定义了 COMPOSE_FILE
预定义变量,这会导致项目目录设置为另一个文件夹,Compose 会加载第二个 .env
文件(如果存在)。第二个 .env
文件的优先级较低。
此机制允许使用自定义变量集作为覆盖来调用现有 Compose 项目,而无需通过命令行传递环境变量。
$ cat .env
COMPOSE_FILE=../compose.yaml
POSTGRES_VERSION=9.3
$ cat ../compose.yaml
services:
db:
image: "postgres:${POSTGRES_VERSION}"
$ cat ../.env
POSTGRES_VERSION=9.2
$ docker compose config
services:
db:
image: "postgres:9.3"
从 shell 替换
您可以使用主机上的现有环境变量或执行 docker compose
命令的 shell 环境中的环境变量。这使您能够在运行时将值动态注入到 Docker Compose 配置中。例如,假设 shell 包含 POSTGRES_VERSION=9.3
,并且您提供以下配置
db:
image: "postgres:${POSTGRES_VERSION}"
当您使用此配置运行 docker compose up
时,Compose 会在 shell 中查找 POSTGRES_VERSION
环境变量,并将它的值替换进去。对于此示例,Compose 会在运行配置之前将镜像解析为 postgres:9.3
。
如果环境变量未设置,Compose 会用空字符串替换。在前面的示例中,如果未设置 POSTGRES_VERSION
,则 image 选项的值为 postgres:
。
注意
postgres:
不是有效的镜像引用。Docker 期望引用没有标签,例如postgres
,默认为最新镜像,或者带有标签,例如postgres:15
。