Что происходит за кулисами, когда переменные `-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 не знает об этом.

Другие вопросы по тегам