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

如何在docker compose中使用环境变量,docker,docker-compose,Docker,Docker Compose,我希望能够在docker-compose.yml中使用env变量,并在docker compose up时传递值。这就是一个例子 今天我使用基本的docker运行命令来完成这项工作,它围绕着我自己的脚本。 有没有一种方法可以在没有任何bash包装器的情况下使用compose实现它 代理: 主机名:$hostname 卷数: -/mnt/data/logs/$hostname:/logs -/mnt/data/$hostname:/data 您不能。。。然而但这是另一种选择,就像docker-co

我希望能够在docker-compose.yml中使用env变量,并在
docker compose up
时传递值。这就是一个例子

今天我使用基本的docker运行命令来完成这项工作,它围绕着我自己的脚本。 有没有一种方法可以在没有任何bash包装器的情况下使用compose实现它

代理:
主机名:$hostname
卷数:
-/mnt/data/logs/$hostname:/logs
-/mnt/data/$hostname:/data

您不能。。。然而但这是另一种选择,就像docker-composer.yml生成器一样:


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

我为此创建了一个简单的bash脚本,它只意味着在使用前在您的文件上运行它:

基本上,只需使用双大括号来表示环境变量来创建compose文件,例如:

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"

据我所知,这是一项正在进行的工作。他们想这么做,但还没有发布。参见(由@Andy提到的“新的”)

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

DOCKER解决方案: docker compose 1.5+似乎启用了变量替换:

最新的Docker Compose允许您从Compose文件访问环境变量。因此,您可以为环境变量提供源代码,然后按如下方式运行Compose:

set -a
source .my-env
docker-compose up -d
然后可以使用${VARIABLE}引用docker-compose.yml中的变量,如下所示:

db:
  image: "postgres:${POSTGRES_VERSION}"
以下是文档中的更多信息,请参见:

使用此配置运行docker compose时,compose会显示 对于shell和 将其值替换为。对于本例,Compose解析图像 到postgres:9.3,然后再运行配置

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

$VARIABLE和${VARIABLE}语法都受支持。延伸 shell样式的功能,例如${VARIABLE default}和 不支持${VARIABLE/foo/bar}

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

我相信这项功能是在拉取请求中添加的:

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\u KEY}
.env
文件插入
SECRET\u KEY

注意,
COMPOSE\u CONFIG
是在my
.env
文件中定义的,并在我的bash脚本中使用,但是您可以轻松地用bash脚本中的
my COMPOSE file.yml
替换
{$COMPOSE\u CONFIG}

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

更新 因为这个答案似乎很流行,我写了一篇博文,更深入地描述了我的Docker部署工作流程:当您向部署配置(如nginx配置、LetsEncrypt证书和链接容器)添加更多复杂性时,这可能会有所帮助

  • 创建一个
    template.yml
    ,它是带有环境变量的
    docker compose.yml
  • 假设您的环境变量位于文件“env.sh”中
  • 将下面的代码放在一个sh文件中并运行它
  • 来源env.sh; rm-rf docker-compose.yml; envsubs<“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
    
    #/bin/bash
    导出ORACLE\u DB\u映像=
    导出ORACLE\u DB\u端口=
    导出ORACLE\u DB\u容器\u名称=ORACLE\u DB\u服务器
    
    将环境添加到.env文件 比如

    VERSION=1.0.0
    
    然后将其保存到
    deploy.sh
    INPUTFILE=docker-compose.yml
    结果_NAME=docker-compose.product.yml
    名称=测试
    准备(){
    本地填充=$(pwd)/$INPUTFILE
    本地输出文件=$(pwd)/$RESULT\u NAME
    cp$inFile$outFile
    当读取-r行时;执行
    OLD_IFS=“$IFS”
    IFS=“=”
    pair=($line)
    IFS=“$OLD_IFS”
    sed-i-e“s/\${${${pair[0]}}/${pair[1]}/g”$outFile
    
    完成最好的方法是在
    docker compose.yml
    文件之外指定环境变量。您可以使用
    env_file
    设置,并在同一行中定义环境文件。然后再次执行docker compose应该使用新的环境变量重新创建容器

    下面是我的docker-compose.yml的样子:

    services:
      web:
        env_file: variables.env
    
    注: docker compose要求env文件中的每一行都采用
    VAR=VAL
    格式。避免在
    .env
    文件中使用
    export
    。此外,
    .env
    文件应放在
    services:
      web:
        env_file: variables.env
    
    HOSTNAME=your_hostname
    
    proxy:
      hostname: ${HOSTNAME}
      volumes:
        - /mnt/data/logs/${HOSTNAME}:/logs
        - /mnt/data/${HOSTNAME}:/data
    
    echo "HOSTNAME=your_hostname" > .env && sudo docker-compose up
    
    MY_SECRET_KEY=SOME_SECRET
    IMAGE_NAME=docker_image
    
    my-service:
      image: ${IMAGE_NAME}
      environment:
        MY_SECRET_KEY: ${MY_SECRET_KEY}
    
    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}
    
    CONSUL_IP=172.31.28.151
    HOST_ADDRESS=172.31.16.221
    TEST_CORE_PORT=10002
    
    web:
      environment:
        - DEBUG=1
          POSTGRES_PASSWORD: 'postgres'
          POSTGRES_USER: 'postgres'
    
    $ cat .env
    TAG=v1.5
    POSTGRES_PASSWORD: 'postgres'
    
    $ cat docker-compose.yml
    version: '3'
    services:
      web:
        image: "webapp:${TAG}"
        postgres_password: "${POSTGRES_PASSWORD}"
    
    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"
    
    hostname=my-host-name
    
    docker-compose --env-file /path/to/my-env-file config
    
    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"
    
    ENV_A=A
    ENV_B=B
    
    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"