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

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

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

当前回答

使用.env文件在docker-compse.yml中定义动态值。不管是port还是其他值。

示例docker-compose:

testcore.web:
       image: xxxxxxxxxxxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com/testcore:latest
       volumes: 
            - c:/logs:c:/logs
       ports:
            - ${TEST_CORE_PORT}:80
       environment:
            - CONSUL_URL=http://${CONSUL_IP}:8500 
            - HOST=${HOST_ADDRESS}:${TEST_CORE_PORT}

在.env文件中,你可以定义这些变量的值:

CONSUL_IP=172.31.28.151
HOST_ADDRESS=172.31.16.221
TEST_CORE_PORT=10002

其他回答

据我所知,这还在进行中。他们想这么做,但还没有发布。参见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和链接容器,这可能会有帮助。

我最终在我的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"

只关注环境变量的默认值和强制值的问题,并更新@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},是不支持的。

将env添加到。env文件中

VERSION=1.0.0

然后将其保存到deploy.sh

INPUTFILE=docker-compose.yml
RESULT_NAME=docker-compose.product.yml
NAME=test

prepare() {
        local inFile=$(pwd)/$INPUTFILE
        local outFile=$(pwd)/$RESULT_NAME
        cp $inFile $outFile
        while read -r line; do
            OLD_IFS="$IFS"
            IFS="="
            pair=($line)
            IFS="$OLD_IFS"
               sed -i -e "s/\${${pair[0]}}/${pair[1]}/g" $outFile
            done <.env
     }
       
deploy() {
        docker stack deploy -c $outFile $NAME
}

        
prepare
deploy