当 `-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 不知道。
作为实验,我在我的 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 不知道。