Как мы управляем конфигами для NodeJs приложений?
Решил поделиться, как мы управляем конфигами для NodeJS приложений.
Давайте отталкиваться от того, что у нас есть несколько окружений, к примеру "prod", "staging", "qa".
Как не стоит управлять конфигурацией?
Я часто видел решения, когда в репозитарии есть config-prod.json, config-staging.json, config-qa.json. Рекомендую такого подхода избегать.
Он имеет массу недостатков:
1. Разграничение доступа. Все разработчики, которые имеют доступ к коду не обязательно должны иметь доступ к продакшену. Также такой код нельзя выложить в OpenSource ввиду наличия в репозитории конфигов с параметрами доступа к вашим окружениям.
2. Набор окружений может расширяться: различные дев-боксы, локальное окружение и тд. Это будет тяжело поддерживать. Вам постоянно придется добавлять новые файлы репозиторий и поддерживать много копий конфигов.
3. Создавая билды в виде docker-контейнеров, они будут привязаны к окружению и это нарушает главную идею использования билдов. По правильному было бы протестировать билд на QA, а потом выкатить этот же билд в prod, а не собирать новый. Сборка нового повышает риск, что у нас будет другая конфигурация (например, обновился один из зависимых пакетов).
Подход "Двенадцать факторов" и почему его недостаточно
Если вы используете подход "Двенадцать факторов", то уже все это знаете. По принципу "Двенадцати факторов", конфигурация должна передаваться в переменных окружения - https://12factor.net/ru/config.
Хранить конфигурационные данные в переменных окружения - очень гибко. Вы можете запускать ваше приложение в докере, без докера, в лямбдах. Более того, вы можете переиспользовать одни и те же билды во всех окружениях.
Но одновременно, передавать переменные окружения, при запуске процесса, не слишком удобно. Есть популярная библиотека dotenv, которая позволяет сохранять переменные окружения в файле .env, но вы не должны коммитить этот файл в репозиторий, обычно в репозитории вы держите файл с примером конфигурации (например ".env.sample", который нужно скопировать в .env файл, если вы деплоите без докера). Вы можете использовать dotenv-defaults, библиотека, которая позволяет вам иметь файл .env.defaults со значениями по умолчанию, который вы уже коммитите в репозиторий.
Но в реальности и этого недостаточно. У вас будут достаточно сложные конфиги с вложенностями и и вы часто не хотите определять все значения в переменных окружения, их слишком много и не все из их изменяются в зависимости от окружения (например ссылка на ваш аккаунт вашего продукта в твиттере должна быть в конфиге, но ее нет смысла передавать в переменных окружения). Если вы знакомы с ansible, то знаете, что можно иметь шаблон конфига и подставлять в него переменные в зависимости от окружения и собирать финальный конфиг, но вы помните, что вы не можете паковать этот конфиг в билд. В связи с этим, мы храним шаблон конфига в репозитории и шаблонизируем его переменными окружения. Также, если в конфиге много опций, то имеет смысл автоматически валидировать его корректность после шаблонизации, это сильно облегчит жизнь разработчикам.
Post #34
3.82K