将所有主机环境变量传递给 docker 容器的最简单方法

Posted

技术标签:

【中文标题】将所有主机环境变量传递给 docker 容器的最简单方法【英文标题】:Simplest way of passing all host environment variables to docker container 【发布时间】:2017-03-06 20:47:16 【问题描述】:

使用带有一堆 -e 标志甚至 .env 的 docker run 似乎很麻烦。

是否有任何简单的方法可以将所有主机环境变量传递给 docker 容器

【问题讨论】:

这可能是个糟糕的主意。用例是什么? 不必创建额外的文件来管理配置,因此需要更新每个人一个新的环境变量 你能再详细点吗?如果你有这么多(动态?)配置,可以看看 consul / consul-template 等...? 对我来说,用例是本地运行。我有一个 make 目标,它执行 docker run foo,它用于本地测试。使用生产 Kubernetes configmap 使 make 目标保持最新是很麻烦的,并且将所有内容转发到容器似乎是一种快速的解决方法。 【参考方案1】:

我同意那些建议您可能实际上并不想做您认为自己想做的事情的评论者的观点。然而:

如果 (a) 您对具有特定前缀的环境变量感兴趣并且 (b) 您的变量不包含任何空格,则类似这样的方法会起作用...在这里,我将公开所有 XDG_*变量到 docker 容器:

$ docker run -it --rm --env-file <(env | grep XDG) alpine sh
/ # env | grep XDG
XDG_SEAT=seat0
XDG_SESSION_TYPE=x11
XDG_SESSION_ID=2
XDG_RUNTIME_DIR=/run/user/21937
XDG_MENU_PREFIX=gnome-
XDG_CURRENT_DESKTOP=GNOME
XDG_SESSION_DESKTOP=gnome
XDG_VTNR=2

如果你真的想要 all 环境变量,你可能需要编写一个较小的包装程序,它会产生正确引用的输出(处理包含空格的变量),并且会排除跨越的东西多行,例如 BASH_FUNC_* 变量。然后,您将使用包装器代替前面示例中的 env | grep ...

【讨论】:

指定一个 env 文件是最佳实践吗? 我不确定如何回答这个问题,因为我真的不知道你的用例。如果您有大量配置容器所需的环境变量,那么环境文件对我来说似乎是个好主意(而不是将它们全部放在命令行上)。或者使用 docker compose 来做类似的事情。但也有可能,如果您正在设计自己的图像,那么可能有更好的方法将任何必要的配置放入容器中,而不是使用环境变量。 感谢您抽出宝贵时间回答问题,即使这种做事方式并不“正确”。这个答案允许我在容器内运行docker-compose,同时保持在我的撰写文件中使用环境变量注入的能力:MY_VAR=derp docker-compose up env 文件的特殊输入重定向是否跨操作系统工作?我假设这是针对 Linux 的。在 Mac 上好像不行。想知道如何在 Windows 上完成。 这里没有发生“特殊输入重定向”。 &lt;(...) 是标准的 Bash 语法;它在(...) 中运行进程列表,并将表达式替换为连接到该进程列表输出的文件名。至少在 bash 3.0 之后(可能更早)的任何版本中都应该支持它。这表明它应该在 MacOS 上运行良好。如果事情没有按预期工作,您可能需要就该主题提出一个新问题。【参考方案2】:

有两种方法可以使用 -e 标志:-e VAR=VALUE 和 -e VAR;如果 VAR 已经导出,那么第二种格式将使用导出的值而不使其公开可读,而且您无需担心将 VALUE 转义为空格、引号等。

所以如果你真的想将所有导出的变量传递给你的容器,试试这个:

docker run ... $(env | cut -f1 -d= | sed 's/^/-e /') ...

【讨论】:

这里的 env 参数替换/注入是否可以跨操作系统工作?我假设这是针对 Linux 的。似乎不适用于 Mac,或者我没有导出的变量用于我的情况。想知道如何在 Windows 上完成。【参考方案3】:

混合一些 user3324033 和 larsks 的答案,这对我来说最适合获取所有导出的环境变量并模仿奇点行为:

docker run [...] --env-file <( env| cut -f1 -d= ) [...]

【讨论】:

env 文件的特殊输入重定向是否跨操作系统工作?我假设这是针对 Linux 的。在 Mac 上好像不行。想知道如何在 Windows 上完成。 这取决于您的 bash 版本。我认为 OSX 有 3.X.X 而 linux 现在是 4.X.X【参考方案4】:

就安全性而言,这可能是最不理想的答案,但如果一切都失败了,我会求助于这样对我有用的东西:

env &gt; env.txt; docker run -it [...] --env-file env.txt [...]; rm env.txt

以上假设您将其作为交互式会话运行。如果您在后台将其作为服务运行,则对 env.txt 的清理处理有所不同。

人们可以在命令链中对文件设置 RW 权限,也许是为了使其更安全。并将; 切换为&amp;&amp; 以更好地依赖执行命令

我自己尝试了其他解决方案,但没有成功(我在 Mac OS 上,如果有效果,则通过 brew 使用 bash 4)。

【讨论】:

【参考方案5】:

我发现@larsks 的回答非常有启发性,但我发现我需要在如何将变量注入到容器中进行更多手术。

如果您使用 Makefiles 来构建和/或运行容器,您可以将 gnu make 的 foreach 关键字与 env -i 结合起来,轻松地将环境变量注入您的容器:

SHELL := /bin/bash

FOO := myfooenv
BAR := mybarenv

VARS := FOO BAR

run:
    docker run --rm -it \
        --env-file <(env -i $(foreach var,$(VARS),$(var)=$($(var)))) \
        bash:latest \
        bash -c ' \
            set -e; \
            env; \
        '

这将给出输出:

$ make run
docker run --rm -it \
        --env-file <(env -i FOO=myfooenv BAR=mybarenv) \
        bash:latest \
        bash -c ' \
            set -e; \
            env; \
        '
HOSTNAME=9d3b6863b8f2
_BASH_VERSION=4.4
_BASH_LATEST_PATCH=23
PWD=/
HOME=/root
FOO=myfooenv
_BASH_GPG_KEY=7C0135FB088AAF6C66C650B9BB5869F064EA74AB
TERM=xterm
SHLVL=1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
BAR=mybarenv
_BASH_PATCH_LEVEL=18
_=/usr/bin/env

【讨论】:

以上是关于将所有主机环境变量传递给 docker 容器的最简单方法的主要内容,如果未能解决你的问题,请参考以下文章

无法将环境变量传递给 docker

在构建时使用 docker-compose 将环境变量传递给 docker 映像

将文件路径传递给dockerfile作为变量_ nodeJS dockerode Docker

AWS Elastic Beanstalk Docker 环境变量

在运行时将环境变量传递给 Vue 应用程序

如何将环境变量传递给前端 Web 应用程序?