Передача переменных окружения в Docker

Мы на работе немного угорели по микросервисам и всё заворачиваем в docker-контейнеры. Зачем — это тема для отдельного поста, сейчас об этом не будем. Просто поверьте, что оно нам действительно надо.

Что особенно удобно — легко поддерживается идентичность среды у разработчика на маке и винде и на серверах с линуксом. Но есть некоторые вещи, например подключения к БД и другим сервисам, ключи от всяких API и т.п. должны быть разными на разных окружениях.

Первым подходом было создание конфигурационных файлов и их подмена при сборке, всё это выглядело крайне костыльно и доставляло определённые неудобства.

Потом к нам пришли переменные окружения, их можно передавать при запуске контейнера поодиночке или все сразу, используя специальный файл (или несколько файлов).

$ docker run --rm --env DB_HOST=postgres_1.local --env-file=dev-env ubuntu env

В этом примере мы запускаем контейнер с убунтой и передаём в него пачку переменных из файла dev-env, а также явно указываем значение для переменной окружения DB_HOST. В результате в терминал выведется список всех переменных окружения внутри запущенного контейнер, после чего контейнер самоуничтожится (потому что он был запущен с ключом --rm).

Всё очень хорошо и красиво, но когда я начал переводить старый проект на эти новые рельсы, то наткнулся на несколько странное поведение. Проект написан на питоне, поэтому для чтения переменных окружения мы используем библиотеку environs. Она позволяет валидировать значения переменных во время чтения, и для одной такой переменной (пусть это будет тот же DB_HOST) был ограничен набор возможных значений.

Но для удобства разработки переменные брались из .env-файла, монтируемого прямо в контейнер и считывались прямо из него всё-той же библиотекой environs. Всё было прекрасно, пока не пошли деплоить на стейджинг. Тут приложение внезапно стало валлиться с ошибкой, что для DB_HOST передано недопустимое значение.

Проверяю env-файл на сервере — всё в нём правильно, ну ладно иду читать, что на самом деле пришло в контейнер и вижу, что значение переменной передано вместе с кавычками (то есть "postgres_1.local" вместо postgres_1.local). Мы давно привыкли всегда заключать значения переменных окружения в кавычки, потому что bash их игнорирует, но зато это позволяет нормально передать значения из нескольких слов, да и вообще, файлы лучше читаются. Но делать нечего, пришлось вычищать все кавычки из значений переменных, чтобы приложение смогло запуститься.

Но что ещё печальнее, такая внимательность к кавычкам у Докера проявляется только для переменных из env-файла, если переменная передаётся явно, через --env, то значение переменной преспокойно можно заключать в кавычки и в контейнер придут правильные данные.

По случаю этой ошибки была Issue на гитхабе, но что-то её закрыли ничего не починив.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *