如何在docker compose中使用环境变量

时间:2015-03-31 20:23:12

标签: docker docker-compose

我希望能够在docker-compose.yml中使用env变量,并在docker-compose时传入值。 这是一个例子。今天我正在使用基本的docker run命令执行此操作,该命令包含在我自己的脚本中。 有没有办法用compose实现它,没有任何这样的bash包装器?

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

15 个答案:

答案 0 :(得分:194)

DOCKER解决方案:

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

最新的Docker 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时,Compose会显示   对于shell中的POSTGRES_VERSION环境变量   将其值替换为。对于此示例,Compose会解析图像   postgres:9.3运行配置之前。

     

如果未设置环境变量,请使用。撰写替代   空字符串。在上面的示例中,如果未设置POSTGRES_VERSION,   图像选项的值是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语法(即${SECRET_KEY})在您的撰写文件中引用您的env变量,以从SECRET_KEY文件中插入.env

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

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

<强>更新 由于这个答案看起来很流行,我写了一篇博文,更深入地描述了我的Docker部署工作流程:http://lukeswart.net/2016/03/lets-deploy-part-1/当您为部署配置添加更多复杂性时,这可能会有所帮助,例如nginx配置,LetsEncrypt证书和链接容器

答案 1 :(得分:71)

  1. 创建一个template.yml,这是您的docker-compose.yml环境变量。
  2. 假设您的环境变量位于文件'env.sh'
  3. 将下面的代码放在sh文件中并运行它。
  4.   

    source env.sh;   rm -rf docker-compose.yml;   envsubst&lt; “template.yml”&gt; “搬运工-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
    

答案 2 :(得分:50)

似乎docker-compose现在支持default environment variables in 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}

答案 3 :(得分:8)

最好的方法是在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命令的文件夹中。

答案 4 :(得分:8)

以下内容适用于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}"

source

答案 5 :(得分:5)

你还不能......但这是一个替代方案,想像docker-composer.yml生成器:

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

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

答案 6 :(得分:4)

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

您应该看起来像这样:

hostname=my-host-name

和命令:

docker-compose --env-file /path/to/my-env-file config

答案 7 :(得分:3)

我为此创建了一个简单的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"

答案 8 :(得分:1)

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

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

答案 9 :(得分:0)

将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

答案 10 :(得分:0)

使用.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

答案 11 :(得分:0)

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

答案 12 :(得分:0)

我最终在我的 deploy.sh 脚本中使用了“sed”来实现这一点,尽管我的要求略有不同,因为 Terrafom 正在调用 docker-compose:Passing Variables to Docker Compose via a Terraform script for an Azure App Service

Passing data to ngTemplateOutlet

答案 13 :(得分:0)

要添加和 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/

答案 14 :(得分:0)

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

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

<块引用>

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

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

<块引用>

同样,以下语法允许您指定必需变量:

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

<块引用>

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