Разворот Backend-сервисов на локальной машине

Установка Docker + WSL в случае windows

Делается один раз, может быть заменен на альтернативные способы установки Docker

  1. Устанавливаем "Docker Desktop for Windows":https://hub.docker.com/editions/community/docker-ce-desktop-windows

  2. Устанавливаем "WSL2": https://docs.microsoft.com/ru-ru/windows/wsl/install-win10.

  3. Ставим галочку в настройках докера для интеграции с wsl

Известные проблемы связки WSL2 - Docker можно почитать здесь https://greensight.atlassian.net/wiki/spaces/ENSI/pages/368508929

Установка Docker compose v2 plugin в случае linux

Делается один раз. Необходимо для работы команды docker compose, которая быстрее чем docker-compose и используется в наших скриптах.

  1. Устанавливаем плагин https://docs.docker.com/compose/cli-command/#install-on-linux

Структура рабочего пространства проекта и Ensi Local Ctl

Для организации рабочего пространства, запуска сервисов ensi и сервисов необходимых для его работы используется набор скриптов Ensi Local Ctl Сокращенно ELC.

Ниже показана предпочтительная структура директорий рабочего пространства, однако вы можете изменить её, задав определённые переменные.

1 2 3 4 5 6 7 8 9 10 11 12 13 . ├── apps │ ├── service-1 │ ├── service-2 │ └── domain-1 │ └── service-3 ├── other │ ├── ensi-local-ctl │ └── some-repo └── packages ├── package-1 ├── package-2 └── studio.json

Директория apps содержит в себе сервисы, которые могут находиться на любом уровне вложенности. Директория packages - пакеты, которые необходимо подключать в сервисы во время разработки через symlink.

В директории other (название может быть любым) находится сам ELC, от этого места рассчитываются пути на две другие директории.

 

Установка Ensi Local Ctl

Для установки ELC клонируйте репозиторий и создайте симлинк на скрипт. Симлинк позволит вам вызывать скрипт в любом месте, а не только в папке с ELC.

1 2 3 git clone git@gitlab.com:greensight/ensi/devops/ensi-local-ctl.git cd ensi-local-ctl sudo ln -s $PWD/ensi-local-ctl /usr/local/bin/ensi

Кроме того, инструменты разработки, запускаемые в контейнерах, используют следующие папки:

  • ~/.config/composer

  • ~/.cache/composer

  • ~/.npm

Если их нет, создайте, иначе они будут созданы автоматически с неправильными правами.

Кроме того, необходимо создать отдельную сеть для контейнеров:

1 docker network create ensi

где ensi - название сети. Вы можете назвать сеть иначе, но тогда вам придётся изменить переменную ELC_NETWORK. Во время создания сети лучше отключить VPN, иначе операция может завершиться ошибкой.

После клонирования репозитория необходимо также выполнить следующую команду , находясь в папке ELC:

1 ensi global init

В езультате будет создан файл ./global/.elc.env, в котором указаны настройки по-умолчанию. Файл содержит список переменных, значение которых вычислено на основании текущего расположения ELC и с учётом вышеописанной структуры папок. Если ваше рабочее пространство организовано иначе, вам придётся изменить часть из этих переменных.

Запуск глобальных сервисов

Многие сервисы ensi требуют для своей работы наличие базы данных или брокера очередей. Подобные глобальные сервисы управляются через ELC командами с префиксом global.

1 2 3 ensi global start # запустить сразу всё ensi global start proxy # запустить только сервис proxy ensi global start postgres elasticsearch # запустить сервисы postgres и elastic

Полный список операций вы можете получить выполнив команду

1 ensi --help

Глобальные сервисы доступны из сервисов ensi по адресам, совпадающим с их названием. Т.е. для подключения к БД, сервис должен делать соединение на postgres:5432.

Если же вы хотите подключиться БД с хоста, то вам необходимо обращаться на localhost:5432, т.к. порты глобальных сервисов прокидываются на хост.

Отдельно стоит рассмотреть сервис proxy. Это реверс-прокси, который автоматически делает доступными все сервисы в браузере по адресам вида <service>.ensi.127.0.0.1.nip.io. Это относится как к сервисам ensi, так и к дашбордам глобальных сервисов, например, открыть kafka-ui можно перейдя по адресу http://kafka-ui.ensi.127.0.0.1.nip.io при условии, что глобальный сервис kafka-ui запущен.

Модификация настроек запуска сервиса ensi

В большинстве случаев ELC не требует никаких правок внутри конкретного сервиса

Однако, если вам необходимо переопределить некоторые настройки для конкретного сервиса, вы можете создать файл настроек в папке сервиса, и указать там необходимые значения переменных. Делается это командой

1 ensi init

которая создаёт файл .elc.env в корне репозитория сервиса.

Установка и локальный запуск сервисов

Для установки и запуска сервисов необходимо лишь наличие git и docker на машине.

Количество действий, необходимых для запуска, немного отличается в зависимости от типа сервиса

PHP + Laravel: установка

  1. Клонируем сервис внуть директории apps или туда куда указывает переменная ELC_APPS_DIR: Рекомендуется дополнительно создать в apps поддиректории под каждый домен Ensi

    1 git clone git@gitlab.com:greensight/ensi/customers/crm.git
  2. Создаем файлы с переменными окружения и заполняем их необходимыми значениями

    1 2 cp .env.example .env cp .env.example .env.testing
  3. Собираем docker образ если еще не был собран ранее

    1 ensi build
  4. Заходим во внутрь контейнера, дальнейшие команды выполняются внутри него

    1 ensi exec sh
  5. Устанавливаем зависимости

    1 composer i && npm i
  6. Генерируем ключ

    1 php artisan key:generate
  7. Накатываем миграции и тестовые данные

    1 2 ensi build # если докер образ еще не был собран ensi exec php artisan migrate --seed

 

В простейшем случае сервис лежит в папке apps (или в той, на которую указывает переменная ELC_APPS_DIR), причём в папке сервиса располагается сразу корень его репозитория, без дополнительной вложенности. Сам сервис является php backend сервисом.

В этом случае работать с сервисом можно используя команды

1 2 ensi <args> ensi app <name> <args>

Это разные способы выполнить команду для определённого сервиса. Первый способ подходит, когда вы находитесь в папке сервиса. Второй не требует находиться в папке сервиса, однако вы должны явно указать к какому сервису относится текущее действие.

В качестве названия сервиса следует использовать путь до сервиса относительно папки ELC_APPS_DIR. Например, чтобы обратиться к сервису, который лежит по пути ELC_APPS_DIR/catalog/pim необходимо вызывать команду так

1 ensi app catalog/pim <args>

Перед первым запуском сервиса необходимо собрать его docker образ.

1 ensi build

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

После этого сервис можно запустить выполнив

PHP + Laravel: запуск сервиса

1 ensi start

Эта команда запускает два контейнера: app и nginx. Сервис доступен в браузере и для других сервисов по адресу http://<name>.ensi.127.0.0.1.nip.io В случае, когда сервис находится в папке домена, его адрес будет содержать и название домена. Уже известный нам сервис catalog/pim будет иметь адрес http://catalog-pim.ensi.127.0.0.1.nip.io

Можно запустить сервис и не находяст в его папке. Для этого надо модифицировать команду запуска следующим образом

1 ensi app <name> start

В качестве названия сервиса name следует использовать путь до сервиса относительно папки ELC_APPS_DIR. Например, для ервису, который лежит в директории ELC_APPS_DIR/catalog/pim получаем

1 ensi app catalog/pim start

PHP + Laravel: запуск тестов

1 2 ensi exec composer test ensi exec composer test-coverage

 

Nodejs: установка и запуск

По умолчанию ELC запускает php приложения, однако, переопределив несколько переменных на уровне сервиса можно настроить его на запуск nodejs. Для этого необходимо выполнить команду ensi init в папке сервиса, а затем, скопировать в файл .elc.env переменные из global/.elc.env

  • ELC_APP_IMAGE

  • ELC_APP_DOCKERFILE

  • ELC_APP_ENTRYPOINT

  • ELC_NGINX_CONF

изменив название образа и поменяв в путях папку php на папку node, либо указав пути до собственных файлов.

В отличие от php приложений, nodejs требует перезапуска при изменении кода, а даже если и нет (при наличии горячей перезагрузки), всё же возникает необходимость запускать как dev так и prod сборку. Поэтому приложение на nodejs не запускается со стартом контейнера.

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

1 2 3 ensi start ensi exec sh yarn prod

Запуск инструментов разработки

Dev образ приложения отличается от боевого наличием в нём инструментов, необходимых во время разработки. Это могут быть как отдельные программы, вроде composer, так и дополнительные расширения php, например xdebug.

Предпочтительным способом запуска инструментов является вход в контейнер приложения

1 2 3 ensi exec sh composer install php artisan key:generate

Можно, однако, и запускать команды не переводя терминал внутрь контейнера

1 2 ensi exec composer install ensi exec php artisan migrate

Настройка git хуков

Хуки организованы через husky. Чтобы они начали работать, необходимо выполнить npm install в корне сервиса. Во время установки пакета husky перехватывает все хуки гита, и дальше уже на основании своих настроек вызывает тот или иной скрипт из папки .git_hooks.

С сервисами поставляются хуки, способные работать как прямо на хосте, так и в контейнерах ELC. По умолчанию они работают на хосте. Чтобы они работали в контейнерах, необхоимо выше по файловой системе создать файл .external-runtime, который содержит такой текст:

1 EXTERNAL_RUNTIME_COMMAND="ensi exec-script"

Файл должен располагаться выше точки монтирования сервиса в контейнер. Лучше класть его в корень рабочего пространства проекта.

Когда этот файл существует, хуки используют указанную в нём команду для запуска самих себя в контейнере текущего сервиса. Т.к. скриптов в каждом хуке бывает больше одного, первый из них при своём выполнении запускает контейнер app текущего сервиса, а последующие просто делают exec в работающем контейнере.

Разработка composer пакетов

Иногда возникает необходимость подключать в сервис пакет, который ещё не опубликован. Для таких случаев, в рабочем пространстве предусмотрена папка packages (путь до которой можно изменить через переменную ELC_DEV_PACKAGES_DIR). Она монтируется в контейнер по тому же пути, по которому она лежит на хосте, что позволяет создавать симлинки, работающие и в контейнере и на хосте.

Для управления симлинками на пакеты можно использовать studio https://github.com/franzliedke/studio

Вначале его нужно установить

1 2 ensi exec sh composer global require franzl/studio

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

1 studio load ~/home/work/ensi/packages/my-dev-package

Эта команда создаст файл studio.json в корне сервиса. В этом файле описаны пути до пакетов, которые нужно подключать через symlink. Далее, при обновлении пакета композером, вместо скачивания, будет сделан симлинк. Обратите внимание: studio не работает во время require. Если пакет ещё не был подключен в сервис, то вам необходимо сначала руками прописать его в composer.json и затем сделать composer update <package>.

Если вы подключаете пакеты во все сервисы, может быть удобно переместить файл studio.json в папку ELC_DEV_PACKAGES_DIR, и сделать на него абсолютный симлинк в сервисах. Это позволит вам один раз зарегистрировать все необходимые пакеты. composer update, все же, придётся выполнять в каждом сервисе отдельно.