作为实验,我通过两种方式在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/