当 `-e` 环境变量被传递到 docker 容器时,幕后发生了什么?

What happens behind the scenes when `-e` env vars are passed into a docker container?

作为实验,我在我的 Docker 容器中以两种方式设置环境变量:使用 -e 选项,以及使用挂载到 [=16] 的 environment 文件=] 在容器内。该文件只有一行:

FROM_ENV_FILE=true

我的docker run命令:

docker run -de FROM_CMD_LINE=true -v $(pwd)/environment:/etc/environment ubuntu:14.04 sleep infinity

当我 运行 docker exec b20543b507e3 cat /etc/environment 时,我确实看到该文件已正确挂载并包含我的值,但是当我 运行 时,我只看到 FROM_CMD_LINE 已设置printenv,看来我的 /etc/environment 文件被忽略了。

我的问题不仅仅是 为什么 /etc/environment 在我的 ubuntu:14.04 docker 图像中不起作用?。我正在寻找一个答案,解释 Docker 为设置进程环境所做的工作,以使通过 -e 传入的自定义环境变量对容器中的所有 运行ning 进程可用,所以我希望能理解为什么 /etc/environment 在容器中被忽略。

下面粘贴了我正在使用的相关 运行时间详细信息。

docker version

Client:
 Version:      18.03.1-ce
 API version:  1.37
 Go version:   go1.9.5
 Git commit:   9ee9f40
 Built:        Thu Apr 26 07:13:02 2018
 OS/Arch:      darwin/amd64
 Experimental: false
 Orchestrator: swarm

Server:
 Engine:
  Version:      18.03.1-ce
  API version:  1.37 (minimum version 1.12)
  Go version:   go1.9.5
  Git commit:   9ee9f40
  Built:        Thu Apr 26 07:22:38 2018
  OS/Arch:      linux/amd64
  Experimental: true

查看 18.03.1-ce 的 release notes

Containerd: update to 1.0.3 release moby/moby#36749

我正处于挖掘 containerd 源代码的阶段,但我希望已经熟悉容器 运行time 的人可以帮助我。

当在 Linux 中产生任何进程时(使用 fork/execve 系统调用),它的环境是通过将带有变量的数组传递给 execve.当 Docker 启动容器时(即它生成容器的根进程),它聚合所有使用 -e 参数传递的变量并将它们添加到必须设置为的环境变量列表中容器的主进程。

然而,Docker 对 /etc/environment 一无所知,它属于容器并且在其文件系统内部,无论是否从外部挂载。此文件由 Linux PAM 系统(负责身份验证)所有,当有人登录时使用它来设置身份验证会话的公共环境变量。您可以在您的容器中通过 运行ning su 检查它:

$ docker run -v $PWD/environment:/etc/environment -it ubuntu:14.04 bash
root@4902dd72b49b:/# env | grep ENV
root@4902dd72b49b:/# su -
root@4902dd72b49b:/# env | grep ENV
FROM_ENV_FILE=true

当您 运行 su 时,身份验证会话开始,因此,使用 /etc/environment 文件。

因此,您不应尝试使用此文件来设置容器主进程的变量。此文件有不同的用途,Docker 不知道。