302

我希望能够在 docker-compose.yml 中使用环境变量,并在docker-compose up. 这就是例子。

我今天使用基本的 docker run 命令执行此操作,该命令包含在我自己的脚本中。有没有办法用 compose 来实现它,而不需要任何这样的 bash 包装器?

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

16 回答 16

301

码头工人解决方案:

看起来 docker-compose 1.5+ 启用了变量替换:https ://github.com/docker/compose/releases

最新的 Docker Compose 允许您从 compose 文件中访问环境变量。因此,您可以获取环境变量,然后像这样运行 Compose:

set -a
source .my-env
docker-compose up -d

然后您可以使用 ${VARIABLE} 引用 docker-compose.yml 中的变量,如下所示:

db:
  image: "postgres:${POSTGRES_VERSION}"

以下是来自文档的更多信息,请点击此处:https ://docs.docker.com/compose/compose-file/#variable-substitution

当您使用此配置运行 docker-compose up 时,Compose 会在 shell 中查找 POSTGRES_VERSION 环境变量并将其值代入。对于此示例,Compose 在运行配置之前将图像解析为 postgres:9.3。

如果未设置环境变量,Compose 将替换为空字符串。在上面的示例中,如果未设置 POSTGRES_VERSION,则 image 选项的值为 postgres:。

支持 $VARIABLE 和 ${VARIABLE} 语法。不支持扩展的 shell 样式功能,例如 ${VARIABLE-default} 和 ${VARIABLE/foo/bar}。

如果您需要在配置值中放置文字美元符号,请使用双美元符号 ($$)。

我相信这个功能是在这个拉取请求中添加的:https ://github.com/docker/compose/pull/1765

BASH 解决方案:

我注意到人们对 Docker 的环境变量支持有问题。与其在 Docker 中处理环境变量,不如回到基础,比如 bash!这是使用 bash 脚本和.env文件的更灵活的方法。

.env 文件示例:

EXAMPLE_URL=http://example.com
# Note that the variable below is commented out and will not be used:
# EXAMPLE_URL=http://example2.com 
SECRET_KEY=ABDFWEDFSADFWWEFSFSDFM

# 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

只需使用通常的 bash 语法在 compose 文件中引用您的 env 变量(即从文件${SECRET_KEY}中插入)。SECRET_KEY.env

请注意,COMPOSE_CONFIG在我的文件中定义.env并在我的 bash 脚本中使用,但您可以轻松地{$COMPOSE_CONFIG}my-compose-file.ymlbash 脚本中的替换。

另请注意,我通过使用“myproject”前缀命名所有容器来标记此部署。您可以使用任何您想要的名称,但它有助于识别您的容器,以便您以后可以轻松地引用它们。假设您的容器应该是无状态的,该脚本将根据您的 .env 文件参数和您的 compose YAML 文件快速删除和重新部署您的容器。

更新 由于这个答案似乎很受欢迎,我写了一篇博客文章,更深入地描述了我的 Docker 部署工作流程:http: //lukeswart.net/2016/03/lets-deploy-part-1/这在您添加时可能会有所帮助部署配置更加复杂,例如 nginx 配置、LetsEncrypt 证书和链接容器。

于 2015-10-17T12:09:03.063 回答
229

似乎 docker-compose 现在对file 中的默认环境变量具有本机支持。

你需要做的就是在一个名为的文件中声明你的变量.env,它们将在 docker-compose.yml 中可用。

例如,对于.env包含内容的文件:

MY_SECRET_KEY=SOME_SECRET
IMAGE_NAME=docker_image

您可以在内部访问变量docker-compose.yml或将它们转发到容器中:

my-service:
  image: ${IMAGE_NAME}
  environment:
    MY_SECRET_KEY: ${MY_SECRET_KEY}
于 2018-05-06T15:11:17.483 回答
115
  1. 创建一个template.yml,这是您docker-compose.yml的环境变量。
  2. 假设您的环境变量在文件“env.sh”中
  3. 将以下代码放入 sh 文件并运行它。

源环境.sh;rm -rf docker-compose.yml;envsubst < "template.yml" > "docker-compose.yml";

docker-compose.yml将使用正确的环境变量值生成一个新文件。

示例 template.yml 文件:

oracledb:
        image: ${ORACLE_DB_IMAGE}
        privileged: true
        cpuset: "0"
        ports:
                - "${ORACLE_DB_PORT}:${ORACLE_DB_PORT}"
        command: /bin/sh -c "chmod 777 /tmp/start; /tmp/start"
        container_name: ${ORACLE_DB_CONTAINER_NAME}

示例 env.sh 文件:

#!/bin/bash 
export ORACLE_DB_IMAGE=<image-name> 
export ORACLE_DB_PORT=<port to be exposed> 
export ORACLE_DB_CONTAINER_NAME=ORACLE_DB_SERVER
于 2015-12-07T09:12:52.513 回答
45

最好的方法是在文件之外指定环境变量docker-compose.yml。您可以使用env_file设置,并在同一行中定义您的环境文件。然后再次执行 docker-compose up 应该使用新的环境变量重新创建容器。

这是我的 docker-compose.yml 的样子:

services:
  web:
    env_file: variables.env

注意: docker-compose 期望 env 文件中的每一行都具有VAR=VAL格式。避免在文件export内部使用。.env此外,该.env文件应放置在执行 docker-compose 命令的文件夹中。

于 2017-10-20T16:34:22.000 回答
38

以下适用于 docker-compose 3.x 在容器内设置环境变量

方法 - 1直接方法

web:
  environment:
    - DEBUG=1
      POSTGRES_PASSWORD: 'postgres'
      POSTGRES_USER: 'postgres'

方法 - 2 “.env”文件

在与 docker-compose.yml 相同的位置创建一个 .env 文件

$ cat .env
TAG=v1.5
POSTGRES_PASSWORD: 'postgres'

你的撰写文件会像

$ cat docker-compose.yml
version: '3'
services:
  web:
    image: "webapp:${TAG}"
    postgres_password: "${POSTGRES_PASSWORD}"

资源

于 2019-01-03T13:18:25.793 回答
33

为卷使用环境变量时,您需要:

  1. 在包含文件的同一文件夹中创建.envdocker-compose.yaml 文件

  2. .env文件中声明变量:

    HOSTNAME=your_hostname
    
  3. 更改$hostname${HOSTNAME}atdocker-compose.yaml 文件

    proxy:
      hostname: ${HOSTNAME}
      volumes:
        - /mnt/data/logs/${HOSTNAME}:/logs
        - /mnt/data/${HOSTNAME}:/data
    

当然,您可以在每个构建上动态地执行此操作,例如:

echo "HOSTNAME=your_hostname" > .env && sudo docker-compose up
于 2018-02-26T13:29:33.637 回答
7

从 1.25.4 开始,docker-compose 支持--env-file使您能够指定包含变量的文件的选项。

你的应该是这样的:

hostname=my-host-name

和命令:

docker-compose --env-file /path/to/my-env-file config
于 2020-05-11T12:10:57.943 回答
6

你还不能……。但这是另一种选择,像 docker-composer.yml 生成器一样思考:

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

基本上是一个 shell 脚本,它将替换您的变量。您还可以使用 Grunt 任务在 CI 流程结束时构建您的 docker compose 文件。

于 2015-04-23T17:25:44.753 回答
6
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得到它

于 2019-11-01T02:24:13.827 回答
5

要添加和 env 变量,您可以将一个env_file(我们称之为var.env)定义为:

ENV_A=A
ENV_B=B

并将其添加到 docker compose manifest 服务中。此外,您可以直接使用environment.

例如在docker-compose.yaml

version: '3.8'
services:
  myservice:
    build:
      context: .
      dockerfile: ./docker/Dockerfile.myservice
    image: myself/myservice
    env_file:
     - ./var.env
    environment:
     - VAR_C=C
     - VAR_D=D
    volumes:
     - $HOME/myfolder:/myfolder
    ports:
     - "5000:5000"

请在此处查看更多/更新信息:https ://docs.docker.com/compose/environment-variables/

于 2021-05-18T11:13:02.077 回答
4

我为此创建了一个简单的 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"
于 2015-05-21T08:48:04.683 回答
2

据我所知,这是一项正在进行的工作。他们想这样做,但尚未发布。请参阅1377 ( @Andy 提到的“新” 495 )。

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

于 2015-07-20T12:09:12.793 回答
2

将环境添加到 .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
    
于 2017-09-28T14:14:40.837 回答
2

仅关注环境变量的默认值和强制值问题,并作为@modulito 答案的更新:

docker-compose.yml现在支持在文件中使用默认值并强制执行强制值(来自文档):

支持 $VARIABLE 和 ${VARIABLE} 语法。此外,当使用 2.1 文件格式时,可以使用典型的 shell 语法提供内联默认值:

如果 VARIABLE 在环境中未设置或为空,则 ${VARIABLE:-default} 评估为默认值。只有在环境中未设置 VARIABLE 时,${VARIABLE-default} 才会评估为默认值。

同样,以下语法允许您指定强制变量:

如果 VARIABLE 在环境中未设置或为空,则 ${VARIABLE:?err} 退出并显示包含 err 的错误消息。如果在环境中未设置 VARIABLE,则 ${VARIABLE?err} 退出并显示包含 err 的错误消息。

不支持其他扩展的 shell 样式功能,例如 ${VARIABLE/foo/bar}。

于 2021-05-18T14:42:11.470 回答
0

使用 .env 文件在 docker-compse.yml 中定义动态值。无论是端口还是任何其他值。

示例 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
于 2018-10-06T17:19:59.790 回答
0

我最终在 deploy.sh 脚本中使用“sed”来完成此操作,尽管我的要求略有不同,因为 Terrafom 正在调用 docker-compose:通过 Azure App Service 的 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"
于 2021-05-13T14:35:01.647 回答