Moby: 1.13 中的 docker stack deploy 不像 docker-compose up 那样加载 .env 文件

创建于 2016-12-05  ·  93评论  ·  资料来源: moby/moby

为了测试docker stack deploy --compose-file函数,我加载了一个示例docker-compose.yml

version: '3'
services:
    nginx:
        image: "${DOCKER_USER}/lnmp-nginx:v1.2"
        build:
            context: .
            dockerfile: Dockerfile.nginx
        ports:
            - "80:80"
        networks:
            - frontend
        depends_on:
            - php
    php:
        image: "${DOCKER_USER}/lnmp-php:v1.2"
        build:
            context: .
            dockerfile: Dockerfile.php
        networks:
            - frontend
            - backend
        environment:
            MYSQL_PASSWORD: Passw0rd
        depends_on:
            - mysql
    mysql:
        image: mysql:5.7
        volumes:
            - mysql-data:/var/lib/mysql
        environment:
            TZ: 'Asia/Shanghai'
            MYSQL_ROOT_PASSWORD: Passw0rd
        command: ['mysqld', '--character-set-server=utf8']
        networks:
            - backend
volumes:
    mysql-data:

networks:
    frontend:
    backend:

在服务nginxphpimage部分中,我使用${DOCKER_USER}从环境变量中获取 docker id。 如果我使用docker-compose up ,它将加载.env文件作为默认的envvar文件,其内容是:

DOCKER_USER=twang2218

但是,如果我使用docker stack来部署这个docker-compose.yml ,我会收到以下错误:

$ docker stack deploy --compose-file docker-compose.yml lnmp
Ignoring unsupported options: build

Creating network lnmp_frontend
Creating network lnmp_backend
Creating network lnmp_default
Creating service lnmp_php
Error response from daemon: rpc error: code = 3 desc = ContainerSpec: "/lnmp-php:v1.2" is not a valid repository/tag

如您所见,由于docker stack deploy命令没有加载.env文件, ${DOCKER_USER}被替换为空字符串,导致图像名称无效。

如果加载了.env文件,则最终图像名称应为twang2218/lnmp-php:v1.2

如果我以这种方式运行命令,则环境替换实际上是有效的:

$ DOCKER_USER=twang2218 docker stack deploy --compose-file docker-compose.yml lnmp
Ignoring unsupported options: build

Creating network lnmp_frontend
Creating network lnmp_backend
Creating network lnmp_default
Creating service lnmp_mysql
Creating service lnmp_nginx
Creating service lnmp_php

我们可以通过docker service inspect命令验证它是否正常工作:

$ docker service inspect lnmp_php | grep Image
                    "Image": "twang2218/lnmp-php:v1.2<strong i="13">@sha256</strong>:4f1aef1350aeef3f757f6b6da8f2e1a79ff849f61382320e4b668bfe2b0d1c5a",

图像名称是twang2218/lnmp-php:v1.2 ,这是正确的。

我在 Digitial Ocean droplet 上测试了这个功能,它通过docker-machine安装了 docker 1.13.0-rc2。

这是版本:

$ docker version
Client:
 Version:      1.13.0-rc2
 API version:  1.25
 Go version:   go1.7.3
 Git commit:   1f9b3ef
 Built:        Wed Nov 23 06:32:39 2016
 OS/Arch:      linux/amd64

Server:
 Version:             1.13.0-rc2
 API version:         1.25
 Minimum API version: 1.12
 Go version:          go1.7.3
 Git commit:          1f9b3ef
 Built:               Wed Nov 23 06:32:39 2016
 OS/Arch:             linux/amd64
 Experimental:        false

这是docker info

root<strong i="25">@d1</strong>:~/docker-lnmp# docker info
Containers: 7
 Running: 1
 Paused: 0
 Stopped: 6
Images: 4
Server Version: 1.13.0-rc2
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 43
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins:
 Volume: local
 Network: bridge host macvlan null overlay
Swarm: active
 NodeID: vyf3mgcj3uonrnh5xxquasp38
 Is Manager: true
 ClusterID: jb8rxvd6ptrn3psfkiixxed7r
 Managers: 1
 Nodes: 3
 Orchestration:
  Task History Retention Limit: 5
 Raft:
  Snapshot Interval: 10000
  Number of Old Snapshots to Retain: 0
  Heartbeat Tick: 1
  Election Tick: 3
 Dispatcher:
  Heartbeat Period: 5 seconds
 CA Configuration:
  Expiry Duration: 3 months
 Node Address: 138.197.195.206
 Manager Addresses:
  138.197.195.206:2377
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 03e5862ec0d8d3b3f750e19fca3ee367e13c090e
runc version: 51371867a01c467f08af739783b8beafc154c4d7
init version: 949e6fa
Security Options:
 apparmor
 seccomp
  Profile: default
Kernel Version: 4.4.0-51-generic
Operating System: Ubuntu 16.04.1 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 488.5 MiB
Name: d1
ID: E6UB:PHX6:I2KY:Q35T:PCCI:MFDQ:ZMMN:2X7K:DEOZ:PAP7:4BUC:FP6X
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Labels:
 provider=digitalocean
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false
arestack areswarm kinenhancement

最有用的评论

@whoan我将其用作解决方法:

env $(cat .env | grep ^[A-Z] | xargs) docker stack deploy --compose-file docker-compose.yml [STACK_NAME]

这样,变量就不会卡在终端窗口上

所有93条评论

这是设计使然。 .env支持是 Compose 的一项功能,而不是文件格式的一项功能。

我们可以讨论为将来的版本添加这个,但我不知道这是否真的是最好的选择。

.env支持在 Compose 中非常有用,我们在许多 compose 文件中都使用了它。 它将docker-compose.yml文件的动态部分和静态部分分开。 默认加载.env ,我们可以只为不同的环境提供不同的.env文件,并保持docker-compose.yml和相关脚本静态。

docker-compose.yml中使用env_fileenvironment #$ 来实现相同的环境变量替换结果是不可能的。 .env是最简单的方法。

否则,我们必须在.env文件的每一行中添加 $ export前缀,并在每次加载docker-compose.yml之前手动source .env #$ ,并且有时很容易出现额外的步骤错误。

我刚刚注意到这一点。
我假设/期望它以与 Compose 相同的方式工作,但docker deploy的情况并非如此。

在我的特殊情况下,我期望使用.env文件来存储我将在堆栈中创建的服务中使用的敏感数据(密码、API 密钥等):

version: '3'

volumes:
  data:
    driver: local

networks:
  backend:
    driver: overlay

services:
  rabbitmq:
    image: rabbitmq:${EXCHANGE_RABBITMQ_TAG}
    volumes: [ "data:/var/lib/rabbitmq" ]
    logging: { driver: gelf, options: { gelf-address: "udp://0.0.0.0:12201" } }
    networks: [ "backend" ]
    ports: [ "15672:15672", "5672:5672" ]
    environment:
      RABBITMQ_DEFAULT_USER: ${EXCHANGE_RABBITMQ_USER}
      RABBITMQ_DEFAULT_PASS: ${EXCHANGE_RABBITMQ_PASS}
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
      placement:
        constraints:
          - node.labels.queue-host == true

虽然此 Compose 文件将在 Git 上签入,但.env文件将被忽略。

我已经关注了 *.dab vs compose 文件的全部内容/历史,我觉得你们正试图避免某些事情 - 或提出更好的解决方案 - 但我忘记了整个讨论......

大家好,

Docker 版本:v1.13.0-rc4

我收到错误:忽略不支持的选项:构建,这是否意味着它不会从 Dockerfile 创建构建?

并且 network_mode 也出现相同的错误:忽略不支持的选项:network_mode。

下面是命令:
DOCKER_IMAGE=akhil123 docker stack deploy -c docker-compose.yml foo

提前谢谢了。

@akhildangore请不要评论与问题不直接相关的问题。 docker stack deploy功能,_by design_ 不执行构建。 原因是在运行命令的主机上执行了 _build_,因此该映像仅在 _that_ 节点上可用。 在 Swarm 中部署该映像时,无法在其他节点上启动该服务。 要部署服务,请确保您正在部署的映像已推送到注册表(或用于测试;确保该映像在 swarm 中的每个节点上都可用)

docker deploy上是否有任何支持/反对支持这种行为的案例/讨论?

@vovimayhem尚未对.env文件做出决定,但您可能对https://github.com/docker/docker/pull/30144感兴趣,它为撰写文件添加了对机密的支持

我刚刚发现了那个讨论。 优秀的!

我正在使用 bash 函数作为解决方法。

secrets功能发布之前,您可以根据自己的需要调整它:

dsd() {
    stack=${1:-${PWD##*/}} # by default, the name of the cointaining folder
    compose_file=${2:-docker-compose.yml}

    if [ ! -f $compose_file ]; then
        echo "Misses compose file: $compose_file" >&2
        return 1
    fi

    # execute as a subcommand in order to avoid the variables remain set
    (
        # export variables excluding comments
        [ -f .env ] && export $(sed '/^#/d' .env)

        # Use dsd your_stack your_compose_file to override the defaults
        docker stack deploy --compose-file $compose_file $stack
    )
}

对于那些订阅这个问题的人; 对 docker-compose 文件的 secrets 支持将包含在 1.13.1 版本中,未来应该不会太远

@whoan我将其用作解决方法:

env $(cat .env | grep ^[A-Z] | xargs) docker stack deploy --compose-file docker-compose.yml [STACK_NAME]

这样,变量就不会卡在终端窗口上

能够从.env文件中加载东西总是很好的——除了现在可以绕过的更简单的 Docker 机密用例之外,总是有一些你不想硬编码的 Docker Compose 值在你的回购中。

假设您使用docker stack deploy来部署一个完整的堆栈,并且您有以下要求:

  • 你想对不同的环境使用完全相同的配置——比如登台和生产

    • 您需要为每个环境设置不同的比例值

如果无法使用.env文件进行配置,则需要在每次部署堆栈之前手动更改docker-compose.yml文件,否则服务规模值将恢复为 1。

您可以使用网络、配置服务应侦听的 DNS 等内容来扩展上述内容。

如果我们认为上述用例有意义,我可以起草一个将加载.env文件的 PR,如果该文件与docker-compose.yml存在于同一目录中。

docker stack deploy 的设计与 $ docker-compose命令有点不同。 我认为默认情况下只读取.env是没有意义的。 默认情况下,甚至docker-compse.yml都不会被读取,因为将来默认的部署源可能会是别的东西。

在运行stack deploy之前,您始终可以自己获取.env文件。

在调用docker stack deploy . .env $ 没有帮助,$variables 不会被替换。 只有env .. xargs技巧有帮助。
最好有--env-file=FILE中的docker run选项。

只是 。 .env 在调用 docker stack deploy 之前没有帮助

这应该有助于@C-Pro - 你需要在你的.env文件中有export ...行。 或者,您可以执行export $(cat .env) ,这适用于大多数情况。

大家好,
今天我尝试运行docker stack deploy
我的docker-compose.yml文件:

version: '3'
services:
  simple:
    image: alpine
    environment:
      - FOO: ${BAR}
    env_file: .env

.env文件在同一目录下:

BAR=worked

启动docker stack deploy -c docker-compose.yml test后,我检查了容器并得到了这个:

$ env
BAR=worked
FOO=
...

似乎,容器中提供了.env ,但主机上没有提供。
这意味着,我可以使用.env文件而不是environment部分,但我不能使用带有变量替换的.env文件。
Docker 版本:v17.03

@ddpaimon
环境:
- FOO=${BAR}

看起来 .env 文件仅适用于容器,但不适用于 docker-compose.yml 文件变量替换。

Docker for MAC,Docker 版本 17.03.1-ce,构建 c6d412e

@realcbb
是的。 但是要在容器内使用.env文件变量,您必须在environment部分中删除它们。
例如:
码头工人-compose.yml

...
environment:
  - FOO=${FOO:-empty}
...

.env

FOO=filled

在容器中我得到了这个:

$ env
FOO=empty

但是,如果我从 docker-compose.yml 的environment部分中删除FOO docker-compose.yml ,我会得到:

$ env
FOO=filled

@ddpaimon
在 environment 中指定的环境变量会覆盖在 .env 文件中指定的这些值。

@dnephin :您声明 .env 不是 docker compose 文件格式的一部分。 但是,.env 文件功能记录在 Compose 文件版本 3 参考中: https ://docs.docker.com/compose/compose-file/#variable -substitution。
这给人的印象是 .env 也应该与 docker stack deploy 一起使用。
除此之外,正如其他人已经提到的,将实际环境特定值与堆栈定义 yaml 分开是一个非常需要/需要的功能。 具体来说,我们希望使用它来指定映像版本和复制。

谢谢,我打开了https://github.com/docker/docker.github.io/issues/3654来修复文档

docker stack deploy可以获取生成的文件。 这在 bash 中适用于我的所有变量,并且也可以保密:

docker stack deploy --with-registry-auth --compose-file=<(ENV1=value1 ENV2=value2 docker-compose -f docker-compose.yaml -f docker-compose.override.yaml -f third-sample-compose.yaml config) stack-name

请注意,我添加了内联 ENV 变量作为附加变量或覆盖。 我的撰写文件引用 .env 文件,这很有效。 希望这有帮助👍

docker-compose config的功能将它们联系在一起。

我在寻找.env没有被docker stack deploy读取的解决方案时遇到了这个问题。 看到它不受支持,我有点惊讶(可以澄清文档),但想添加我对.env的支持,比如 compose。

我的用例是我在开发、测试、登台环境中使用docker stack deploy并使用环境变量作为堆栈选项以保持 yml 文件相同。

当前使用此处发布的解决方法之一,但使用.env文件将是首选路线。

只是一个友好的提醒:您可能正在尝试使用 dotenv 文件来存储 API 密钥、密码和其他被认为是“敏感”的东西以放入集群中。 对于这些情况,您应该使用Docker Secrets

对于其他东西,我可以建议每个已部署/可部署的环境有一个撰写文件吗? 在不同环境之间发生变化的大部分内容将是可用的服务器、不同的服务器组织等......因此需要在deploy内容上使用不同的值( placement规则, resources保留等),使得对所有内容都使用单个文件有点过于复杂。

实际上我想要这个功能,当使用 docker stack deploy 时,compose 文件中的变量可以被视为不同主机上的不同值。

“对于其他东西,我是否可以建议每个已部署/可部署环境使用一个 compose 文件?在不同环境之间更改的大部分内容将是可用服务器、不同服务器组织等......因此需要在部署键上使用不同的值内容(放置规则、资源预留等),使得使用单个文件处理所有内容有点过于复杂。”

@vovimayhem很抱歉直言不讳,但这并不像使用单个 compose 文件和使用 env_file 的变量替换一样有意义。 我更喜欢使用 env_file 格式,因为这也使我更容易将堆栈作为可交付成果提供给我的客户并培训他们更新单个 ini 样式的 vars 文件,而不是弄乱 compose 文件(我不这样做'不想要)。

服务配置是一个很好的补充,但它们似乎不适用于部署时间插值(例如 $TAG)。

如果完全支持环境变量,则在用于跨工具解决它们的机制中保持一致。 Stack deploy 似乎选择了不一致,没有从根本上改变环境变量的行为。 秘密和服务配置是环境变量某些用法的更好替代方案,但它们不包含在内。

你似乎没有得到它@vovimayhem。 我不是在谈论将环境传递给容器。 按预期工作。 我的意思是使用在stack deploy期间解析的 env_file ,就像在compose up期间一样。

@ntwrkguru我只是认为这个新功能会帮助你......我很伤心它没有。

这仍然可以作为替代方案;

$ echo 'BAR=worked' > ./.env

$ export $(cat .env) && docker stack deploy testing -c -<<'EOF'
version: '3'
services:
  simple:
    image: nginx:alpine
    environment:
      FOO: ${BAR}
    env_file: .env
EOF

$ docker inspect testing_simple -f '{{json .Spec.TaskTemplate.ContainerSpec.Env}}'
["BAR=worked","FOO=worked"]

@thaJeztah ,确实如此。 我的剧本中有一项任务是获取环境文件,但这缺少更大的意义。 这曾经可以通过compose实现,而现在对于stack是不可能的。 IMO,这是一种回归。 此外,在您的示例中,您仍在将环境变量传递到容器中。 我今天可以用env_files做到这一点; 问题是在stack deploy -c docker-compose.yml操作期间解析env_file

这是特别痛苦的,因为stack不再支持多个撰写文件,否则可以简单地为每个环境使用一个辅助撰写文件。 要做到这一点,需要从撰写文件构建堆栈文件,引入另一个步骤。 所以,无论你怎么看,我们都从一个单步过程变成了一个多步过程,以实现相同的最终结果。

此外,FWIW,在我的实际配置经验中, configs确实低于标准。 我在设想(希望)我可以在源代码中有/application/config.conf 。 更新该文件、提交、推送和 CI 将使用新配置重新部署堆栈。 如果没有一些黑客技术来更改文件名或其他一些机制,这是不可能的。 当然,我们至少可以对文件进行校验和,或者根据文件本身扫描内容更改和更新? 总而言之,我们似乎在倒退。 现在加入对 K8s 的支持,这让我想知道 swarm 是否会在藤蔓上憔悴,直到它失去足够的使用量而被悄悄放弃。

此外,FWIW,在我对实际配置的体验中,配置确实低于标准。 我在设想(希望)我可以在源代码中有 /application/config.conf。 更新该文件、提交、推送和 CI 将使用新配置重新部署堆栈。 如果没有一些黑客技术来更改文件名或其他一些机制,这是不可能的。

@ntwrkguru简单的解决方法不是更改文件名,而是更改配置本身的名称。 我为我的配置名称使用了版本方案,例如config_v1config_v2 、..

因此,请记住在更改配置文件后升级该版本。

services:
  app:
    [...]
    configs:
      - source: config_v2
      - target: /config.yml

configs:
  config_v2:
    file: ./config.yml

我理解没有版本化配置和秘密背后的原因,所以我个人目前对这个(简单的)解决方法没问题。

感谢@djmaze ,但是当每个源代码控制系统都内置了固有的版本跟踪时,这最终是一件荒谬的事情。 另外,感谢您的链接; 我也在那里发表评论。 我不明白为什么 Docker 关心当前版本以外的版本。 我可以看到需要对这些进行版本控制的唯一原因是回滚,但是无论如何也需要在那里跟踪大量的东西,那么还有什么? (不需要编写代码的人说):-)

试试这个:
echo "$(docker-compose -f stack.yml config 2>/dev/null)" | docker stack deploy -c- stack_name

它使用 docker-compose 解析配置文件,替换环境变量,从输出中去除警告,然后通过标准输入将其通过管道传输到 docker stack deploy。
将“-f stack.yml”替换为您的配置文件的名称或省略它以使用默认的 docker-compose.yml。

+1

一年后,我们仍然必须破解它才能工作。 从 17.09.1 开始, docker stack deploy -f compose.yml甚至不会使用已知的 shell 变量来替代。

$ printenv | grep PORTAINER
PORTAINER_VER=1.14.3
portainer:
    image: "portainer/portainer:${PORTAINER_VER}"
$ sudo docker stack deploy -c /tmp/docker/jedi-core.yml --with-registry-auth --prune --resolve-image always jedi-core
Updating service jedi-core_redis_server (id: 0csjyandro713y13ncitk6c0k)
Updating service jedi-core_api-gateway (id: gzcz2eturuxqkjojsc9e6954l)
Updating service jedi-core_auto_results_api (id: tw43c6e0x98q6f0m2g0zttwhf)
Updating service jedi-core_auto_results_api_mongo (id: qpwpypyzd9aigpa71xgxxdzcp)
invalid reference format

标签的任何变量都会产生invalid reference format

一年后,我们仍然必须破解它才能工作。 从 17.09.1 开始, docker stack deploy -f compose.yml 甚至不会使用已知的 shell 变量来替代。

请参阅使用 SUDO 时如何保留环境变量

$ export PORTAINER_VER=1.14.3
$ printenv | grep PORTAINER
PORTAINER_VER=1.14.3

$ sudo printenv | grep PORTAINER

$ sudo -E printenv | grep PORTAINER
PORTAINER_VER=1.14.3


$ cat > docker-compose.yml <<'EOF'
version: '3'
services:
  portainer:
    image: "portainer/portainer:${PORTAINER_VER}"
EOF


$ sudo -E docker stack deploy -c docker-compose.yml foobar
Creating network foobar_default
Creating service foobar_portainer

$ sudo docker service ls
ID                  NAME                MODE                REPLICAS            IMAGE                        PORTS
vt4h0g8yygcg        foobar_portainer    replicated          1/1                 portainer/portainer:1.14.3   

谢谢,但是关于简单地支持文件中的变量替换的任何消息?

[编辑] 这不应该是一个问题(但可能是),因为我正在使用 Ansible 执行become: yes任务,但用户仍然是获取环境变量的同一用户。

我不敢相信这是不可能的。 我们希望保留一个堆栈文件,并能够使用动态变量更改部署选项。

这会起作用,但很丑陋而且很糟糕:

echo "$(docker-compose -f stack.yml config 2>/dev/null)" | docker stack deploy -c- stack_name

我已经搞砸了很多小时,看起来像是在做一些后台脚本工作(我将使用 CI 来做这件事)来从这些不同的部分创建一个 DAB 文件。 如果有一个 docker 工具可以做到这一点,那就太好了... :-) 也许在 docker-compose bundle 中添加一个--env-file version.env docker-compose bundle

在我的用例中,我想使用version.env “清单”来跟踪和控制构成平台的容器/图像的版本。 我的过程如下所示:

  • 更新.env文件
  • 用于填充 shell 变量的源.env文件
  • 运行docker-compose -f stack.yml config > docker-compose.yml
  • 运行docker-compose pull以注册图像摘要
  • 运行docker-compose bundle -o stack.version.dab DAB 文件

在这一点上,理想情况下我可以docker deploy --host manager.swarm.com --bundle-file stack.version.dab --with-registry-auth --resolve-image always stack-name ,但我知道现在不可能。 在这种情况下,我会将 DAB 文件 scp 到管理器并执行docker deploy

这是 Docker 想到的工作流程@thaJeztah 吗? 有没有更好的办法?

[编辑] 这不起作用,因为 DAB 忽略volume:network:deploy:指令。 我已经开始简单地将一个 env 文件采购到 shell,重建一个临时 compose 文件,然后部署它。

如果.env文件在 Docker Compose 中默认读取并且--env-file (简称-e )将添加docker stack deploy以便能够覆盖,我会很高兴环境变量和.env文件中的默认值。

+1
像 docker-compose 一样,首先阅读 .env 会非常方便。
默认情况下,或者只是在 docker stack 命令行中将 env 文件作为参数传递。

这两个已经提到的解决方法(_在下面也找到它们_)似乎有效,尽管与提议的“修复”相比有点难看。

_echo "$(docker-compose -f stack.yml config 2>/dev/null)" | docker stack deploy -c- stack_name_

_env $(cat .env | grep ^[AZ] | xargs) docker stack deploy --compose-file docker-compose.yml [STACK_NAME]_

我要补充一点,安装 docker-compose 只是为了能够处理这些变量实际上也很危险。

如果有人错误地使用 docker-compose up -d 而不是使用 docker stack deploy 来部署堆栈,则很可能会导致应用程序错误和文件损坏。

在部署中进行环境变量插值是持续集成的最佳解决方案。

使用“.env”的一个问题是它与 Ruby on Rails 使用的类似文件名重叠,能够通过参数指定环境文件是优越的。

@ntelisil的建议很好,可以通过以下方式补充或修改:

https://unix.stackexchange.com/questions/294835/replace-environment-variables-in-a-file-with-their-actual-values

您可以使用 envsubst(gnu gettext 的一部分):
envsubst < infile

我用了:

$ envsubst < docker-compose.yml-template > docker-compose.yml

这很好用,但我需要在我的容器中添加 3Mb 左右。

不错的 @rnickle ,但与 Docker 能够像以前一样做到这一点相比,它仍然是“hacky”。 似乎(如果我错了,请 Docker 大佬纠正我)自从宣布 K8s 支持以来,进入 swarm 模式的努力很少,所以我怀疑这些回归中的任何一个是否会得到解决。

这很好用,但我需要在我的容器中添加 3Mb 左右。

如果设置了环境变量, docker slack deploy应该已经插入它们

与 Docker 能够像以前一样做到这一点相比。

Docker 从来没有这个功能。 docker compose 有; docker compose 和 docker stack deploy 共享_文件格式_,但不一定共享软件本身的所有行为。

自从宣布 K8s 支持以来,进入 swarm 模式的努力很少

Compose 文件处理都是在客户端完成的,并且同时用于 k8s 和 swarmkit,因此在这方面没有什么会放慢速度,除了“在任何给定时间我们只能做这么多”

对于那些等待该功能的人; 即将发布的版本将支持docker stack deploy的多个 compose 文件,因此,如果您当前在 docker compose 中使用该功能:即将发布的 docker 版本也将支持此功能

除了语义,感谢您的更新。 当我说 Docker 时,我不一定指守护进程或引擎,而是指构建工具的公司。 关于几乎没有努力的评论的起源实际上源于一个事实,即 swarm-mode 已经出现了一年多,并且仍然远远落后于我们使用 compose 的单节点。

我可以理解它们是不同的,但使用相同的文件格式,但是当用户发现他们必须使用 swarm 交换功能时,这实际上会导致更多的混乱,并可能令人失望。 那以及 DAB 文件仍然被列为实验性的事实。 不幸的是,我们决定在一个大项目中使用 swarm-mode,否则我什至不会在意。 幸运的是,我们不会再犯这样的错误了。

[编辑]

如果设置了环境变量, docker slack deploy 应该已经插入它们

在 CI 环境中这样做是一件非常痛苦的事情。 本质上,我最终安装了 compose,采购了 envvar,清洗了 compose 文件(在提取图像之后),然后吐出一个新的 compose 文件以用于stack deploy 。 (而且我什至不会开始讨论当:latest :latest时有多痛苦,因为这个问题专门与变量插值有关。)

_EDIT:我希望这篇文章不会受到攻击。 我喜欢 Docker Stack 的概念,而且我确实认为整个 Docker 套件都得到了很好的支持。 似乎 Docker(该组织)目前并没有像用户那样看待其产品,这很不幸,并且似乎是我在使用 Compose 和 Stack 时遇到的大多数问题的原因。

Docker 从来没有这个功能。 docker compose 有; docker compose 和 docker stack deploy 共享文件格式,但不一定共享软件本身的所有行为。

我觉得这句话揭示了 Docker 的开发人员和用户看待这些产品的方式之间的根本脱节。 作为用户,无论我使用的是 Docker Engine、Docker Compose 还是 Docker Swarm,它都是 Docker 并且应该尽可能地表现一致。

我对这些产品的用途的理解是:

  • Docker Engine 用于构建和运行单个容器
  • Docker Compose 用于在开发中运行一套容器
  • Docker Stack 用于将容器部署到生产环境

Docker(以及一般的容器)的主要卖点之一是在多个环境中轻松重用同一个应用程序。 因此,Compose 应该添加到 Engine,而 Stack 应该添加到 Compose。 特别是由于它们共享相同的文件格式,Stack 不支持 Compose 的功能会导致开发人员感到困惑并增加 CI 流程的复杂性。

我不会说 compose 是用于开发的,而 stack 是用于产品的。 我认为 compose 用于多容器应用程序或“系统”,并使用 swarm-mode 作为调度程序/协调器进行多主机部署的堆栈。 否则,您的评论是 100% 正确的。 我也很沮丧(如果我的其他评论不明显的话)开发人员和用户之间在产品的使用方式上存在脱节。

哦,哇。 在为一个大项目评估 docker swarm 时,我也加入了困惑和痛苦。
这些秘密都是有趣和游戏,只是并非所有外部 docker 图像都支持从文件中读取秘密。 我不想为它们中的每一个进行修改并放置自定义图像。 可以将它们用于我的项目,是的,但对于外部项目将是不行的。
这样就留下了环境变量。 但是,嘿,它们的行为从 compose 到 stack 不同! 当我注意到它们并没有真正起作用时,想象一下我的惊讶。
没有 env 支持怎么可能有 docker stack?在我看来最好是 --env-file=dev.env ,所以它不会干扰其他 env 文件......但是对此的支持是可怕的。 不幸的是,我必须回到 k8s,因为堆栈从一开始就缺少这个,在生产中可能被证明是一个可怕的选择,谁知道会缺少多少其他东西。

已经两年了,我们还是那样……我不想给人粗鲁的印象,但是来吧! 重用来自 docker-compose 的一些代码很重要!

我刚刚遇到的另一个类似问题是,即使您使用 env_file,行为仍然不完全相同。

我使用 env_file 加载从项目根目录指定的路径,但我的撰写文件位于不同的子目录中。 要使用 docker-compose 启动,我只需使用 --project-directory 。 -f 路径/到/docker-compose.yml

docker stack不允许我指定项目目录,导致我的所有 env_files 都无法加载。

将 env_file 更改为“../../path/to/envrc”不适用于 docker-compose,因为这些文件必须位于项目根目录中

+1

+1

+1这将非常有用。 真的看不到坏处。

docker 还不支持这一点真是太愚蠢了。

+1 @joao-fidalgo 绝对是。

+1

刚刚遇到了与我们尝试 swarm 相同的事情。 我已经阅读了各个线程中的所有消息,感到非常沮丧。 IMO, @ntwrkguru和其他人提出了一些非常好的观点和强有力的论点。 我希望我们可以考虑让他们加入这个功能; 黑客不会削减它。

.env 文件

export MYSQL_USER=user

source .env && docker stack deploy

它也适用于 bash 的docker-compose up

.env 文件

export MYSQL_USER=user

source .env && docker stack deploy

它也适用于docker-compose up

这仅适用于 bash 而不适用于其他 shell。

这让我很困惑。 我的应用程序会使用 docker-compose,但不会使用 docker stack deploy。 至少应该在文档中突出显示免责声明

但 IMO 这是一个错误,正在降低 docker 体验。

我们需要一个关于这个的答案

将近 2 年了,没有人捡起它……不要屏住呼吸@jorgelimafeitosa

我认为 CLI 永远不会添加.env支持。 docker stack deploy命令最初是在考虑分布式应用程序包文件的情况下构建的(因此有--bundle-file选项)。 DAB 文件由 Docker Compose 使用docker-compose bundle命令生成。 .env和其他 Compose 功能将由docker-compose处理,然后传递给docker stack deploy 。 在docker stack deploy中直接支持 Compose 文件总是更多的妥协。

DAB 文件的最初承诺现在存在于 Docker 应用程序中,它也不处理.env

我让我的开发人员使用docker-compose config对 Docker Compose 项目进行预处理,然后再将它们传递给docker stack deploy 。 您可以在一行中执行此操作:

docker stack deploy -c <(docker-compose config) stack-name-here

这样,包括.env处理在内的所有 Docker Compose 功能都被完全应用。

@kinghuang尝试了您的解决方案,但没有奏效。 “docker-compose config”在同一目录中产生正确的输出,但“docker stack deploy -c docker-compose.yaml my_stack”不会替换 .env 中的变量。 我错过了什么? 这是 Docker 版本 18.09.0,构建 4d60db4。

@kinghuang尝试了您的解决方案,但没有奏效。 “docker-compose config”在同一目录中产生正确的输出,但“docker stack deploy -c docker-compose.yaml my_stack”不会替换 .env 中的变量。 我错过了什么? 这是 Docker 版本 18.09.0,构建 4d60db4。

docker stack deploy -c <(docker-compose -f docker-compose-frpc-swarm-traefik.yml config) traefik

@kinghuang

打开 /dev/fd/63:没有这样的文件或目录

警告:某些服务(project1、project2)使用“deploy”键,该键将被忽略。 Compose 不支持“部署”配置 - 使用docker stack deploy部署到 swarm。

@kinghuang
只有root环境不会报错。

在部署/生产环境中支持.envenv_file并不总是有意义的。 对于 Docker Swarm 的任何其他功能,您不需要直接访问文件系统。 因此,该系统的负责设计者/操作者不希望让您能够将环境文件转储到文件系统上。

从理论上讲,Swarm 可以支持自动将机密加载到环境中,但请参阅https://github.com/moby/moby/issues/30866#issuecomment -278924983 了解为什么这在安全方面可能不是一个好主意。

您今天可以做的是使用机密并在容器运行时将它们加载到您的应用程序环境中。 这使您可以控制可以看到秘密环境值的位置。

+1
docker stack deploy 应该真的支持--env-file。
我自己正在努力重新使用相同的 .yml 文件为开发/测试/生产环境部署不同的堆栈,并且我不想在部署堆栈之前处理一些繁琐的环境变量导出/采购。 这非常容易出错(并且每次都记住确切的命令也很痛苦)。
在我的特殊情况下,我想为每个环境设置不同的索引名称(elasticsearch)——但其余的配置保持不变。 这与前面文章中提到的“秘密”无关。
根据上面的评论历史,docker stack deploy 似乎确实需要 --env-file,但遗憾的是 Docker 开发人员似乎没有看到这一点。

在我的 swarm 环境中,我确定了一些解决方法:

  • secrets/configs,我用来加载配置文件和证书。
  • 在观看了 Azure 开发环境的演示后,他们在提交 compose 文件之前运行了一个变量插值脚本,然后我编写了自己的代码,并将其放入我的 GitLab 发布流程中。

只需在 docker-compose.yml 中指定 .env 文件即可:

env_file:
  - .env

请参阅https://stackoverflow.com/questions/44694640/docker-swarm-with-image-versions-externalized-to-env-file

在 Windows 上使用的 powershell 中的一种解决方法,以便在调用 docker 之前解析 .env 文件:

switch -regex -file "./.env" { "^\s ([^#].+?)\s =\s (. )" { $name,$value = $matches[1..2]; 设置项目 "env:$name" $value}}

受到解析 .ini 文件的极大启发: https ://stackoverflow.com/questions/417798/ini-file-parsing-in-powershell

另一种解决方法是: set -a && . .env && set +a && docker stack deploy...

这是荒唐的。 我只是花了一整天的时间试图让它发挥作用。 在docker stack命令不读取 .env 的文档中至少需要一个免责声明。

@cjancsar他们有。 文档说:

重要提示:.env 文件功能仅在您使用 docker-compose up 命令时有效,不适用于 docker stack deploy

不感兴趣。 人们目前在 swarm 模式下会做什么,并且他们想要更新他们新建的 docker 映像,例如从application:v1application:v2 ,相同的服务(没有其他改变)?

这就是我来这个问题的原因。 这就是我感兴趣的原因。

目前在 docker-compose 中,自动化与源代码控制未跟踪文件. env交互以更新映像版本是微不足道的,然后docker-compose up -d

我经常使用提交 sha 作为 docker 镜像版本用于“暂存”部署(在足够的测试周期后用于实际发布的 git 标签),因此实际上不可能将新的镜像版本提交到源代码管理。

是否可以更新 docker 机密(即使它不是真正的机密)作为解决方法? 这是人们做的事情,还是有其他事情要做。

我正在询问此问题的未来访问者,以便他们实际上采用当前的最佳实践,因为他们正在寻找的功能不(还没有?)存在。

嗨,我正忙于研究用于 CI/CD 管道的堆栈部署,能够使用 .env 文件将非常有用,关于是否会在任何阶段引入此选项的任何反馈?

似乎官方建议确实是迁移您的图像代码以支持从机密文本文件中读取这些类型的变量——保留从环境变量中读取这些变量以实现非堆栈/群向后兼容性的能力。

该示例对每个文本文件使用一个密钥,从而避免解析旧的 .env 文件。

https://docs.docker.com/engine/swarm/secrets/#use -secrets-in-compose 的文档中解释:

services:
   db:
     image: mysql:latest
     environment:
       MYSQL_ROOT_PASSWORD_FILE: /run/secrets/db_root_password
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD_FILE: /run/secrets/db_password
     secrets:
       - db_root_password
       - db_password

secrets:
   db_password:
     file: db_password.txt
   db_root_password:
     file: db_root_password.txt

这应该在文档中更清楚。 尽管在每个@lengxuehx变量替换部分中指出 .env 不受支持,但没有提到env_file在堆栈部署中被忽略。

我可以确认@kinghuang提出的解决方案有效,并且没有像有人说的那样排除部署密钥。

docker stack deploy -c <(docker-compose config) stack-name-here

这应该在文档中更清楚。 尽管在每个@lengxuehx变量替换部分中指出 .env 不受支持,但没有提到env_file在堆栈部署中被忽略。

我可以确认 env_file 已被使用并用于部署堆栈命令,就像 docker compose 一样。

docker version
Client: Docker Engine - Community
 Version:           19.03.4
 API version:       1.40
 Go version:        go1.12.10
 Git commit:        9013bf5
 Built:             Thu Oct 17 23:44:48 2019
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.4
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.10
  Git commit:       9013bf5
  Built:            Thu Oct 17 23:50:38 2019
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.10
  GitCommit:        b34a5c8af56e510852c35414db4c1f4fa6172339
 runc:
  Version:          1.0.0-rc8+dev
  GitCommit:        3e425f80a8c931f88e6d94a8c831b9d5aa481657
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683

总结一下,对于像我这样读过这篇文章的人来说:

  • docker stack deploy支持“变量替换”,但您需要以某种方式从.env文件中设置环境变量。 上面已经解释了几个选项。 最巧妙的解决方法之一是使用docker-compose config作为预处理器。
    所以你可以用docker stack deploy -c <(docker-compose config) STACK_NAME创建你的堆栈。
  • 尽管 Docker 引入了configssecrets功能,但它们有自己的用例,但不会做与“变量替换”相同的事情。
  • docker-compose.yml文件中的env_file参数将在创建的容器中设置环境变量,而不是在docker-compose.yml文件本身(因此它不能用作“变量替换”)。

更新:

@thaJeztah 纠正了我。

Docker 不支持使用 docker stack deploy 进行变量替换,并且建议的解决方案都不起作用。

docker stack deploy确实支持变量替换,但不评估.env文件; 在下面的示例中, HELLO_VERSION设置为linux ,并且服务将使用hello-world:linux标记(而不是默认的hello-world:latest

HELLO_VERSION=linux docker stack deploy -c docker-compose.yml mystack
Creating network mystack_default
Creating service mystack_hello

docker service inspect --format '{{.Spec.TaskTemplate.ContainerSpec.Image}}' mystack_hello
hello-world:linux<strong i="14">@sha256</strong>:d073a5775c0b99d653c413161a8ed0e9685061afe697931d30eddf6afeef40f6

话虽如此,您仍然可以在 docker-compose.yml 文件中使用 env_file 参数来使用环境变量

env_file用于不同的目的(相当于docker run --env-file ); env_file选项指定要在创建的容器上设置的 env-vars,但不用于 compose 文件本身(也不用于在部署堆栈之前替换 compose 文件中的变量)。

在 docker-compose 和 docker stack 之间的其他细微差别中,我遇到了同样的问题。
我最终创建了https://github.com/egyel/dcsh脚本/工具来处理这个管道问题。

image
大家好,这帮助我将 env_file 放入了我的 docker-compose 中:

env_file: /path/to/env/file
不是

env_file:
  - /path/to/env/file

我刚刚从另一篇文章中看到了这一点,我只能推测它为什么起作用(与您的推测相同),但我们需要确认为什么它在文档中明确提到 env_file 不起作用。

我的理解是 env 文件不能用于填充占位符
docker-stack.yml 文件,但它们仍然可以提供给容器。
请注意,您正在做的事情不允许您设置图像名称
例如 env 文件。

2020 年 5 月 17 日星期日 06:08 raphyphy [email protected]写道:

[图片:图片]
https://user-images.githubusercontent.com/30310576/82135555-a1e4be00-9836-11ea-9df4-a1b82e014b0e.png
大家好,这帮助我将 env_file 放入了我的 docker-compose 中:

env_file: /path/to/env/file
不是

环境文件:

  • /path/to/env/文件

我刚刚从另一篇文章中看到了这个,我只能推测它为什么有效
(与您的猜测相同)但我们需要确认为什么会这样
作为 docker 工作,在文档中明确提到 env_file 没有
工作。


您收到此消息是因为您发表了评论。
直接回复此邮件,在 GitHub 上查看
https://github.com/moby/moby/issues/29133#issuecomment-629740002 ,或
退订
https://github.com/notifications/unsubscribe-auth/ABHLQMCARDQGJQIBWCQKAYLRR5PMHANCNFSM4CYRHCTA
.

上面提到的docker-compose解决方案:

docker stack deploy -c <(docker-compose config) stack-name-here

(对我来说)缺点是.env文件,尤其是docker-compose.override.yml文件通常是我的开发环境的一部分。 我真的不希望在部署到生产环境时引入这些。

我最终得到了一个单独的docker-compose-production.yml ,我在其中仔细控制了一些东西,即使这涉及到一些重复。

我认为 CLI 永远不会添加.env支持。 docker stack deploy命令最初是在考虑分布式应用程序包文件的情况下构建的(因此有--bundle-file选项)。 DAB 文件由 Docker Compose 使用docker-compose bundle命令生成。 .env和其他 Compose 功能将由docker-compose处理,然后传递给docker stack deploy 。 在docker stack deploy中直接支持 Compose 文件总是更多的妥协。

DAB 文件的最初承诺现在存在于 Docker 应用程序中,它也不处理.env

我让我的开发人员使用docker-compose config对 Docker Compose 项目进行预处理,然后再将它们传递给docker stack deploy 。 您可以在一行中执行此操作:

docker stack deploy -c <(docker-compose config) stack-name-here

这样,包括.env处理在内的所有 Docker Compose 功能都被完全应用。

这就像一个魅力,请记住,如果您的撰写文件没有“docker-compose.yml”名称,您的命令应该包含实际的撰写文件名。

docker stack deploy -c <(docker-compose -f CUSTOM-COMPOSE-FILENAME.yml config) CUSTOM-STACK

当心<(docker-compose -f CUSTOM-COMPOSE-FILENAME.yml config黑客攻击!!! docker-compose configdocker-compose -f myfile.yml config的输出不一定相同! 后者有时会将 env 变量包含在额外的引号中,因此输出会出错!

例子:

environment:
  SERVER_URL: '"xxx"'

代替

environment:
  SERVER_URL: xxx

这个问题是否已经在某个地方跟踪过?

此页面是否有帮助?
0 / 5 - 0 等级