Как настроить GitHub Actions и не заплакать: пошаговая инструкция
Привет всем! Меня зовут Виталий, я фронтендер в Mish. Решил недавно освоить полноценный автоматический деплой проекта, чтобы все работало само. Расскажу и вам, что из этого получилось.
В статье буду разговаривать о деплое только фронтенда. Про деплой бэкенда расскажу в следующем материале.
Выбираем платформу
Настраивать деплой файлов и переносить их на сервер в определенную папку — как-то несовременно. Поэтому взгляд упал на Docker.
Дальше встал вопрос хостинга. Можно было воспользоваться AWS, но хотелось построить весь процесс с нуля. Поэтому выбрал сторонний сервис, чтобы и домен, и все остальное было свое.
Так как до этого проект лежал на хостинге Sprinthost, а недавно они добавили виртуальные боксы, решил купить его и там же настроить деплой. Не хотелось платить много денег за мощности, поэтому решил собирать приложение за счет GitHub, раз уж они такие добрые.
Теперь выбираем сервер дороже 100 рублей и начинаем думать, как реализовать проект.
Начинаем процесс
Раз мы будем использовать докер, то грех не использовать Docker Hub. Вот как это будет выглядеть:
Если описать эту историю словами, то выглядеть будет так:
- Собираем на Git новый image приложения.
- Закидываем его в репозиторий Docker Hub.
- Обновляем контейнер.
- Наслаждаемся победой.
Для начала нам нужно будет определиться с Linux, который будем использовать. Так как Sprinthost предоставляет готовые сборки, выберем Ubuntu + Docker + Pointer. Но если захотите иначе, все это сработает и на CentOS.
Подготавливаем окружение
Создадим Dockerfile для нашего фронтенда:
Если вы новичок, то можете еще не знать, что такое nginx.conf и зачем он нужен. Это конфигурационный файл nginx — сервера, который будет отображать нашу страницу по заданному домену. Его задача — лежать внутри проекта. Для этого создаем в корне папку nginx и в нее кладем .CONFIG файл:
Подготавливаем репозиторий Docker Hub
Репозитории в Docker Hub есть приватные и публичные. Использовать можно любой. Я не хотел тратить бесплатный приватный слот, поэтому сделал его публичным. Вы можете сделать так, как удобно вам.
Заходим на Docker Hub, регистрируемся, запоминаем пароль и логин — он понадобится в будущем. Теперь создаем репозиторий:
Нажимаем на синюю кнопку, после чего указываем тип репозитория и его название:
Теперь докер подсказывает справа, как привязать репозиторий. Но можно поступить проще. Идем в консоль сервера и начинаем процесс логина. Для этого не нужны никакие SSH-ключи, достаточно логина и пароля:
Если все прошло успешно, вы увидите надпись login succeeded.
Настраиваем сервис
Как помним из схемы, сначала нужно подтянуть все обновления image из репозитория, потом обновить контейнер. Для этого проще всего создать собственный скрипт, чтобы запускать его потом из-под GitHub Actions.
Создадим отдельного пользователя и дадим необходимые права. Сразу переходим на этого пользователя, чтобы скрипт был ему доступен:
Теперь создаем новый файл под названием deploy.sh и пропишем в него следующие команды:
В данном случае я назвал пользователя frontend — для прозрачного распределения обязанностей — и выдал ему права доступа к контейнеру Docker, чтобы не было ошибок. Нужно учитывать, что подобный деплой сделает недоступным сервис во время остановки и запуска контейнера. Чтобы всего этого избежать, можно использовать дополнительные возможности, о которых я расскажу в следующих материалах.
Создаем контейнер
Теперь придется немного поработать руками. Собираем локально image и закидываем его на Docker Hub через консоль или Docker Desktop. Первый вариант удобнее:
Далее переходим в контейнер на сервере и обновляем image:
Теперь создадим контейнер, который будем обновлять. Заодно проверим, как все работает:
У меня это выглядит вот так:
Переходим в консоль сервера и проверяем, все ли работает:
Результат перед вами:
Все запустилось с первого раза. Главное — не забудьте выключить nginx, если он запущен на сервере, чтобы не было конфликтов. Это можно сделать такой командой:
Мы на середине пути — что имеем к этому этапу:
- Сборку приложения в докере
- Репозиторий на Dockerhub
- Работающий контейнер на сервере
Автоматизируем процесс
Для этого используем GitHub Actions.
Заходим в наш репозиторий и задаем все секретные ключи:
- Docker username
- Docker password
- Docker Repo Name
- Server ip
- Server port (default 22)
- Server user login
- Server user password
Добавляем их в секретные ключи. В итоге страница будет выглядеть так:
Теперь можем переходить к настройке самого GitHub Action. Идем во вкладку и выбираем Manual Workflow. Задаем туда этот код:
Первая часть job запускает стандартный workflow гита:, он собирает image и пушит его в репозиторий. Здесь же можно настроить различные метки, например, если хотите хранить больше одного image на сервере.
В server_update подключаемся к нашему серверу и запускаем написанный скрипт, чтобы обновить контейнер с приложением. Также указываем script stop, если выпала какая то ошибка на сервере.
Еще указан параметр needs. Он нужен, чтобы программа дождалась предыдущего шага и только потом начала что-то творить на сервере.
Тут же можно настроить билд для pull requst и проверки на сборку, чтобы случайно не залить нерабочую версию.
Так мы защищаем главную ветку и триггерим сборку только в тот момент, когда кто-то вносит изменения в основной код. Как только мы объединили две ветки, запускается верхний workflow, который обновляет версию на сервере.
Теперь все готово — можем поаплодировать и себе и погладить по голове. Пользуйтесь моими советами и алгоритмами, чтобы у вас все было, но вам за это ничего не было.