
У гэтым артыкуле я падзялюся сваім досведам налады CI/CD з выкарыстаннем панэлі кіравання Plesk і Github Actions. Сёння будзем вучыцца дэплоіць прасценькі праект з немудрагелістай назвай «Helloworld». Ён напісаны на Python-фрэймворку Flask, з воркерамі на Celery і франтэндам на Angular 8.
Спасылкі на рэпазітары: , .
У першай частцы артыкула мы паглядзім на наш праект і яго часткі. У другой – разбярэмся, як наладзіць Plesk і ўсталяваць неабходныя пашырэнні і кампаненты (БД, RabbitMQ, Redis, Docker і г.д.).
У трэцяй частцы мы, нарэшце, разбярэмся, як наладзіць пайплайн для дэплою нашага праекта на сервер у dev-і prod-асяроддзе. А потым запусцім сайт на серверы.
І так, забыўся прадставіцца. Мяне клічуць Алег Барзоў, я fullstack-распрацоўшчык у камандзе CRM для мэнэджэраў іпатэчнага крэдытавання ў Домклік.
Агляд праекту
Для пачатку разгледзім два рэпазітары праекта - бэкенда і фронту - і прабяжымся па кодзе.
Бэкенд-частка: Flask+Celery
Для бэк-часткі я ўзяў досыць папулярную сярод Python-распрацоўнікаў звязку: фрэймворк Flask (для API) і Celery (для чаргі задач). У якасці ORM выкарыстоўваецца SQLAchemy. Для міграцый прымяняецца Alembic. Для валідацыі JSON у ручках - Marshmallow.
В есць файл Readme.md з падрабязным апісаннем структуры і інструкцыямі для запуску праекта.
досыць немудрагелісты, складаецца з 6 ручак:
/ping- Для праверкі даступнасці;- ручкі для рэгістрацыі, аўтарызацыі, дэаўтарызацыі і атрымання аўтарызаванага карыстальніка;
- ручка для адпраўкі email, якая кладзе задачку ў чаргу Celery.
яшчэ прасцей, там усяго адна задачка send_mail_task.
У тэчцы ляжаць дзве падтэчкі:
dockerз двума Docker-файламі (base.dockerfileдля зборкі рэдка змяняецца базавай выявы іDockerfileдля асноўных зборак);.env_files- З файламі з зменнымі асяроддзі для розных асяроддзяў.
У корані праекта знаходзяцца чатыры файлы docker-compose:
docker-compose.local.db.ymlдля ўзняцця лакальнай БД для распрацоўкі;docker-compose.local.workers.ymlдля лакальнага ўзняцця воркера, БД, Redis і RabbitMQ;docker-compose.test.ymlдля прагону тэстаў пры разгортванні;docker-compose.ymlдля дэплою.
І апошняя цікавая нам тэчка - . У ёй ляжаць shell-скрыпты для разгортвання:
deploy.sh- запуск міграцыі і дэплою. Запускаецца на серверы пасля зборкі і прагону тэстаў у Github Actions;rollback.sh- Адкат кантэйнераў на папярэднюю версію зборкі;curl_tg.sh— адпраўка апавяшчэнняў аб разгортванні ў Telegram.
Франтэнд на Angular
моцна прасцей бэкаўскай. Фронт складаецца з трох старонак:
- Галоўная старонка з формай для адпраўкі email і кнопкай вынахаду.
- Старонка ўваходу.
- Старонка рэгістрацыі.
Галоўная старонка выглядае аскетычна:

У корані ляжаць два файлы Dockerfile и docker-compose.yml, а таксама знаёмая нам тэчка .ci-cd з крыху меншай колькасцю скрыптоў, чым у бэкаўскім рэпазітары (прыбраны скрыпты для запуску тэстаў).
Заводзім праект у Plesk
Пачнём з налады Plesk і стварэння падпіскі для нашага сайта.
Ўстаноўка пашырэнняў
У Plesk нам спатрэбяцца чатыры пашырэнні:
Dockerдля кіравання і візуальнага адлюстравання стану кантэйнераў у адмінцы Plesk;Gitдля настройкі кроку дэплою на серверы;Let's Encryptдля генерацыі (і аўтападаўжэння) бясплатных TLS-сертыфікатаў;Firewallдля налады фільтрацыі ўваходнага трафіку.
Усталяваць іх можна праз адмінку Plesk у падзеле Extensions:

Дэталёвую наладу пашырэнняў мы разглядаць не будзем, для нашых дэма-мэт падыдуць налады па змаўчанні.
Стварэнне падпіскі і сайта
Далей нам трэба стварыць падпіску для нашага сайта helloworld.ru і дадаць туды паддамен dev.helloworld.ru.
- Ствараем падпіску для дамена helloworld.ru і паказваем лагін-пароль для сістэмнага карыстальніка:

Унізе старонкі ставім галачку Secure the domain with Let's Encrypt, калі жадаем наладзіць HTTPS для сайта:
- Далей у гэтай падпісцы ствараем паддамен dev.helloworld.ru (для якога таксама можна выпусціць бясплатны TLS-сертыфікат):

Ўстаноўка серверных кампанентаў
У нас у наяўнасці сервер з OS Debian Расцяжка 9.12 і ўсталяванай панэллю кіравання Plesk Obsidian 18.0.27.
Нам трэба ўсталяваць і наладзіць для нашага праекту:
- PostgreSQL (у нашым выпадку будзе адзін сервер з двума БД для dev-і prod-асяроддзя).
- RabbitMQ (тое ж самае, адзін інстанс з рознымі vhosts для асяроддзяў).
- Два інстансу Redis (для dev- і prod-асяроддзя).
- Docker Registry (для лакальнага захоўвання сабраных Docker-вобразаў).
- UI-інтэрфейс для Docker registry.
PostgreSQL
У камплекце з Plesk ужо ідзе СКБД PostgreSQL, аднак не самай свежай версіі (на момант напісання артыкула Plesk Obsidian Postgres (версій 8.4–10.8). Мы ж хочам для свайго дадатку самую апошнюю версію (12.3 на момант напісання артыкула), таму будзем ставіць яе ўручную.
Падрабязных інструкцый па ўстаноўцы Postgres на Debian у сетцы поўна (), таму падрабязна апісваць іх не буду, проста прывяду каманды:
wget -q https://www.postgresql.org/media/keys/ACCC4CF8.asc -O - | sudo apt-key add -
sudo sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt/ stretch-pgdg main" >> /etc/apt/sources.list.d/pgdg.list'
sudo apt-get update
sudo apt-get install postgresql postgresql-contrib
Улічваючы, што ў PostgreSQL дастаткова пасрэдныя налады па змаўчанні, трэба абавязкова скарэктаваць канфігурацыю. У гэтым нам дапаможа : трэба убіць параметры свайго сервера і замяніць наладкі ў файле /etc/postgresql/12/main/postgresql.confна прапанаваныя. Тут варта абмовіцца, што падобныя калькулятары - не чароўная куля, і базу варта цюніць больш кропкава, зыходзячы з вашага жалеза, прыкладанні і складанасці запытаў. Але для старту гэтага дастаткова.
Акрамя прапанаваных калькулятарам налад таксама мяняем у postgresql.confпрапісаны па змаўчанні порт 5432 на іншы (у нашым прыкладзе — 53983).
Пасля змены канфігурацыйнага файла перазагружаем postgresql-server камандай:
service postgresql restart
Мы паставілі і настроілі PostgreSQL. Цяпер створым БД, карыстальнікаў для dev- і prod-асяроддзяў, і выдадзім карыстальнікам права на кіраванне БД:
$ su - postgres
postgres:~$ create database hw_dev_db_name;
CREATE DATABASE
postgres:~$ create user hw_dev_db_user with password 'hw_dev_db_password';
CREATE ROLE
postgres:~$ grant ALL privileges ON database hw_dev_db_name to hw_dev_db_user;
GRANT
postgres:~$ create database hw_prod_db_name;
CREATE DATABASE
postgres:~$ create user hw_prod_db_user with password 'hw_prod_db_password';
CREATE ROLE
postgres:~$ grant ALL privileges ON database hw_prod_db_name to hw_prod_db_user;
GRANT
RabbitMQ
Пяройдзем да ўстаноўкі RabbitMQ – брокера паведамленняў для Celery. Ставіцца ён на Debian дастаткова проста:
wget https://packages.erlang-solutions.com/erlang-solutions_1.0_all.deb
sudo dpkg -i erlang-solutions_1.0_all.deb
sudo apt-get update
sudo apt-get install erlang erlang-nox
sudo add-apt-repository 'deb http://www.rabbitmq.com/debian/ testing main'
wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -
sudo apt-get update
sudo apt-get install rabbitmq-server
Пасля ўстаноўкі нам трэба стварыць vhosts, карыстальнікаў і выдаць патрэбныя правы:
sudo rabbitmqctl add_user hw_dev_amqp_user hw_dev_amqp_password
sudo rabbitmqctl set_user_tags hw_dev_amqp_user administrator
sudo rabbitmqctl add_vhost hw_dev_vhost
sudo rabbitmqctl set_permissions -p hw_dev_vhost hw_dev_amqp_user ".*" ".*" ".*"
sudo rabbitmqctl add_user hw_prod_amqp_user hw_prod_amqp_password
sudo rabbitmqctl set_user_tags hw_prod_amqp_user administrator
sudo rabbitmqctl add_vhost hw_prod_vhost
sudo rabbitmqctl set_permissions -p hw_prod_vhost hw_prod_amqp_user ".*" ".*" ".*"
Redis
Цяпер усталюем і наладзім апошні кампанент для нашага прыкладання - Redis. Ён будзе выкарыстоўвацца як бэкенд для захоўвання вынікаў задач Celery.
Мы паднімем два Docker-кантэйнера з Redis пад dev- і prod-асяроддзя з дапамогай пашырэння Docker для Plesk.
- Заходзім у Plesk, пераходзім у падзел Пашырэння, шукаем пашырэнне Docker і ўсталёўваны яго (нам патрэбна бясплатная версія):

- Пераходзім ва ўсталяванае пашырэнне, знаходзім праз пошук выява
redis bitnamiі ставім апошнюю версію:
- Заходзім у запампаваны кантэйнер і карэктуем канфігурацыю: паказваем порт, максімальны які выдзяляецца памер АЗП, пароль у зменных асяроддзі, і які мантуецца тым:

- Выконваем крокі 2-3 для prod-кантэйнера, у наладах толькі мяняем параметры: порт, пароль, памер АЗП і шлях да тэчкі volume на серверы:

Рэестр докераў
Апроч базавых сэрвісаў было б нядрэнна паставіць на сервер уласны рэпазітар Docker-вобразаў. Балазе месца на серверах цяпер досыць таннае (ужо сапраўды танней падпіскі на DockerHub), ды і працэс усталёўкі прыватнага рэпазітара вельмі просты.
Мы хочам, каб у нас былі ўсталяваныя:
- абаронены паролем Docker-рэпазітар, даступны па паддамене ;
- UI-інтэрфейс для прагляду выяў у рэпазітары, даступны па адрасе .
Для гэтага:
- Створым у Plesk два паддамены ў нашай падпісцы: docker.helloworld.ru і docker-ui.helloworld.ru, і наладзім для іх сертыфікаты Let's Encrypt.
- У тэчку паддамена docker.helloworld.ru дадамо файл
docker-compose.ymlз такім змесцівам:version: "3" services: docker-registry: image: "registry:2" restart: always ports: - "53985:5000" environment: REGISTRY_AUTH: htpasswd REGISTRY_AUTH_HTPASSWD_REALM: basic-realm REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data volumes: - ./.docker-registry.htpasswd:/auth/.htpasswd - ./data:/data docker-registry-ui: image: konradkleine/docker-registry-frontend:v2 restart: always ports: - "53986:80" environment: VIRTUAL_HOST: '*, https://*' ENV_DOCKER_REGISTRY_HOST: 'docker-registry' ENV_DOCKER_REGISTRY_PORT: 5000 links: - 'docker-registry' - Пад SSH згенераваны файл .htpasswd для Basic-аўтарызацыі ў Docker-рэпазітары:
htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password - Збяром і паднімем кантэйнеры:
docker-compose up -d - І трэба перанакіраваць Nginx на нашы кантэйнеры. Гэта можна зрабіць праз Plesk.
Наступныя дзеянні трэба прарабіць для паддаменаў docker.helloworld.ru і docker-ui.helloworld.ru:
У раздзеле Інструменты распрацоўшчыкаў нашага сайта заходзім у Docker Proxy Rules:

І дадаем правіла для праксіравання ўваходнага трафіку ў наш кантэйнер:

- Правяраем, што можам аўтарызавацца ў нашым кантэйнеры з лакальнай машыны:
$ docker login docker.helloworld.ru -u hw_docker_admin -p hw_docker_password WARNING! Using --password via the CLI is insecure. Use --password-stdin. Login Succeeded - Таксама праверым працу паддамена docker-ui.helloworld.ru:

Пры націску на Browse repositories браўзэр выдасць акенца для аўтарызацыі, куды трэба будзе ўвесці лагін і пароль для рэпазітара. Пасля чаго нас перакіне на старонку са спісам рэпазітараў (у вас пакуль яна будзе пустой):
Адкрываем парты ў Plesk Firewall
Пасля ўстаноўкі і настройкі кампанентаў нам трэба адкрыць парты, каб кампаненты былі даступныя з Docker-кантэйнераў і знешняй сеткі.
Паглядзім, як гэта рабіць, на прыкладзе ўсталяванага намі раней пашырэнні Firewall для Plesk.
- пераходзім у Tools & Settings > Settings > Firewall:

- пераходзім у Modify Plesk Firewall Rules > Add Custom Rule і адчыняны наступныя TCP-парты для падсеткі Docker (172.0.0.0 / 8):
RabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
Redis: 32785, 32786
- Таксама дадамо правіла, якое адкрые знешняму свету парты PostgreSQL і management-панэлі RabbitMQ:

- Ужывальны правілы з дапамогай кнопкі Apply Changes:

Настройка CI/CD у Github Actions
Прыступім да самай цікавай часткі - наладзе пайплайн бесперапыннай інтэграцыі і дастаўкі нашага праекта да сервера.
Гэты пайплайн будзе складацца з дзвюх частак:
- зборка выявы і прагон тэстаў (для бэкенда) - на боку Github;
- запуск міграцый (для бэкенда) і дэплой кантэйнераў - на серверы.
Дэплой у Plesk
Разбярэмся спачатку з другім пунктам (бо ад яго залежыць першы).
Працэс дэплою мы будзем наладжваць з дапамогай пашырэння Git для Plesk.
Разгледзім прыклад з Prod асяроддзем для Backend рэпазітара.
- Заходзім у падпіску нашага сайта Helloworld і пераходзім у падраздзел Git:

- Устаўляемы ў поле «Remote Git repository» спасылку на наш Github-рэпазітар і змяняем тэчку па змаўчанні
httpdocsна іншую (напрыклад,/httpdocs/hw_back):
- Капіяваны SSH Public key з папярэдняга этапу і яго ў наладах Github.
- Націскаем ОК на экране ў пункце 2, пасля чаго нас перакідае на старонку рэпазітара ў Plesk. Цяпер нам трэба наладзіць абнаўленне рэпазітара пры комітах у галінку master. Для гэтага пераходзім у Repository Settings і захоўваем значэнне
Webhook URL(яно нам спатрэбіцца пазней пры наладзе Github Actions):
- У поле Actions на экране з папярэдняга пункта ўводны скрыпт для запуску дэплою:
cd {REPOSITORY_ABSOLUTE_PATH} .ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID}дзе:
{REPOSITORY_ABSOLUTE_PATH}- шлях да тэчкі prod backend-рэпазітара на серверы;
{ENV}- серада (dev/prod), у нашым выпадкуprod;
{DOCKER_REGISTRY_HOST}— хост нашага docker рэпазітара
{TG_BOT_TOKEN}- токен Telegram-бота;
{TG_CHAT_ID}- ID чата/канала для адпраўкі апавяшчэнняў.Прыклад скрыпту:
cd /var/www/vhosts/helloworld.ru/httpdocs/hw_back/ .ci-cd/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890 - Дадаем карыстальніка з нашай падпіскі ў групу Docker (каб ён мог кіраваць кантэйнерамі):
sudo usermod -aG docker helloworld_admin
Dev-асяроддзе для backend-рэпазітара і frontend наладжваюцца аналагічна.
Pipeline дэплою ў Github Actions
Пераходзім да налады першай часткі нашага CI/CD-пайплана ў Github Actions.
Backend
Пайплайн апісваецца ў .
Але перад яго разборам запоўнім у Github патрэбныя нам Secret-зменныя. Для гэтага пераходзім у Settings -> Secrets:
DOCKER_REGISTRY- хост нашага Docker-рэпазітара (docker.helloworld.ru);DOCKER_LOGIN— лагін да Docker-рэпазітара;DOCKER_PASSWORD- пароль да яго;DEPLOY_HOST- хост, на якім даступная адмінка Plesk (прыклад: :8443 ці :8443);DEPLOY_BACK_PROD_TOKEN- токен для дэплою ў prod-рэпазітар на серверы (мы яго атрымалі ў Разгортванне ў Plesk п. 4);DEPLOY_BACK_DEV_TOKEN- токен для дэплою ў dev-рэпазітар на серверы.
Працэс дэплою просты і складаецца з трох асноўных крокаў:
- зборка і публікацыя выявы ў нашым рэпазітары;
- запуск тэстаў у кантэйнеры на базе свежазабранай выявы;
- разгортванне ў патрэбнае асяроддзе ў залежнасці ад галіны (dev/master).
Frontend
мала чым адрозніваецца ад бэкаўскай. У ім адсутнічае крок з запускам тэстаў і мяняюцца назвы токенаў для дэплою. Сакрэты для фронт-рэпазітара, дарэчы, трэба запаўняць асобна.
Настройка сайта
Праксіраванне трафіку праз Nginx
Ну што ж, мы падышлі да канца. Засталося толькі наладзіць праксіраванне ўваходнага і выходнага трафіку ў наш кантэйнер праз Nginx. Гэты працэс мы ўжо разгледзелі ў пункце 5 наладкі Docker Registry. Тое ж самае трэба паўтарыць для бэк- і фронт-часткі ў dev-і prod-акружэннях.
Прывяду скрыны налад.
Backend

Frontend

Важнае ўдакладненне. У фронтэнд-кантэйнер будуць праксіравацца ўсе URL, акрамя якія пачынаюцца на /api/ - Яны будуць праксіраваны ў бэк-кантэйнер (таму у бэк-кантэйнеры ўсе апрацоўшчыкі павінны пачынацца з /api/).
Вынікі
Цяпер наш сайт павінен быць даступны па адрасах helloworld.ru і dev.helloworld.ru (prod- і dev-асяроддзе адпаведна).
Разам, мы даведаліся, як падрыхтаваць простае дадатак на Flask і Angular і наладзіць у Github Actions пайплайн для яго выкаткі на сервер пад кіраваннем Plesk.
Прадублірую спасылкі на рэпазітары з кодам: , .
Крыніца: habr.com
