我希望能够在docker-compose中使用env变量。Yml,在docker-compose up时传入的值。这就是例子。

今天我使用的是基本的docker run命令,该命令包含在我自己的脚本中。 有没有一种方法来实现它与撰写,没有任何这样的bash包装?

proxy:
  hostname: $hostname
  volumes:
    - /mnt/data/logs/$hostname:/logs
    - /mnt/data/$hostname:/data

当前回答

我最终在我的deploy.sh脚本中使用“sed”来完成这一点,尽管我的要求略有不同,因为Docker - Compose是由Terrafom调用的:通过Azure应用程序服务的Terraform脚本将变量传递给Docker Compose

eval "sed -i 's/MY_VERSION/$VERSION/' ../docker-compose.yaml"

cat ../docker-compose.yaml

terraform init 
terraform apply -auto-approve \
    -var "app_version=$VERSION" \
    -var "client_id=$ARM_CLIENT_ID" \
    -var "client_secret=$ARM_CLIENT_SECRET" \
    -var "tenant_id=$ARM_TENANT_ID" \
    -var "subscription_id=$ARM_SUBSCRIPTION_ID"

eval "sed -i 's/$VERSION/MY_VERSION/' ../docker-compose.yaml"

其他回答

就像这样简单:

使用文档中提到的命令行:

docker-compose --env-file ./config/.env.dev config 

或者使用.env文件,我认为这是最简单的方法:

 web:
  env_file:
    - web-variables.env

带样本的文件

你不能……然而。但这是另一种选择,像码头作曲家一样思考。yml发电机:

https://gist.github.com/Vad1mo/9ab63f28239515d4dafd

基本上是一个替换变量的shell脚本。你也可以使用Grunt任务在CI进程结束时构建docker合成文件。

我有一个简单的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"

据我所知,这还在进行中。他们想这么做,但还没有发布。参见1377 (@Andy提到的“新”495)。

我最终实现了@Thomas提出的“生成。yml作为CI的一部分”方法。

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和链接容器,这可能会有帮助。