Что происходит за кулисами, когда переменные `-e` env передаются в контейнер Docker?
В качестве эксперимента я устанавливаю переменные среды в контейнере 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 делает для настройки среды процесса, чтобы сделать доступными переменные среды, передаваемые через -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:
Containerd: обновление до версии 1.0.3. Moby/moby#36749
Я нахожусь в точке, где я копаюсь в containerd
исходный код, но я надеялся, что кто-то, уже знакомый со средой выполнения контейнера, сможет мне помочь.
1 ответ
Когда какой-либо процесс порождается в Linux (используя fork
/execve
системные вызовы), его среда явно указывается путем передачи массива с переменными в execve
, Когда Docker запускает контейнер (то есть порождает корневой процесс контейнера), он объединяет все переменные, переданные с использованием -e
аргумент и добавляет их в список переменных среды, которые должны быть установлены для основного процесса контейнера.
Однако Докер ничего не знает о /etc/environment
, который принадлежит контейнеру и является внутренним по отношению к его файловой системе, независимо от того, монтируется он снаружи или нет. Этот файл принадлежит системе Linux PAM (которая отвечает за аутентификацию) и используется, когда кто-то входит в систему, чтобы установить общие переменные среды для сеанса аутентификации. Вы можете проверить это, запустив 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 не знает об этом.