Привет, Хабр! В этом материале мы разберем деплой приложения на React, арендуем облачный сервер и настроим nginx. Здесь будет необходимый минимум для фронтенд-разработчика:
- Заливка проекта на GitHub.
- Аренда и настройка облачного сервера по SSH.
- Настройка nginx для раздачи статических файлов.
- Сжатие бандла.
- Подключение домена.
- Настройка HTTPS.
- Настройка Docker.
Для этого материала также доступна видеоверсия.
Зальем проект на GitHub
Нас интересует только запуск в режиме dev и сборка самого приложения. Для разработчиков на Vue или Angular все будет работать аналогично. Исключение — приложения с серверным рендерингом. Алгоритм деплоя для них отличается.
В приложении есть пара кнопок, значения и навигация по страницам. Этого достаточно, чтобы рассмотреть процесс деплоя. Чтобы взаимодействовать с этим проектом, нам необходимо залить его на GitHub, GitLab, Bitbucket — любой удаленный репозиторий. Делаем git init, git add, проводим commit — теперь с кодом можно работать. Наиболее подробно про инициализацию репозитория можно прочитать по ссылке.
Арендуем и настроим облачный сервер по SSH
облачный сервер
Облачная платформа
Создать
Проверьте в терминале, установлен ли у вас SSH-клиент. Команда SSH должна выдавать такой результат.
Поздравляю — вы успешно подключились к серверу, и вам полностью доступно взаимодействие с операционной и файловой системой.
Здесь можно вводить любые команды, которые доступны на Ubuntu, поскольку мы выбрали именно эту операционную систему.
Теперь обновим APT — инструмент для работы с пакетами. Это нужно для того, чтобы установить Node.js, Git, Docker, если потребуется.
sudo install git-all
После установки Git перейдем в корень файловой системы и клонируем в нее репозиторий. Поскольку репозиторий открытый, можно легко клонировать его через git clone.
Теперь здесь есть index.html, исходный код, и можно установить зависимости. Node Version Manager необходимо поставить на чистую операционную систему облачного сервера. NVM нужен, чтобы гибко управлять версиями Node.js.
Чтобы все заработало, необходимо добавить переменную окружения. Копируем строчку:
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
После ввода команды NVM должен заработать.
Сейчас актуальная LTS-версия Node.js — v18.16.1. Устанавливаем ее через NVM. Чтобы проверить установку, можно использовать команду:
node -v
Теперь время установить пакеты. Делаем:
npm i
Чтобы сделать сборку проекта в package.json, есть отдельный скрипт.
Удалим папку dist и попробуем его запустить:
npm run build
Появляется папка dist — там будет index.html, внутри которого подключен скрипт. Последним является наш бандл .js, который получился в результате компиляции Typescript-кода и счетчика на React.
Теперь эту же сборку сделаем уже на удаленном сервере. Для этого пишем npm run build и ждем успешной сборки. Если написать команду ls, то здесь появится папка dist со всем нужным внутри.
Теперь необходимо донести сборку с index.html до пользователя, чтобы он перешел на наш домен и сервер отдал ему эти статические файлы. Для этого используем nginx.
Команду sudo apt update уже выполнили. Теперь с помощью APT установим сам nginx. Копируем команду:
sudo apt install nginx
Настройка nginx
Перейдем в папку etc и введем команду ls, чтобы посмотреть содержимое папки. Появится директория nginx. Здесь лежит много файлов, но нас интересует файл с конфигурациями.
С помощью Vim откроем его и посмотрим на содержимое. Если Vim по дефолту не установлен, то сначала займемся этим, чтобы более удобно работать с файлами. Повторяем команду:
vim nginx config
Сейчас нужно обратить внимание на два зеленых include, которые находятся в самом низу. В них подключаются дополнительные конфиги, которыми можно расширить главный.
При работе с Vim в первый раз будет трудно. Сначала нужно выйти, нажав Escape, далее :q! — так можно выйти из редактора без сохранения.
Теперь перейдем в папку sites enabled, на которую стоял include. Здесь будет файл default, откроем его с помощью Vim. Здесь множество различных комментариев, которые лучше удалить, чтобы не отвлекаться.
Первая строчка listen 80 говорит, что веб-сервер будет слушать 80 порт. Для HTTP он является основным по умолчанию. То есть здесь можно прописать любой порт, но тогда его каждый раз придется указывать в URL.
Далее указана строчка root /var/www/html — это путь к папке, в которой будут располагаться статические файлы: index.html, css-файлы, js-файлы, картинки и т. д. Далее указываются названия энтри-пойнтов. В нашем случае это index.html. Здесь можно задать разные названия. Затем указывается server_name — он пока не особо интересен. Следующая директива — location, в ней идет работа с URL. С помощью нее можно настраивать редиректы, проксирование, обрабатывать query-параметры.
Так выглядит минимальный конфиг для того, чтобы nginx раздавал статические файлы.
Теперь сохраним конфиг без комментариев. Для этого нажимаем Escape :wq.
Еще раз поговорим, как nginx понимает, какие файлы ему надо раздавать. В пространстве var/www/html нужно указать путь до папки, в которой лежит проект. Давайте заменим его на var/www/dist. Dist — это папка, в которой собирается наше фронтенд-приложение.
Выходим из Vim с сохранением :wq, и теперь уйдем обратно в корень на несколько уровней вниз, чтобы перейти в папку var/www. Здесь внутри лежит html-папка, которую нужно удалить командой:
rm -rf html
Теперь сделаем сборку еще раз:
npm run build
Когда папка со сборкой появится, переместим туда var/www.
Указываем название папки, которую хотим переместить, и куда хотим переместить.
Теперь папке dist внутри лежит index.html. Если обновить страницу — получим not found. Обратите внимание на директиву location. Сейчас папку html удалили, поэтому найти ее не получилось, и вернулся 404.
Чтобы система начала читать уже не из папки html, а из папки dist, необходимо перезапустить nginx командой:
sudo service nginx restart
Чтобы nginx всегда запрашивал index.html, необходимо настроить проксирование запросов. Нужно избавиться от этого 404 и сделать редирект. На любом участке пути он всегда будет отдавать пользователю ndex.html. Сейчас у нас в участке пути — welcome, если мы страницу обновляем — все начинает работать.
Если вы делали не Single Page Application, а классическое многостраничное приложение, где много HTML-файлов, проксирование на index.html настраивать не надо.
Промежуточный итог: что успели сделать
- Арендовали облачный сервер.
- Подключились к нему по SSH.
- Клонировали проект, установили Node.js, NVM.
- Установили нод-модули, сделали сборку, установили nginx.
- Настроили раздачу статических файлов и сборку приложения в отдельной директиве.
Концепция сжатия бандла
Смотрим на колонку Size и перезагружаем с очисткой кэша. И видим index bundle — это как раз файл index.js, который получился в результате сборки приложения.
Теперь попробуем уменьшить размер бандла. Если приложение большое и весит, например, 5-7 МБ, его лучше оптимизировать через код: разбить на чанки, использовать Lazy loading и т. д. Кроме этого, можно оптимизировать размер с помощью nginx-модуля gzip. Чтобы gzip работал, в корневой конфигурации nginx необходимо раскомментировать строки:
Эти строчки можно перенести в нашу конфигурацию, которая лежит в папке sites enabled.
Здесь важно обратить внимание на gzip_comp_level — это уровень грубости сжатия файлов. Максимальное сжатие — девять, минимальное — один. Важно соблюдать золотую середину: если переборщить с сжатием, можно потратить слишком много ресурсов. Чем сильнее сжатие, тем меньше трафика тратится, когда бандл перегоняется файлами по сети.
Нажимаем Escape, :wq, перезапускаем nginx:
sudo service nginx restart
При любых изменениях в конфиге nginx лучше делать рестарт. Перезагрузим страницу с очисткой кэша еще раз. Как видим, бандл стал весить ровно в три раза меньше: весил 193 килобайта, сейчас — 63.
В заголовках можно увидеть content encoding gzip, то есть gzip сжал index.html и разархивировал его в браузере.
Подключение домена
Вводите любое уникальное название для вашего домена — в нашем случае пусть это будет vite-deploy-test. Для подключения необходимо указать DNS-серверы, которые будут обрабатывать домен. Поскольку хостимся в Selectel, будем использовать его DNS-серверы — здесь также есть небольшая инструкция, чтобы добавить домен.
Копируем название домена в панель управления Selectel и добавляем его. Открываем этот домен и видим адреса. Вернемся обратно в инструкцию и посмотрим, как делегировать домен.
Здесь необходимо передать управление на DNS-серверы Selectel. Они отличаются только цифрами в названии. Указав их, возвращаемся в инструкцию по делегированию доменов. Нажимаем Подключить к другому хостингу или сервису, указываем DNS-сервера — ns1, ns2, ns3 и ns4.
Настройка сертификатов
Let’s Encrypt
Далее по SSH подключаемся к серверу, необходимо установить snapd. Проверить, установлен ли snapd, можно с помощью команды:
snapd--version
Далее уже существующий certbot нужно удалить. На всякий случай выполним команду:
sudo apt get remove certbot
Следующим этапом идет его установка. Копируем команду:
sudo ln -s /snap/bin/certbot /usr/bin/certbot
Certbot успешно установился. Переходим в корень проекта и выполняем следующую команду. Теперь необходимо объединить certbot с nginx и настроить его. Вставляем команду, а далее будет небольшой опросник:
- Certbot спрашивает email-адрес, вводим свой.
- Дальше дважды он требует подтверждения, соглашаемся.
- После чего он попросит ввести вас доменное имя, для которого нужен сертификат.
Деплоим сертификат
Теперь перейдем в nginx sites enabled с нашим дефолтным конфигом. Здесь появятся дополнительные настройки. Теперь прослушивается 443-й порт — дефолтный порт для HTTPS. 80-й порт для классического HTTP у нас также прослушивается. Можно также увидеть строчки, которые подгружает certbot для работы с сертификатами. Остается в server namе передать доменное имя. Передаем его и через пробел передаем его с префиксом www. Почти конец.
Сохраняем, выходим из Vim и перезапускаем nginx. Еще есть команда, которая проверяет, что конфиг заполнен корректно — рекомендую ее выполнить:
nginx -t
Меняем HTTP на HTTPS, и замок становится закрытым — безопасное подключение, сертификаты валидны, HTTPS работает как нужно.
Промежуточный итог
Сертификаты настроили, домен настроили, облачный сервер настроили. Теперь посмотрим, как довозить изменения в коде. Обратите внимание, что в welcome page появились правки: вывод id из query-параметров и параметров строки запроса.
Переходим на welcome, вводим id в строку. Убедимся, что nginx сейчас корректно обрабатывает эти query-параметры.
Работаем с изменениями
Во-вторых, переходим в папку, в которой расположен проект. Перед этим подключимся по SSH, потому что через какое-то время соединение отваливается. Открываем папку и делаем git pull. Таким образом, мы подтянем с GitHub, с удаленного репозитория, все изменения. Заново делаем сборку:
npm run build
Удалим старую сборку из папки var/www и переместим туда новую сборку: mv dist, и путь до папки www.
Попробуем открыть приложение vite-deploy-test. Сейчас уже с новыми правками сюда доехал id. Давайте попробуем добавить query-параметр:
Дело за малым: осталось сохранить конфигурацию nginx. Перейдем в папку, в которой она находится, с помощью команды:
cat default
Выведем все содержимое файла в терминал и скопируем это.
Откроем Webstorm, сделаем папку .nginx, а внутрь поместим сам конфиг, nginx.conf. Сюда вставляем то, что скопировали из терминала. Если теперь будет изменен сервер, конфиг можно забрать с собой, скопировав его в нужную папку.
Для базового сценария и Single Page Application все готово. Изменения появляются быстро, какого-то сложного пайплайна не нужно. Если нужно автоматизировать и инкапсулировать все это в контейнер, то теперь настроим Docker.
Настройка Docker
Завершающие штрихи
Повторяем действия для самого конфига: перемещаем в папку nginx sites enabled. Запускаем nginx, и теперь из коробки все будет работать. Может быть, на этом этапе еще потребуется поработать с портами и настройкой доступа по HTTPS, но нет ничего такого, что мы не рассматривали.
Для простых сценариев это избыточно. Docker нужен, если есть какой-то нетипичный пайплайн или сложная инфраструктура, а вы хотите больше автоматизировать. Тогда да, без проблем, но и конфиг будет сложнее.
Заключение
конфигурация
Полезные материалы по теме
Как задеплоить сайт в облако. Инструкция для новичков
Опубликовать сайт можно разными способами. Например, если проект лежит в репозитории на GitHub, можно воспользоваться GitHub Pages. Но если вы не боитесь трудностей, советуем попробовать кое-что поинтересней — разместить сайт на облачном сервере.
Новичкам этот способ может показаться сложным. Но на самом деле он очень удобен, потому что вы сможете легко масштабировать архитектуру проекта и гибко управлять мощностями сервера.
- Масштабируемость. Облачные серверы легко масштабируются, вы можете увеличивать ресурсы по мере роста проекта.
- Гибкость и контроль. Вы полностью контролируете виртуальный сервер и можете настроить его под проект.
Просто повторяйте за этой инструкцией, и все получится.
Дисклеймер: статический сайт в статье взят в качестве примера.
План работы
Что нужно знать для начала работы: как работать с Git.
Что будем делать:
- арендуем облачный сервер,
- запустим виртуальный сервер,
- задеплоим сайт,
- установим доменное имя,
- подключим сертификат безопасности.
Важно: мы не будем углубляться в детали работы с веб-сервером — затронем лишь то, что важно для нашей задачи. Но для тех, кому интересно разобраться поглубже, оставим ссылки на полезные материалы.
Арендуем сервер
инфраструктуру Selectel
Есть два варианта конфигов: фиксированный или произвольный. У нас простой ознакомительный проект, поэтому выбираем первый вариант. Но вы можете более гибко настроить конфигурацию под свои задачи.
Указали имя и регион, выбрали фиксированную конфигурацию.
Обязательно проверяем, что на странице указан новый публичный IP — без него сайт будет недоступным в сети.
Нажимаем Создать сервер и ждем, пока появится статус Active:
Готово! Мы создали облачный сервер и теперь можем разместить на нем сайт.
Подключаемся к веб-серверу
Открываем терминал и смотрим, установлен ли у нас SSH-клиент. Вводим команду:
ssh
Если все в порядке, вы увидите примерно такой результат.
Если клиент не установлен или вы не знаете, что такое SSH, прочитайте эту статью.
Переходим в панель управления, открываем раздел с серверами и копируем публичный IP:
Публичный IP находится сверху.
ssh root@198.51.100.155
Консоль предложит ввести пароль. Переходим в панель управления и выбираем сервер — пароль будет лежать в разделе Консоль под звездочками:
Копируем пароль и вставляем в терминале.
Готово, сервер запущен.
Клонируем проект из GitHub
Важно: далее мы будем работать с менеджером пакетов apt, такова специфика нашего дистрибутива Ubuntu. В CentOS, AlmaLinux и других дистрибутивах могут использоваться иные пакетные менеджеры, например, yum. Структура каталогов в Nginx тоже может отличаться.
Мы можем или скопировать архив в формате tar.gz, или склонировать репозиторий. Давайте остановимся на втором варианте — он нам нравится больше. Чтобы склонировать проект на сервер, сначала нужно установить Git. Вводим поочередно команды:
sudo apt update
sudo apt install git
Затем создаем каталог для сайта:
sudo mkdir -p /var/www/mysite
Открываем репозиторий с проектом и копируем SSH:
А затем клонируем репозиторий:
cd /var/www/
sudo git clone <ваш-SSH>
На этом этапе может появиться ошибка доступа. Без паники, нужно лишь настроить подключение по SSH к вашему репозиторию.
Как это сделать
Устанавливаем Nginx и деплоим сайт
NGINX Unit.
Как работать с Nginx
Поочередно вводим в терминале:
sudo apt update
sudo apt install nginx
Если вы сейчас откроете браузер и введете в адресной строке публичный IP, откроется приветственная страница. Это знак, что вы на верном пути.
Сервер подняли, теперь нужно его настроить. Создаем конфигурацию Nginx:
sudo nano /etc/nginx/sites-available/mysite
server {
listen 80;
server_name your_domain_or_ip;
root /var/www/mysite;
index index.html;
location / {
try_files $uri $uri/ =404;
}
location ~ /\.(?!well-known).* {
deny all;
}
}
Вместо IP можно сразу указать домен, но мы это сделаем позже, иначе сейчас не сможем проверить работу сервера.
И теперь активируем конфигурацию и запускаем веб-сервер:
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/
sudo service nginx restart
Вновь откроем браузер и вставим в адресную строку IP. Если все сделали верно, увидим нашу страницу:
Теперь под нашим IP открывается сайт.
Подключаем домен
Домен можно арендовать у компании-регистратора доменов. Минимальный срок регистрации для всех доменных зон — год, а максимальный зависит от зоны. Например, для .ru это год, а для .com — до 10 лет.
У нас появится домен с автоматически настроенными NS-серверами: ns1.selectel.ru, ns2.selectel.ru, ns3.selectel.ru, ns4.selectel.ru. Теперь нужно перейти на сайт доменного регистратора (где вы арендовали домен) и добавить эти серверы. То есть настроить делегирование:
Делегирование занимает время — набираемся терпения и просто ждем.
Когда все будет готово, возвращаемся в терминал и меняем публичный IP на домен:
Обязательно обновляем конфигурацию и перезапускаем веб-сервер:
sudo ln -s /etc/nginx/sites-available/mysite /etc/nginx/sites-enabled/
sudo service nginx restart
Переходим в панель управления, открываем вкладку с доменом, кликаем по нему и в открывшемся окне жмем на кнопку Добавить запись.
- Выбираем тип записи — A, AAAA, TXT, CNAME, NS, MX, SRV, SSHFP, ALIAS или CAA.
- Вводим имя — домен, для которого будет создана запись. Мы создаем для основного домена, поэтому оставляем поле пустым.
- Указываем TTL — время в секундах, через которое кэш запросит информацию об обновлении записи. Мы оставляем значение по умолчанию.
- Указываем публичный IP.
Жмем на кнопку Добавить запись.
Добавляем запись типа А.
Мы опубликовали сайт. Можно открыть браузер и проверить, что все работает.
Настраиваем SSL-сертификат
SSL-сертификат
SSL (Secure Sockets Layer) — это протокол шифрования, он обеспечивает защищенную передачу данных между пользователем и сервером.
Мы установим бесплатный сертификат от Центра Сертификации Let’s Encrypt®. Воспользуемся Certbot и за пару кликов подключим SSL.
apt install certbot python3-certbot-nginx
sudo certbot --nginx
Нам предложат указать почту — вводим ее, а затем соглашаемся с условиями:
Вводим Y, чтобы согласиться с условиями.
Далее появится список аккаунтов — указываем номер подходящего и видим сообщение о выпуске сертификата:
Сообщение о создании сертификата.
Возвращаемся в браузер, перезагружаем страницу и видим иконку безопасного соединения:
Появилась иконка замка.
На этом наша работа закончена. Мы опубликовали сайт и настроили сертификат.
Заключение
файрвол