我希望能够在docker-compose中使用env变量。Yml,在docker-compose up时传入的值。这就是例子。
今天我使用的是基本的docker run命令,该命令包含在我自己的脚本中。 有没有一种方法来实现它与撰写,没有任何这样的bash包装?
proxy:
hostname: $hostname
volumes:
- /mnt/data/logs/$hostname:/logs
- /mnt/data/$hostname:/data
我希望能够在docker-compose中使用env变量。Yml,在docker-compose up时传入的值。这就是例子。
今天我使用的是基本的docker run命令,该命令包含在我自己的脚本中。 有没有一种方法来实现它与撰写,没有任何这样的bash包装?
proxy:
hostname: $hostname
volumes:
- /mnt/data/logs/$hostname:/logs
- /mnt/data/$hostname:/data
当前回答
这是为Docker v20编写的,使用Docker compose v2命令。
I was having a similar roadblock and found that the --env-file parameter ONLY works for docker compose config command. On top of that using the docker compose env_file variable, still forced me to repeat values for the variables, when wanting to reuse them in other places than the Dockerfile such as environment for docker-compose.yml. I just wanted one source of truth, my .env, with the ability to swap them per deployment stage. So here is how I got it to work, basically use docker compose config to generate a base docker-compose.yml file that will pass ARG into Dockerfile's.
。local。这是你的。env,我把我的。env分成了不同的部署。
DEVELOPMENT=1
PLATFORM=arm64
docker-compose.config。yml -这是我的核心docker合成文件。
services:
server:
build:
context: .
dockerfile: docker/apache2/Dockerfile
args:
- PLATFORM=${PLATFORM}
- DEVELOPMENT=${DEVELOPMENT}
environment:
- PLATFORM=${PLATFORM}
- DEVELOPMENT=${DEVELOPMENT}
现在不幸的是,我需要传递两次变量,一次用于Dockerfile,另一次用于environment。然而,它们仍然来自单一来源。local。env这样至少我不需要重复值。
然后,我使用docker compose config生成一个半成品docker-compose.yml。这让我传入我的同伴override docker-compose.local。Yml表示发生最终部署的地方。
docker compose --env-file=.local.env -f docker-compose.config.yml config > docker-compose.yml
这将允许我的Dockerfile访问.env变量。
FROM php:5.6-apache
# Make sure to declare after FROM
ARG PLATFORM
ARG DEVELOPMENT
# Access args in strings with $PLATFORM, and can wrap i.e ${PLATFORM}
RUN echo "SetEnv PLATFORM $PLATFORM" > /etc/apache2/conf-enabled/environment.conf
RUN echo "SetEnv DEVELOPMENT $DEVELOPMENT" > /etc/apache2/conf-enabled/environment.conf
然后从docker-compose中传递.env变量。yml到Dockerfile,然后传递到我的Apache HTTP服务器,它传递到我的最终目的地,PHP代码。
我的下一步是从部署阶段传入我的docker合成重写。
docker-compose.local。yml -这是我的docker重写。
services:
server:
volumes:
- ./localhost+2.pem:/etc/ssl/certs/localhost+2.pem
- ./localhost+2-key.pem:/etc/ssl/private/localhost+2-key.pem
最后,运行docker compose命令。
docker compose -f docker-compose.yml -f docker-compose.local.yml up --build
请注意,如果你在你的.env文件中改变了任何东西,你将需要重新运行docker compose config并添加——build for docker compose up。因为构建是缓存的,所以影响很小。
因此,对于我的最后一个命令,我通常运行:
docker compose --env-file=.local.env -f docker-compose.config.yml config > docker-compose.yml; docker compose --env-file=.local.env -f docker-compose.yml -f docker-compose.local.yml up --build
其他回答
只关注环境变量的默认值和强制值的问题,并更新@modulito的答案:
在docker-compose中使用默认值和强制强制值。现在支持Yml文件(来自docs):
同时支持$VARIABLE和${VARIABLE}语法。此外,当使用2.1文件格式时,可以使用典型的shell语法提供内联默认值: 如果环境中的VARIABLE未设置或为空,${VARIABLE:-default}计算为默认值。 ${VARIABLE-default}只有在环境中未设置VARIABLE时才计算为默认值。
类似地,下面的语法允许你指定强制变量: ${变量:?如果环境中的VARIABLE未设置或为空,则err}退出,并显示包含err的错误消息。 ${变量?如果在环境中未设置VARIABLE,则err}退出,并显示包含err的错误消息。
其他扩展的shell样式的特性,如${VARIABLE/foo/bar},是不支持的。
DOCKER解决方案:
Docker-compose 1.5+启用了变量替换:https://github.com/docker/compose/releases
最新的Docker Compose允许你从你的Compose文件中访问环境变量。所以你可以获取环境变量,然后像这样运行Compose:
set -a
source .my-env
docker-compose up -d
例如,假设我们有如下的.my-env文件:
POSTGRES_VERSION=14
(或者在调用docker-compose时通过命令行参数传递,像这样:POSTGRES_VERSION=14 docker-compose up -d)
然后你可以在docker-compose中引用这些变量。yml使用${VARIABLE}语法,如下所示:
db:
image: "postgres:${POSTGRES_VERSION}"
这里有更多来自文档的信息,在这里:https://docs.docker.com/compose/compose-file/#variable-substitution
When you run docker-compose up with this configuration, Compose looks for the POSTGRES_VERSION environment variable in the shell and substitutes its value in. For this example, Compose resolves the image to postgres:9.3 before running the configuration. If an environment variable is not set, Compose substitutes with an empty string. In the example above, if POSTGRES_VERSION is not set, the value for the image option is postgres:. Both $VARIABLE and ${VARIABLE} syntax are supported. Extended shell-style features, such as ${VARIABLE-default} and ${VARIABLE/foo/bar}, are not supported. If you need to put a literal dollar sign in a configuration value, use a double dollar sign ($$).
该特性被添加到此拉请求中。
另一种基于docker的解决方案:通过docker-compose命令隐式地派生一个env vars文件
如果你想避免任何bash包装器,或者必须显式地来源一个env vars文件(如上所示),那么你可以传递一个——env-file标志给docker-compose命令,其中包含env var文件的位置:https://docs.docker.com/compose/env-file/
然后你可以在docker-compose命令中引用它,而不必显式地引用它:
docker-compose --env-file .my-env up -d
如果你不传递——env-file标志,默认的env变量文件将是.env。
使用这种方法需要注意以下注意事项:
运行时环境中呈现的值总是覆盖.env文件中定义的值。类似地,通过命令行参数传递的值也具有优先级。
所以要小心任何可能覆盖——env文件中定义的env变量!
BASH解决方案:
我注意到Docker对环境变量的自动处理可能会引起混乱。我们不需要在Docker中处理环境变量,而是回到基础,比如bash!下面是一个使用bash脚本和.env文件的方法,有一些额外的灵活性来演示env vars的实用程序:
POSTGRES_VERSION=14
# Note that the variable below is commented out and will not be used:
# POSTGRES_VERSION=15
# You can even define the compose file in an env variable like so:
COMPOSE_CONFIG=my-compose-file.yml
# You can define other compose files, and just comment them out
# when not needed:
# COMPOSE_CONFIG=another-compose-file.yml
然后在相同的目录中运行这个bash脚本,它应该正确地部署所有内容:
#!/bin/bash
docker rm -f `docker ps -aq -f name=myproject_*`
set -a
source .env
cat ${COMPOSE_CONFIG} | envsubst | docker-compose -f - -p "myproject" up -d
只要在你的合成文件中引用你的env变量与通常的bash语法(即${POSTGRES_VERSION}插入POSTGRES_VERSION从。env文件)。
虽然此解决方案涉及bash,但有些人可能更喜欢它,因为它具有更好的关注点分离。
注意,COMPOSE_CONFIG是在我的.env文件中定义的,并在我的bash脚本中使用,但您可以轻松地将{$COMPOSE_CONFIG}替换为my-compose文件。Yml在bash脚本中。
还要注意,我通过以“myproject”前缀命名我的所有容器来标记这个部署。您可以使用任何您想要的名称,但它有助于识别您的容器,以便稍后轻松引用它们。假设您的容器是无状态的(它们应该是无状态的),这个脚本将根据您的.env文件参数和撰写YAML文件快速删除和重新部署容器。
由于这个答案似乎很受欢迎,我写了一篇博客文章,更深入地描述了我的Docker部署工作流:https://modulitos.com/blog/lets-deploy-part-1/当你为部署配置添加更复杂的配置时,比如Nginx配置,LetsEncrypt certs和链接容器,这可能会有帮助。
我有一个简单的bash脚本,我为此创建,这只是意味着在使用之前在你的文件上运行它: https://github.com/antonosmond/subber
基本上只要创建你的合成文件使用双花括号表示环境变量,例如:
app:
build: "{{APP_PATH}}"
ports:
- "{{APP_PORT_MAP}}"
双花括号中的任何内容都将被同名的环境变量替换,因此如果我设置了以下环境变量:
APP_PATH=~/my_app/build
APP_PORT_MAP=5000:5000
运行subber docker-compose。Yml生成的文件看起来像这样:
app:
build: "~/my_app/build"
ports:
- "5000:5000"
env SOME_VAR="I am some var" OTHER_VAR="I am other var" docker stack deploy -c docker-compose.yml
使用3.6版本:
version: "3.6"
services:
one:
image: "nginx:alpine"
environment:
foo: "bar"
SOME_VAR:
baz: "${OTHER_VAR}"
labels:
some-label: "$SOME_VAR"
two:
image: "nginx:alpine"
environment:
hello: "world"
world: "${SOME_VAR}"
labels:
some-label: "$OTHER_VAR"
我从这个链接得到的 https://github.com/docker/cli/issues/939
当为卷使用环境变量时,您需要:
在包含docker-compose的文件夹中创建.env文件。yaml文件 在.env文件中声明变量: 主机名= your_hostname 在docker-compose中将$hostname修改为${hostname}。yaml文件 代理: 主机名:${主机名} 卷: - / mnt /数据/ logs / ${主机名}:/日志 - / mnt /数据/ ${主机名}:/数据
当然,你可以在每次构建时动态地这样做,比如:
echo "HOSTNAME=your_hostname" > .env && sudo docker-compose up