October 13, 2022

Свой приватный Интернет-клуб (на платформе Vas3k.Club) #4

Всем привет! Это 4 часть цикла статей про создание своего Интернет-Клуба по интересам на базе платформы Vas3k'а. В этой части мы с Вами обсудим процесс выкладки Клуба в продакшен (Наконец-то!). Но мы его не завершим, останется чуть-чуть :)

Предыдущие серии:

  1. Делаем форк и поднимаем базовые сервисы: https://teletype.in/@toptuk/pmiclub1
  2. Готовим конфигурационные файл и поднимаем клуб локально: https://teletype.in/@toptuk/pmiclub2
  3. Кастомизируем Клуб под себя: https://teletype.in/@toptuk/pmiclub3

ПРЕДИСЛОВИЕ

В первой части на сервере мы уже запустили сервисы обратный прокси (reverse proxy), Pepic и ogimgd. Эти сервисы должны быть доступны для обращения в браузере. Если это не так, то самое время это исправить!

Также, для Клуба нужен собственный почтовый сервис. Вы можете использовать Mailgun или же поднять собственный сервис.

Вы должны уметь конфигурировать Клуб:

  • Подготовлен конфигурационный файл .env
  • Актуализирован файл settings.py
  • Настроена интеграция с сервисом Sentry
  • Настроена интеграция с Telegram

Если это не сделано, то вот статья, как это сделать.

Ну штош! Я надеюсь, что локального все работает иготово для публикации Клуба в продакшн. ПОЕХАЛИ! Надеюсь вы получите удовольствие от настройки Клуба :)

Структура проекта в GitHub

Структура бранчей

При создании форка репозитория Vas3k'а в GitHub по умолчанию был создан master бранч вашего Клуба, и для него были отключены все GitHub Actions.

Скрипты Actions располагаются в директории ".github/workflows" вашего проекта:

По умолчанию, унаследованы следующие GitHub Actions:

  • Run tests - файл "tests.yml". Запускает тест Линтер и функциональные тесты Клуба.
  • Check it could be build and run from scratch - файл "check_build_and_run.yml". Тест, что Клуб может быть запущен с параметрами по умолчанию. Это смоук тестирование Клуба.
  • Deploy production - файл "deploy.yml". Запускает скрипт публикации и запуск Клуба в продакшн среде. Это основной Action, с помощью которого осуществляется публикация новой версии Клуба.
CodeQL - файл "codeql-vulnerability-analysis.yml". Запускает анализатор кода Клуба. Мне не удалось нормально запустить этот Action, поэтому, он останется выключенным.

Ранее мы договаривались, что мы дополнительно сделаем следующие ветки (бранчи) Клуба:

  • dev - для локальных доработок. Сюда мы будем делать коммиты всех локальных доработок.
  • deploy - бранч, который отвечает за публикацию новой версии Клуба в продакшн, когда в него делается пул реквест.

Процесс доработок выглядит следующим образом:

  • Локальные доработки делаем в dev ветке (бранче). При коммите тест Action не запускаются.
  • Когда в dev ветке сделаны логически законченные доработки, то синхронизируем dev с master. Синхронизацию доработок будем делать через pull request -> запускаются тест Action "Check it could be build and run from scratch и Run tests".
  • Когда хотим опубликовать новую версию Клуба в продакшн, то делаем pull request из master ветки в ветку deploy. При этом запускается Action "Deploy production".

Обратите внимание, что осуществлять публикацию мы будем при условии, что тестовые Actions успешно пройдены.

Для перехода в раздел GitHub Actions нужно выбрать соответствующую вкладку:

GitHub actions запускаются только из master ветки..
Пока еще все GitHub Actions отключены.

Проверьте, что локальные доработки из 3 части статей сделаны для dev ветки. Если это не так, то пообещайте себе и мне, что следующие инкрементальные доработки будут сделаны в dev бранче ❗

Исследуем GitHub Actions

Исследуем Makefile

Откройте файл Makefile в корне вашего Клуба. В этом файле содержатся команды, которые запускают Клуб в различных средах - тестовом или продакшн окружении.

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

run-bot: ## Runs telegram bot
  pipenv run python bot/main.py

docker-run-bot:
  python3 bot/main.py

docker-run-dev: ## Runs dev server in docker
  python3 ./utils/wait_for_postgres.py
  python3 manage.py migrate
  python3 manage.py update_tags
  python3 manage.py runserver 0.0.0.0:8000

Знакомые команды, неправда ли? Все эти команды вызываются при запуске Клуба с помощью Docker. Вот пример из файла docker-compose.yml (см. "command: make docker-run-dev"):

...
services:
  club_app: &app
  build:
    dockerfile: Dockerfile
    context: .
  command: make docker-run-dev
...

Т.е. при запуске команды "docker-compose -f docker-compose.yml up -d" в контейнерах будут выполнены команды из Makefile раздела "docker-run-dev".

Исследуем Action "Check it could be build and run from scratch"

Файл .github/workflows/check_build_and_run
name: Check it could be build and run from scratch

on:
  pull_request:
    branches: master

jobs:
  dockerize:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Build the docker-compose stack
        run: docker-compose up -d
      - name: Sleep
        uses: jakejarvis/wait-action@master
        with:
          time: '20s'
      - name: Check db migrate on container
        run: |
          docker-compose exec -T club_app make docker-migrate
      - name: Check build frontend on container
        run: |
          docker-compose exec -T webpack npm run build          

Этот скрипт будет запущен при создании pull request в master ветку (бранч):

  • В Docker будет запущены сервисы Клуба из файла docker-compose.yml с параметрами по умолчанию (т.е. .env файл будет отсутствовать).
  • Далее будет установлен таймаут 20 секунд на запуск сервисов.
  • После будет запущена миграция базы данных в сервисе docker-compose exec -T club_app make docker-migrate (docker-compose exec -T club_app make docker-migrate).
  • После в сервисе webpack будет запущен frontend (docker-compose exec -T webpack npm run build)

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

Вы можете уже активировать данный GitHub Action у себя в репозитарии. Дополнительной настройки этот тест не требует :)

Исследуем Action "Run tests"

Файл .github/workflows/tests.yml Я не буду приводить далее этот файл целиком, только рассмотрим основные моменты.

Скрипт запускается в случае pull request или push в master бранч и содержит два теста:

  • lint - запускает литер flake8 для Python кода.
  • test - запускает тесты.
on:
  pull_request:
  push:
    branches:
      - master      

Обратите внимание, что Клуб запускается в Docker с помощью файла docker-compose.test.yml (о нем ниже). Сервисы запускаются последовательно.

...
- name: Run redis
  run: |
    docker-compose -f docker-compose.test.yml up -d redis
- name: Run frontend
  run: |
    docker-compose -f docker-compose.test.yml up -d webpack
...

Для этого теста важно, чтобы корректно были внесены правки в файл settings.py, что мы делали во второй части. Этот Action активируем когда актуализируем файл docker-compose.test.yml.

Исследуем Action "Deploy production"

Файл .github/workflows/deploy.yml Это ключевой Action для публикации Клуба в продакшн.

В самом начале этого скрипта указано, что он срабатывает при прохождении pull request'а или push'а в ветку deploy.

on:
  push:
    branches:
      - Deploy      

Далее идут два скрипта:

  • build - данный скрипт собирает образ Docker Клуба (image) и выкладывает (push) его в репозитарий GitHub Packages. Образ собирается с помощью конфигурационного файла Dockerfile.
  • deploy - этот скрипт используется для публикации и запуска Клуба на продакшн сервере. Для этого скрипт осуществляет подключение по ssh к продакшн серверу, скачивает последнюю версию образа Клуба, генерирует .env файл и копирует docker-compose.production.yml файла.

Этот Action активно использует секреты репозитарий вашего Клуба, о которых ниже.

Файл docker-compose.test.yml

Файл docker-compose.test.yml

В этом файле нужно задать значения для следующих параметров сервисов tests и Postgres:

  • POSTGRES_DB
  • POSTGRES_USER
  • POSTGRES_PASSWORD

Запускаются следующие сервисы:

  • redis
  • postgres
  • webpack
  • tests - вызывается команда "make test-ci" из Makefile
Для сборки образа используется Dockerfile. Его править не нужно.

В третье части мы включали бесплатный вход в Клуб. Чтобы тестирование Клуба проходило успешно нам потребуется отключить некоторые тесты Stripe и Patreon. Для этого нам нужно отредактировать файл auth/views/tests.py.

Нужно пометить некоторые функции декоратором @skip:

  • Функция test_login_user_not_exist
@skip("Free membership")
def test_login_user_not_exist(self):
  response = self.client.post(reverse('email_login'),
    data={'email_or_login': 'not-existed@user.com', })
  
  self.assertContains(response=response, text="Такого юзера нет 🤔", status_code=404)
  • Класс ViewPatreonLoginTests(TestCase):
@skip("Free membership. Skip Pateron login")
class ViewPatreonLoginTests(TestCase):
  def test_positive(self):
  ...  
  • Класс ViewPatreonOauthCallbackTests(TestCase):
@skip('Free membership. Skip Pateron login')
@patch('auth.views.patreon.patreon')
class ViewPatreonOauthCallbackTests(TestCase):
  @classmethod
  def setUpTestData(cls):
  ...  

Настройка завершена. Можно активировать GitHub Action и делать коммит в начале в dev ветку, а после сделать pull request в master ветку. Должно запускаться тестирование, и его успешное прохождение. Поздравляю!

Если в процессе тестирования в логе вы видите какие-то ошибки, то их придется поправить руками.

Файл docker-compose.production.yml

Файл docker-compose.production.yml

Запускаемые сервисы:

  • club_app - основной сервис Клуба
  • queue - планировщик задач
  • bot - Телеграмм бот
  • cron - планировщик задач по расписанию
  • postgres - сервис базы данных
  • pgbackups - сервис бэкапа базы данных
  • redis - кеш сервис

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

networks:
  front:
    name: pmi_network
  club:
    name: club_network    
  • Сеть front - эта та сеть, которую мы создавали в первой части статей про Клубостроительства. Все сервисы: Обратный прокси, Pepic, Ogimgd, Mail-сервер; должны быть подключены к этой сети.
  • Сеть club нужна для того, чтобы сервисы Клуба взаимодействовали друг с другом.

Сервис club_app

club_app: &app
  image: ghcr.io/toptuk/pmiclub:${GITHUB_SHA:-latest}
  build:
    dockerfile: Dockerfile
    context: .
  command: make docker-run-production
  container_name: club_app
  environment:
    - MODE=production
    - PYTHONUNBUFFERED=1
    - DEBUG=false
    - APP_HOST=https://pmi.moscow
    - MEDIA_UPLOAD_URL=https://media.pmi.moscow/upload/
    - POSTGRES_DB=pmi_club
    - POSTGRES_USER=pmiclub
    - POSTGRES_PASSWORD=pmiclub
    - POSTGRES_HOST=postgres
    - REDIS_DB=0
    - REDIS_HOST=redis
    - VIRTUAL_HOST=pmi.moscow,www.pmi.moscow
    - VIRTUAL_PORT=8814
    - VIRTUAL_PATH=/
  env_file:
    - club/.env
  restart: always
  volumes:
    - ./frontend/static:/tmp/static
    - ./gdpr/downloads:/app/gdpr/downloads
  depends_on:
    - postgres
    - redis
    - queue
  ports:
    - "127.0.0.1:8814:8814"
  networks:
    - front
    - club    

Круто! Много параметров нужно задать:

  • image - образ Клуба, который опубликован в GitHub Packages. Обратите внимание, что должны быть использованы только прописные символы! Пример: ghcr.io/toptuk/pmiclub:${GITHUB_SHA:-latest}, где toptuk - это мой никнейм, pmiclub - название моего образа Клуба. Этот образ публикуется с помощью нашего GitHub Action, посмотрите на следующий пример (см. docker image push ghcr.io/toptuk/pmiclub:$GITHUB_SHA):
build:
  name: Build and pull club image
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@master
    - run: docker login ghcr.io -u $GITHUB_ACTOR -p ${{ secrets.TOKEN }}
    - run: docker build -t ghcr.io/toptuk/pmiclub:latest -t ghcr.io/toptuk/pmiclub:$GITHUB_SHA .
    - run: docker image push ghcr.io/toptuk/pmiclub:$GITHUB_SHA
    - run: docker image push ghcr.io/toptuk/pmiclub:latest
  • command: make docker-run-production - скрипт из Makefile.
  • APP_HOST - адрес вашего Клуба в Интернете.
  • MEDIA_UPLOAD_URL - ссылка на сервис Pepic. Заканчиваться должен на /upload/
  • POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_HOST - Параметры для подключения к БД Postgres.
  • REDIS_DB, REDIS_HOST - параметры для подключения к сервису Redis. Если ничего не переименовывали, то менять не нужно.
  • VIRTUAL_HOST - веб-адрес вашего Клуба для сервиса обратного прокси. С www и без www.
  • VIRTUAL_PORT=8814 и VIRTUAL_PATH=/ - вписать эти параметры для настройки обратного прокси.
  • Обратите внимание, что .env файл должен располагаться в директории club. Нам потребуется клонировать наш репозитарий на сервер и периодически обновлять его (когда изменяться static файлы).

Сервис Queue

queue:
  <<: *app
  command: make docker-run-queue
  container_name: club_queue
  depends_on:
    - postgres
    - redis
  ports: []
  networks:
    - club    

Пока все просто:

  • Сервис наследует все параметры из сервиса club_app (см. <<: *app)
  • Вызывается скрипт docker-run-queue из Makefile
  • Запуск сервиса зависит от запуска сервисов postgres и redis
  • Сервис должен быть подключен к сети club, и не подключатся к front.

Сервис Cron

cron:
  <<: *app
  command: make docker-run-cron
  container_name: club_cron
  depends_on:
    - club_app
    - postgres
    - redis
 ports: [] 

Надеюсь, что параметры для этого сервиса уже стали для вас тривиальными. Править ничего не нужно :)Удивление вызывает только то, что этот сервис не нужно подключать ни к одной Docker-сети.

Сервис redis

redis:
  image: redis:alpine
  container_name: club_redis
  restart: always
  environment:
    - ALLOW_EMPTY_PASSWORD=yes
  networks:
    - club    

Комментировать особо-то и нечего. Не забудьте подключить этот сервис к Docker-сети club. Остальное должно остаться аналогичным.

Сервис bot

bot:
  <<: *app
  command: make docker-run-bot
  container_name: club_bot
  environment:
    - APP_HOST=https://pmi.moscow
    - POSTGRES_DB=pmi_club
    - POSTGRES_USER=pmiclub
    - POSTGRES_PASSWORD=pmiclub
    - POSTGRES_HOST=postgres
    - REDIS_HOST=redis
    - REDIS_DB=0
    - VIRTUAL_HOST=pmi.moscow
    - VIRTUAL_PATH=/telegram/webhook/
    - VIRTUAL_PORT=8816
  depends_on:
    - club_app
    - postgres
    - redis
  ports:
    - "8816:8816"
  networks:
    - club    

Супер! Тут есть нюансы (не так, как в анекдоте):

  • APP_HOST - адрес вашего Клуба
  • POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD - уже знакомые вам параметры для подключения к БД. POSTGRES_HOST=postgres - название сервиса БД.
  • REDIS_HOST, REDIS_DB - оставляем как есть, если не меняли названия сервисов.
  • VIRTUAL_HOST - веб-адрес вашего Клуба без "https://".
  • VIRTUAL_PATH=/telegram/webhook/ - оставить "как есть". Это контроллер, обрабатывающий обращения к боту.
  • VIRTUAL_PORT=8816 - внешний порт для обращения к сервису, куда будут проксироваться запросы.
  • Сервис должен быть подключен к сети "club".

Сервис postgres

postgres:
  image: postgres:12
  container_name: club_postgres
  restart: always
  environment:
    POSTGRES_USER: pmiclub
    POSTGRES_PASSWORD: pmiclub
    POSTGRES_DB: pmi_club
  volumes:
    - /home/pmi-admin/pgdata:/var/lib/postgresql/data:rw
  ports:
    - "127.0.0.1:54333:5432"
  networks:
    - club    

Настройки:

  • POSTGRES_USER, POSTGRES_PASSWORD, POSTGRES_DB - параметры подключения к БД Postgres 12.
  • Сервис должен подключаться к Docker-сети "club"
  • Раздел volumes - нужно задать директорию, где будет локально храниться БД и синхронизироваться с Docker контейнером. Вам нужно изменить левую часть "/home/pmi-admin/pgdata" на свой путь.

Чтобы определить путь, где будет храниться БД нужно на сервере выполнить команду "pwd". В консоль будет возвращен путь до текущей директории. У меня это - "/home/pmi-admin/".

После этого, придумать название директории, где будут синхронизироваться файлы БД. У меня это "pgdata". Создавать ее вручную не надо, она будет создана автоматически при запуске сервиса postgres.

В итоге должны получить строку, соответствующую шаблону "/home/<user_name>/<db_directory>/. Эту строку записываем в левую часть раздела volumes.

Сервис pgbackups (опционально)

Предлагаю сразу сделать сервис, который бы периодически бекапил базу данных. В следующей статье вы узнаете как сделать так, чтобы ничего не потерялось :)

pgbackups:
  image: prodrigestivill/postgres-backup-local
  restart: always
  volumes:
    - /home/pmi-admin/backup/pmi/pgdata:/backups
  links:
    - postgres
  depends_on:
    - postgres
  environment:
    - POSTGRES_HOST=postgres
    - POSTGRES_DB=pmi_club
    - POSTGRES_USER=pmiclub
    - POSTGRES_PASSWORD=pmiclub
    - POSTGRES_EXTRA_OPTS=-Z6 --schema=public --blobs
    - SCHEDULE=@weekly
    - BACKUP_KEEP_DAYS=7
    - BACKUP_KEEP_WEEKS=4
    - BACKUP_KEEP_MONTHS=6
    - HEALTHCHECK_PORT=8080
  networks:
    - club    

Подробно почитать про "prodrigestivill/postgres-backup-local" можно тут: https://hub.docker.com/r/prodrigestivill/postgres-backup-local

На сервере нужно сделать (создать) директорию резервного хранилища. У меня это "/home/pmi-admin/backup/pmi/pgdata", у вас путь может быть другой, но не забудьте актуализировать секцию volumes.

Для директории бэкапов нужно установить права на чтение, выполнить "chmod -R 755 <путь до вашей директории>"

Не забудьте указать параметры POSTGRES_DB, POSTGRES_USER, POSTGRES_PASSWORD.

Секреты GitHub Actions

Приступим к настройке секретов GitHub Actions. Напомню, что они используются для деплоя новой версии Клуба.

В своем репозитарий Клуба в Github переходим в Settings -> Secrets/Actions:

С помощью кнопки "New repository secret" добавляем следующие параметры из .env файла (см. часть 2):

  • APP_HOST - веб-адрес вашего Клуба. Например: https://pmi.moscow
  • EMAIL_HOST - веб-адрес хоста почтового сервера. Например: mail.pmi.moscow
  • EMAIL_HOST_PASSWORD - пароль почтового аккаунта, который будет отправлять письма от имени Клуба.
  • EMAIL_HOST_USER - имя пользователя почтового аккаунта, который будет отправлять письма от имени Клуба.
  • JWT_PRIVATE_KEY - приватная часть JWT ключа. Важно! Проверьте, что нет лишних символов, особенно "\n\r". Лучше вписывайте его длинной строкой, без кавычек.
  • MEDIA_UPLOAD_CODE - код для сервиса Pepic (см. первую часть)
  • MEDIA_UPLOAD_URL - адрес сервиса Pepic с /upload/ в конце. Например: https://media.pmi.moscow/upload/
  • POSTGRES_DB - имя базы данных Postgres. Также, как в docker-compose файлах.
  • POSTGRES_PASSWORD - пароль для подключения к базе данных. Такой же как в docker-compose файлах.
  • POSTGRES_USER - имя пользователя для подключения к базе данных Клуба. Такой же как в docker-compose файлах.
  • SECRET_KEY - секретный ключ для Клуба. Попрежнему не вижу, где он используется, но пускай будет.
  • SENTRY_DSN - ссылка на Sentry. Формат такой же как в .env файле, без кавычек. Например: https://<aaabbbcccddd>@<o123456>.ingest.sentry.io/123456
  • TELEGRAM_ADMIN_CHAT_ID - идентификатор телеграм чата Модераторов.
  • TELEGRAM_BOT_URL - ссылка на телеграммное бота Клуба. Например: https://t.me/pmiclubbot
  • TELEGRAM_CLUB_CHANNEL_ID - идентификатор основного Клубного канала. Например: -100123456789
  • TELEGRAM_CLUB_CHANNEL_URL - URL адрес Клубного канала.
  • TELEGRAM_CLUB_CHAT_ID - идентификатор основного телеграм чата Клуба. Например: -100123456789
  • TELEGRAM_CLUB_CHAT_URL - URL адрес Клубного чата.
  • TELEGRAM_ONLINE_CHANNEL_ID - идентификатор телеграм Online чата.
  • TELEGRAM_ONLINE_CHANNEL_URL - URL адрес Online канала в телеграм.
  • TELEGRAM_TOKEN - токен для телеграммное бота.

Вы думаете это всё? Как бы не так... Давайте внимательно исследуем файл deploy.yml (GitHub Action).

Параметр TOKEN

Помните, что в первой части при создании Клуба создавали токен? Надеюсь вы его сохранили. Если нет, то нужно создать новый.

Этот токен используется тут, см. параметр secrets.TOKEN

build:
  name: Build and pull club image
  runs-on: ubuntu-latest
  steps:
    - uses: actions/checkout@master
    - run: docker login ghcr.io -u $GITHUB_ACTOR -p ${{ secrets.TOKEN }}
    - run: docker build -t ghcr.io/toptuk/pmiclub:latest -t ghcr.io/toptuk/pmiclub:$GITHUB_SHA .
    - run: docker image push ghcr.io/toptuk/pmiclub:$GITHUB_SHA
    - run: docker image push ghcr.io/toptuk/pmiclub:latest    

Он нужен для авторизации в GitHub Packages "docker login ghcr.io" вместе со встроенным параметром $GITHUB_ACTOR (это ваш логин в GitHub).

Обращаю внимание, что название образа вашего Клуба должно прописными символами. Например: ghcr.io/toptuk/pmiclub:latest

  • toptuk - мой никнейм, в оригинале TopTuK
  • pmiclub - название образа Клуба.

Исправьте, если это не так. Также параметр TOKEN используется в последней строке deploy.yml.

Добавьте параметр TOKEN в секреты вашего репозитария Клуба.

Настраиваем подключение к серверу Клуба

Давайте внимательно посмотрим на следующие строки deploy.yml

...
env:
  SSH_KEY_PATH: /tmp/ssh_key
...
- run: echo "${{ secrets.PRODUCTION_SSH_KEY }}" > ${{ env.SSH_KEY_PATH }} && chmod 600 ${{ env.SSH_KEY_PATH }}
- run: scp -o StrictHostKeyChecking=no -i ${{ env.SSH_KEY_PATH }} .env ${{ secrets.PRODUCTION_SSH_USERNAME }}@${{ secrets.PRODUCTION_SSH_HOST }}:/home/pmi-admin/pmi.moscow.club/club/.env
- run: scp -o StrictHostKeyChecking=no -i ${{ env.SSH_KEY_PATH }} docker-compose.production.yml ${{ secrets.PRODUCTION_SSH_USERNAME }}@${{ secrets.PRODUCTION_SSH_HOST }}:/home/pmi-admin/pmi.moscow.club/docker-compose.production.yml
- run: ssh -i ${{ env.SSH_KEY_PATH }} ${{ secrets.PRODUCTION_SSH_USERNAME }}@${{ secrets.PRODUCTION_SSH_HOST }} "cd /home/pmi-admin/pmi.moscow.club && docker login ghcr.io -u $GITHUB_ACTOR -p ${{ secrets.TOKEN }} && docker pull ghcr.io/toptuk/pmiclub:$GITHUB_SHA && docker-compose -f docker-compose.production.yml --env-file=./club/.env up -d && docker system prune --all --force"
...
  • Задаем параметр SSH_KEY_PATH = /tmp/ssh_key
  • В первой строке run в файл SSH_KEY_PATH записывается значение некоторого параметра secrets.PRODUCTION_SSH_KEY.
  • Во второй строке run осуществляется копирование файла .env по ssh с использованием файла env.SSH_KEY_PATH (см. "-i ${{ env.SSH_KEY_PATH }}") на сервер secrets.PRODUCTION_SSH_HOST от имени пользователя secrets.PRODUCTION_SSH_USERNAME в файл /home/pmi-admin/pmi.moscow.club/club/.env
Файл .env генерируется Action скриптом командой: run: export | grep "secret_" | sed "s/declare -x secret_//" > .env
  • В третьей строке run осуществляется копирование файла docker-compose.production.yml по ssh аналогично предыдущему пункту.
  • В четвертой строке осуществляется подключение к серверу по ssh, переход в директорию Клуба, логин в GitHub Packages, загрузка образа Клуба, потом запуск клуба с параметрами "-f docker-compose.production.yml --env-file=./club/.env". Потом вызывается команда "docker system prune --all --force", которая удаляет лишние образы и volumes.

Создаем SSH-ключи для подключения к Deploy серверу

Для деплоя Клуба мне помогла статья: https://zellwk.com/blog/github-actions-deploy/

Переходим в директорию "~/.ssh":

cd ~/.ssh

Выполняем команды для генерации SSH ключей:

ssh-keygen -t rsa -b 4096 -C "your_email@example.com"

В процессе выполнения команды будет запрошено указание название файла и задание пароля:

  • Рекомендуется вместо файла по умолчанию (id_rsa) указать что-то другое, например, "github-actions"
  • Пароль надо оставить пустым.

В результате будут созданы файлы ssh ключей:

Нужно добавить публичный ключ в файл authorized_keys. Для этого выполним команду:

cat github-actions.pub >> ~/.ssh/authorized_keys

Теперь добавим новый секрет PRODUCTION_SSH_KEY в секреты репозитария Клуба:

cat github-actions

Скопируем содержимое github-actions в значение секрета PRODUCTION_SSH_KEY репозитория Клуба.

Напомню, что значение данного параметра записывается в файл SSH_KEY_PATH: /tmp/ssh_key нашего Action'а deploy.yaml.

Указываем имя пользователя для подключения к серверу по SSH

Самый простой способ узнать имя пользователя для подключения к серверу это выполнить команду whoami:

Нужно в секрете PRODUCTION_SSH_USERNAME репозитария вашего Клуба указать значение имени пользователя, с которыми будет осуществляться подключение к SSH.

Создадим еще один секрет - PRODUCTION_SSH_HOST, в который запишем IP-адрес сервера Клуба.

Делаем Pull request в master бранч

До сих пор, все изменения которые мы делали для Клуба должны были сделаны и закоммичены в бранч Dev репозитария GitHub. Настало время сделать Pull Request в master бранч.

Для этого переходим во вкладку Pull requests и нажимаем на кнопку New pull request:

Выбираем правильные бранчи! Это важно, т.к. я несколько раз ошибался и делал PR'ы в master бранч Vas3k'а (прошу прощения! :)

  • В левой части выбираем ваше репозитарий, бранч master
  • В правой части выбираем бранч dev

GitHub должен подсказать, что Pull Request не содержит конфликтов, можно делать объединение (Merge). Создаем PR и после выполняем Merge, даже принудительный.

Отлично! Тут должны синхронизировать ветки dev с master.

Создаем директорию Клуба на сервере

Первое, что мы сделаем - это узнаем текущую директорию. Выполним команду pwd. У меня это "/home/pmi-admin".

Клонируем репозитарий Клуба на сервер. Выполним команду:

git clone https://<TOKEN>@github.com/<username>/<clubrepo>.git
  • <TOKEN> - ваш токен для репозитария
  • <username> - ваш никнейм в GitHub. У меня это "toptuk"
  • <clubrepo> - название репозитария Клуба. У меня это "pmiclub"

В итоге, на сервере должна быть создана директория вашего Клуба:

Теперь в в вашем файле deploy.yml актуализируем пути до Клуба. У меня это "/home/pmi-admin/pmi.moscow.club". У вас должно быть что-то свое.

Заключение

Почувствуйте себя Шерстяным волчарой, вы МОЛОДЕЦ!

Для запуска Клуба нам осталось:

  • Настроить обратный прокси для Клуба.
  • Запустить Клуба на сервере вручную через создание .env файла в директории club. (Команда кому не терпится и он знает, что делает "docker-compose -f docker-compose.production.yml up -d")
  • Создать первого пользователя Администратора (см. 2 часть). Подключить для него Телеграммное бота.
  • Попробовать публикацию Клуба с помощью GitHub Action deploy.yml.

Но! Обо всем этом мы поговорим в следующей статье :) Всем Meow! ❤️