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

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

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

当前回答

就像这样简单:

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

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

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

 web:
  env_file:
    - web-variables.env

带样本的文件

其他回答

这是为Docker v20编写的,使用Docker compose v2命令。

I was having a similar roadblock and found that the --env-file parameter ONLY works for docker compose config command. On top of that using the docker compose env_file variable, still forced me to repeat values for the variables, when wanting to reuse them in other places than the Dockerfile such as environment for docker-compose.yml. I just wanted one source of truth, my .env, with the ability to swap them per deployment stage. So here is how I got it to work, basically use docker compose config to generate a base docker-compose.yml file that will pass ARG into Dockerfile's.

。local。这是你的。env,我把我的。env分成了不同的部署。

DEVELOPMENT=1
PLATFORM=arm64

docker-compose.config。yml -这是我的核心docker合成文件。

services:
  server:
    build:
      context: .
      dockerfile: docker/apache2/Dockerfile
      args:
        - PLATFORM=${PLATFORM}
        - DEVELOPMENT=${DEVELOPMENT}
    environment:
      - PLATFORM=${PLATFORM}
      - DEVELOPMENT=${DEVELOPMENT}

现在不幸的是,我需要传递两次变量,一次用于Dockerfile,另一次用于environment。然而,它们仍然来自单一来源。local。env这样至少我不需要重复值。

然后,我使用docker compose config生成一个半成品docker-compose.yml。这让我传入我的同伴override docker-compose.local。Yml表示发生最终部署的地方。

docker compose --env-file=.local.env -f docker-compose.config.yml config > docker-compose.yml

这将允许我的Dockerfile访问.env变量。

FROM php:5.6-apache

# Make sure to declare after FROM
ARG PLATFORM
ARG DEVELOPMENT

# Access args in strings with $PLATFORM, and can wrap i.e ${PLATFORM}
RUN echo "SetEnv PLATFORM $PLATFORM" > /etc/apache2/conf-enabled/environment.conf
RUN echo "SetEnv DEVELOPMENT $DEVELOPMENT" > /etc/apache2/conf-enabled/environment.conf

然后从docker-compose中传递.env变量。yml到Dockerfile,然后传递到我的Apache HTTP服务器,它传递到我的最终目的地,PHP代码。

我的下一步是从部署阶段传入我的docker合成重写。

docker-compose.local。yml -这是我的docker重写。

services:
  server:
    volumes:
      - ./localhost+2.pem:/etc/ssl/certs/localhost+2.pem
      - ./localhost+2-key.pem:/etc/ssl/private/localhost+2-key.pem

最后,运行docker compose命令。

docker compose -f docker-compose.yml -f docker-compose.local.yml up --build

请注意,如果你在你的.env文件中改变了任何东西,你将需要重新运行docker compose config并添加——build for docker compose up。因为构建是缓存的,所以影响很小。

因此,对于我的最后一个命令,我通常运行:

docker compose --env-file=.local.env -f docker-compose.config.yml config > docker-compose.yml; docker compose --env-file=.local.env -f docker-compose.yml -f docker-compose.local.yml up --build 
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

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

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

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

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

这是我的docker-compose。Yml看起来像:

services:
  web:
    env_file: variables.env

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

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