作为实验,我通过两种方式在Docker容器中设置环境变量:使用-e选项,以及使用安装在容器内environment上的/etc/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传递的自定义环境变量可用于容器中所有正在运行的进程,因此,我希望理解为什么/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源代码,但是我希望已经熟悉容器运行时的人可以帮助我。

最佳答案

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

但是,Docker不了解/etc/environment的任何信息,su属于该容器且在其文件系统内部,无论是否从外部安装。该文件由Linux PAM系统(负责身份验证)拥有,并在有人登录以设置身份验证 session 的公共(public)环境变量时使用。您可以通过在容器中运行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

当您运行/etc/environment时,身份验证 session 开始,因此,使用了ojit_code文件。

因此,您不应尝试使用此文件来设置容器主进程的变量。该文件具有不同的用途,而Docker对此一无所知。

关于docker - 将 `-e` env vars传递到docker容器中后,幕后会发生什么?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51247824/

10-16 22:35
查看更多