Прокидываем данные через окружение

При разработке проекта на сервисной архитектуре встает вопрос пробрасывания различных параметров и конфигураций. На сегодня у меня есть проект со следующей SOA (Service Oriented Architecture) архитектурой. Есть четкое разделение Frontend и Backend. Frontend сервер представляет из себя связку Nginx + Nodejs. Все это, вместе с кодом приложения собирается в Docker контейнер. Frontend серверу нужно сообщать о местонахождении REST API сервиса. Можно конечно зафиксировать значения и вшить их в код, поставив различные условия. Но есть способ лучше — использовать Etcd.

Etcd — это распределенная система хранения конфигураций.

И так, у нас есть package.json следующего содержания:

https://gist.github.com/frontdevops/0230bcde1b8c2001d669ff494baca532

В случае запуска в dev режиме, мы просто пробрасываем переменные окружения через shell:

API_HOST='http://localhost/' npm run dev

В случае если это production версия, которая запускается внутри Docker контейнера, то все эти переменные окружения прописаны в секции betterScript.start-prod.env

better-npm-run — это просто утилита для более удобного описания переменных окружения внутри package.json.

Все отлично, пока у вас не становится больше сред выполнения. К примеру, у вас есть среда разработки, далее есть сервер тестирования, после чего код идет на боевой. Т.е. вам нужно уже иметь 3 варианта URL для обращения к REST API. Так же у вас может быть потребность обращаться с сервера Frontend к Beckend, а не только с клиента. И тут вы, конечно, можете гонять все запросы через публичный домен. Но если говорить о сокращении издержек на сетевое взаимодействие и просто, банально, секурность, то лучший способ — это общаться по IP напрямую из контейнера в контейнер.

Я не буду говорить сейчас про установку Etcd сервера, это тема отдельной статьи. Представим что у вас уже есть этот демон, его настроили админы или вы сами и вам предстоит забрать данные и выставить переменные окружения. Я покажу способ получения данных перед запуском сервера, без использования демонов и вотчеров. Мы не будем ставить никакие npm-etcd так как это уже скорее про внедрение в логику приложения, а не про переменные окружения.

Bash way

https://gist.github.com/frontdevops/20b8465a633d1bad21ac337c5a4ae7e0

Что мы сделали. У нас в контейнер пробрасываются переменные ETCD_HOST и ETCD_PORT. Строки

${ETCD_HOST:-10.0.100.100}
${ETCD_PORT:-80}

означают, что если вдруг этих переменных не существует, то выставить им дефолтное значение (у вас будут свои адреса и порт).

Далее, вы формируете REST запрос к серверу Etcd. Получить URL можно через Etcd browser. Затем, используя curl, читаем данные, без сохранения в файл и сразу же передаем данные в утилиту jq. Эта утилита позволяет парсить JSON прямо в Bash.

jq — утилита для работы с JSON из командной строки. С её помощью можно разбирать, фильтровать, сопоставлять и преобразовывать json-данные.

Как выглядит результат запроса к REST API Etcd:


Чтобы получить доступ к нашему значению, мы прописываем следующий путь в запросе к jq:

jq '.node.nodes[0].value'|tr -d '"'

Ну и затем отрезаем лишние кавычки с помощью команды tr -d. В итоге получаем чистое значение поля. В таком подходе есть не мало минусов, но он самый простой, как мне кажется.

Что касается получения URL для общения внутри сети между серверами, то вы можете добавить следующую переменную окружения:

API_URI="http://$(netstat -nr | grep '^0\.0\.0\.0' | awk '{print $2}'):48884"

Этой строчкой мы вычисляем IP Docker хоста, через который проходят все наши запросы. Но это только для общения во внутренней сети. Порт мы четко фиксируем, так как его вычислять не приходится, он у нас всегда постоянен (как и все порты в наших сервисах).

А как вы прокидываете свои переменные окружения?

Предлагаю подискутировать…