Следующий шаг после разработки веб-приложения — размещение его на сервере. Независимо от сложности проекта или используемой инфраструктуры, общий процесс остается одинаковым: нужно «упаковать» код в CI/CD-конвейер и отправить на сервер. В тексте рассмотрим, как это происходит на примере простого приложения to-do list на React. Подробности под катом!
Используйте навигацию, если не хотите читать текст полностью:
→ Описание проекта
→ Создание проекта в облаке
→ Настройка веб-сервера и ручной деплой
→ Настройка раннера
→ Автодеплой
→ Заключение
Описание проекта
Скриншот приложения.
To-do list — это приложение для управления задачами. Оно помогает пользователю быстро добавлять, удалять и помечать задачи как выполненные. Так как они хранятся в локальном хранилище браузера, нам не нужна внешняя база данных и API для работы. Сосредоточимся на деплое приложения и настройке веб-сервера. В качестве последнего используем Nginx, а для обеспечения доступности из глобальной сети — облачную инфраструктуру.
Создание проекта в облаке
1. Переходим в Панель управления → Облачная платформа. Нажимаем Создать проект.
2. Вводим название для нового проекта и нажимаем Создать проект.
3. В разделе Облачная платформа видим новый проект. Во вкладке Серверы нажимаем Создать сервер.
4. Выбираем произвольное имя (в нашем случае — todo-list), локацию, пул и источник.
В качестве источника выбрали Debian 12, но есть множество других вариантов. Вы можете выбрать подходящий дистрибутив Linux или уже готовый образ с приложениями.
5. Настраиваем конфигурацию. В нашем случае подойдет Standard с локальным SSD-диском на 8 ГБ, 1 vCPU и 1 ГБ ОЗУ. В блоке Сеть выбираем Новый публичный IP-адрес. Так наше приложение будет доступно из интернета.
6. В блоке Доступ добавляем SSH-ключ (публичную часть) для пользователя root.
7. После нажатия на кнопку Добавить SSH-ключ появляется окно ввода. Здесь есть шпаргалка для генерации пары SSH-ключей, а также ссылка на полную версию инструкции. Вводим публичный ключ в формате OpenSSH и имя для него, нажимаем Добавить.
8. Получаем пароль и сохраняем его в безопасное место.
9. Проверяем стоимость выбранной конфигурации и создаем сервер.
Отлично — сервер готов. Видим его в списке созданных.
После получения статуса ACTIVE можно заходить на сервер по выделенному белому IP-адресу:
ssh root@31.129.35.121
В примере мы сосредоточены на публикации нашего приложения и не рассматриваем вопросы первичной настройки и безопасности сервера. О необходимых мерах по защите сервера, настройке, подключении SSH и установку специализированного ПО для блокировки злоумышленников — рассказываем в пошаговой шпаргалке.
Настройка веб-сервера и ручной деплой
1. Обновляем информацию о пакетах:
apt update
2. Устанавливаем пакеты:
- mc — для удобной графической навигации по файловой системе,
- git — для клонирования репозитория с приложением,
- nginx — для организации веб-сервера,
- nodejs и npm — для установки пакетов и сборки веб-приложения на React.
apt install mc git nginx nodejs npm
3. После установки проверяем корректность работы Nginx. Для этого в браузере переходим по IP-адресу сервера 31.129.35.121, который ранее арендовали:
Приветственная страница Nginx. Если вы ее видите, значит сервер работает корректно.
4. Перемещаемся в директорию /var/www/ и клонируем репозиторий с веб-приложением:
git clone <a href="https://gitlab.com/Byurrer/todo-list.git">https://gitlab.com/Byurrer/todo-list.git</a>
5. Переходим в директорию todo-list и устанавливаем пакеты:
npm install
6. Производим сборку проекта:
npm run build
Теперь появилась директория build, в которой лежит вся статика нашего приложения:
7. Готовим конфигурацию сайта в Nginx. Для этого в директории /etc/nginx/sites-available/ создаем файл todo-list и записываем в него код:
server {
listen 80;
server_name 31.129.35.121;
location / {
root /var/www/todo-list/build/;
try_files $uri $uri/ =404;
}
}
Записать код можно с помощью mcedit:
mcedit /etc/nginx/sites-available/todo-list
В этом конфиге приложение будет доступно на 80 порте (http) при обращении к хосту 31.129.35.121.
8. Указываем корень нашего сайта /var/www/todo-list/build/ и в директиве try_files обращаемся к файлам/директориям, переданным в строке запроса. Если их не удается найти — отдаем страницу 404.
9. Создаем символьную ссылку на нашу конфигурацию в директорию /etc/nginx/sites-enabled/ и проверяем ее на валидность. Если ошибок нет, отправляем Nginx команду на перезагрузку конфигурации:
ln -s /etc/nginx/sites-available/todo-list /etc/nginx/sites-enabled/
nginx -t
nginx -s reload
Вывод должен выглядеть примерно так.
10. Если ошибок не было, то при обращении к серверу через веб-браузер http://31.129.35.121/ вы получите страницу веб-приложения:
Настройка раннера
Когда проект небольшой и разрабатывается одним человеком, то ручной деплой, как мы это делали ранее, вполне уместен. Но если речь о командной работе над корпоративным или продуктовым приложением, то нужен автодеплой. Так при правках код будет сразу поставляться на сервере.
Пойдем простым путем. У нас есть сервер с развернутым веб-приложением, а код хостим на GitLab, где доступен удобный инструмент для организации CI/CD-конвейера — GitLab CI. С его помощью сможем поставлять приложение на веб-сервер. Рабочий механизм — GitLab Runner, а процессы описываются с помощью gitlab-ci.yml в корне репозитория.
1. Создадим раннер для проекта. Перейдем в Settings → CI/CD → Runners и нажмем New Project Runner.
2. Укажем произвольный тег, который мы дальше будем использовать при настройке CI/CD, а также описание раннера. Нажмем Create runner.
3. Следующая страница содержит инструкции по настройке раннера, а при клике по выделенной ссылке появится шпаргалка по установке раннера на сервер.
Выполнение шагов установки должно выглядеть примерно так:
Во время выполнения джобов CI/CD можно столкнуться с ошибкой:
ERROR: Job failed: prepare environment: exit status 1. Check https://docs.gitlab.com/runner/shells/index.html#shell-profile-loading for more information
Для решения нужно использовать подсказку из документации.
4. Перейдем к регистрации раннера, как указано в Step 1.
Указываем источник и название по умолчанию, тип раннера — shell, так как исполнять команды будем на самом сервере:
5. После успешной регистрации на странице появится блок об успешном завершении.
6. Нажимаем кнопку View runners и видим страницу с раннерами для нашего проекта.
Важно! Нажимаем кнопку Enable for this project, чтобы раннер был включен для этого проекта.
Автодеплой
Созданный раннер будет выполнять все команды от пользователя gitlab-runner, но сперва попробуем сделать все вручную.
1. Создаем новую директорию, в котором будем размещать всю «статику» (статические файлы). Меняем владельца и группу на gitlab-runner.
mkdir /var/www/todo-list-build
chown gitlab-runner:gitlab-runner /var/www/todo-list-build
2. Меняем путь до корня сайта в конфиге Nginx.
3. При помощи nginx -t проверяем конфигурацию на ошибки, а далее перезагружаем конфиг командой nginx -s reload.
4. Заходим от имени пользователя gitlab-runner, собираем и деплоим проект.
su gitlab-runner
cd # переход в домашнюю директорию пользователя
git clone <a href="https://gitlab.com/Byurrer/todo-list.git">https://gitlab.com/Byurrer/todo-list.git</a>
npm install
npm run build
rsync -av --delete build/ /var/www/todo-list-build/
5. Проверяем в директории /var/www/todo-list-build/, что файлы скопированы.
6. Переходим в браузере по IP сервера. Веб-приложение также должно работать.
7. Теперь, когда мы поняли, какие команды будет выполнять раннер, можем реализовать автодеплой. Для его настройки нужно в корне репозитория создать файл .gitlab-ci.yml с таким содержимым:
stages:
- build
- deploy
build:
stage: build
script:
- npm install
- npm run build
cache:
paths:
- node_modules/
artifacts:
paths:
- build/
tags:
- todo-list
deploy:
stage: deploy
script:
- rsync -av --delete $CI_PROJECT_DIR/build/ /var/www/todo-list-build/
only:
- main
tags:
- todo-list
8. Запушим в ветку main произвольные изменения и перейдем в Builds → Pipelines, где появился автоматически запущенный конвейер.
Внутри выполняются две джобы:
Можно перейти к каждому из них и наблюдать процесс выполнения.
Успешное исполнение джобы на стадии deploy выглядит примерно так.
После выполнения всего конвейера наши правки должны поступить в приложение на веб-сервере.
Заключение
Мы рассмотрели один из простых вариантов организации CI/CD-конвейера для веб-приложения. В реальных условиях процесс становится более сложным и гибким, однако понимание его основ — первый шаг. Далее вы можете масштабировать и адаптировать проект под задачи в рабочей среде.
egribanov
Можно подобное, но только на gitea? Небольшие проекты тоже можно автодеплоить
markelov69
git webhook (применим к любому типу github, gitlab, gitea и т.д. и т.п.)
1) поднимаете http server (например на node.js)
2) настраивайте webhook чтобы слал инфу о пушах по адресу вашего http сервера
3) Получаете инфу на сервере о пушах и делаете уже что нужно. Например git pull && npm i && npm run build и т.п.
Всё что душе угодно, хоть тэги с версиями проставляйте, в JIRA или куда угодно по АПИ обращайтесь
4) Запустить всё это чтобы работало автоматически например через pm2
Вот пример:
В это примере на этом же сервере поднят nginx и он натравлен на папку dist которая появляется при сборке.
По сравнению с остальными способами типа раннеров с докерами и т.п. этот работает сверх быстро, по сути время работы занимает только npm run build, сомневаюсь что при каждом пуше вы меняете зависимости чтобы их приходилось доустанавливать)
Если планируется что пушить будете очень часто и возможна ситуация где условно в рамках нескольких секунд прилетит более 1 хука которые должно провоцировать билд, то лучше завернуть это в очередь, это достаточно легко
Byurrer Автор
Пока не доводилось работать с gitea, возможно позже рассмотрю.
savostin
Да почти так же.