CI/CD en accións de Github para un proxecto Flask+Angular
Neste artigo, compartirei a miña experiencia na configuración de CI/CD usando o Panel de control de Plesk e as accións de Github. Hoxe aprenderemos a implementar un proxecto sinxelo co nome sinxelo "Helloworld". Está escrito no framework Flask Python, con traballadores de Celery e unha interface Angular 8.
Na primeira parte do artigo, analizaremos o noso proxecto e as súas partes. No segundo, descubriremos como configurar Plesk e instalar as extensións e compoñentes necesarios (DB, RabbitMQ, Redis, Docker, etc.).
Na terceira parte, finalmente descubriremos como configurar unha canalización para implementar o noso proxecto nun servidor nun ambiente de desenvolvemento e produción. E despois lanzaremos o sitio no servidor.
E si, esquecín presentarme. Chámome Oleg Borzov, son un programador fullstack no equipo de CRM para xestores de hipotecas de Domclick.
Descrición xeral do proxecto
En primeiro lugar, vexamos dous repositorios de proxectos - backend e front - e repasemos o código.
Fondo: frasco + apio
Para a parte traseira, tomei un grupo que é bastante popular entre os desenvolvedores de Python: o framework Flask (para a API) e Celery (para a cola de tarefas). SQLAchemy úsase como ORM. O alambic úsase para as migracións. Para validación JSON en controladores - Marshmallow.
В repositorios hai un ficheiro Readme.md cunha descrición detallada da estrutura e instrucións para executar o proxecto.
docker con dous Dockerfiles (base.dockerfile para construír unha imaxe base que raramente cambia e Dockerfile para conxuntos principais);
.env_files - con ficheiros con variables de ambiente para diferentes ambientes.
Hai catro ficheiros docker-compose na raíz do proxecto:
docker-compose.local.db.yml crear unha base de datos local para o desenvolvemento;
docker-compose.local.workers.yml para a crianza local do traballador, base de datos, Redis e RabbitMQ;
docker-compose.test.yml para realizar probas durante a implantación;
docker-compose.yml para o despregamento.
E o último cartafol que nos interesa... .ci-cd. Contén scripts de shell para a súa implantación:
deploy.sh — Lanzamento da migración e despregamento. Execútase no servidor despois de construír e executar probas en Github Actions;
rollback.sh - retrotraer os contedores á versión anterior da montaxe;
curl_tg.sh - envío de notificacións de implantación a Telegram.
Frontend en Angular
Repositorio con fronte moito máis sinxelo que o de Beck. A fronte consta de tres páxinas:
Páxina principal cun formulario para enviar correo electrónico e un botón de saída.
Páxina de inicio de sesión.
Páxina de rexistro.
A páxina principal parece ascética:
Hai dous ficheiros na raíz Dockerfile и docker-compose.yml, así como o cartafol coñecido .ci-cd con un pouco menos de scripts que no repositorio posterior (elimináronse scripts para realizar probas).
Comezando un proxecto en Plesk
Comecemos configurando Plesk e creando unha subscrición para o noso sitio.
Instalación de extensións
En Plesk, necesitamos catro extensións:
Docker para xestionar e mostrar visualmente o estado dos contedores no panel de administración de Plesk;
Git para configurar o paso de implantación no servidor;
Let's Encrypt para xerar (e renovar automaticamente) certificados TLS gratuítos;
Firewall para configurar o filtrado do tráfico entrante.
Pode instalalos a través do panel de administración de Plesk na sección Extensións:
Non consideraremos a configuración detallada das extensións, a configuración predeterminada servirá para os nosos fins de demostración.
Crea unha subscrición e un sitio
A continuación, necesitamos crear unha subscrición para o noso sitio web helloworld.ru e engadir alí o subdominio dev.helloworld.ru.
Cree unha subscrición para o dominio helloworld.ru e especifique o contrasinal de inicio de sesión para o usuario do sistema:
Marque a caixa na parte inferior da páxina Protexe o dominio con Let's Encryptse queremos configurar HTTPS para o sitio:
A continuación, nesta subscrición, crea un subdominio dev.helloworld.ru (para o que tamén podes emitir un certificado TLS gratuíto):
Instalación de compoñentes do servidor
Temos un servidor con OS Debian Stretch 9.12 e panel de control instalado Plesk Obsidian 18.0.27.
Necesitamos instalar e configurar para o noso proxecto:
PostgreSQL (no noso caso, haberá un servidor con dúas bases de datos para entornos de desenvolvemento e produción).
RabbitMQ (mesmo, mesma instancia con vhosts diferentes para ambientes).
Dúas instancias de Redis (para entornos de desenvolvemento e produción).
Rexistro de Docker (para o almacenamento local de imaxes de Docker construídas).
IU para o rexistro de Docker.
PostgreSQL
Plesk xa vén con PostgreSQL DBMS, pero non a última versión (no momento de escribir Plesk Obsidian apoiado versións de Postgres 8.4–10.8). Queremos a última versión para a nosa aplicación (12.3 no momento de escribir este artigo), polo que instalarémola manualmente.
Hai moitas instrucións detalladas para instalar Postgres en Debian na rede (exemplo), así que non os describirei en detalle, só darei os comandos:
Tendo en conta que PostgreSQL ten unha configuración predeterminada bastante mediocre, é necesario corrixir a configuración. Isto axudaranos calculadora: necesitas controlar os parámetros do teu servidor e substituír a configuración do ficheiro /etc/postgresql/12/main/postgresql.confaos ofrecidos. Cabe sinalar aquí que tales calculadoras non son unha bala máxica e que a base debería axustarse con máis precisión, en función do seu hardware, aplicación e complexidade de consulta. Pero isto é suficiente para comezar.
Ademais dos axustes propostos pola calculadora, tamén cambiamos postgresql.confo porto predeterminado 5432 a outro (no noso exemplo - 53983).
Despois de cambiar o ficheiro de configuración, reinicie postgresql-server co comando:
service postgresql restart
Instalamos e configuramos PostgreSQL. Agora imos crear unha base de datos, usuarios para ambientes de desenvolvemento e produción, e darlle aos usuarios dereitos para xestionar a base de datos:
$ 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
CoelloMQ
Pasemos á instalación de RabbitMQ, un corredor de mensaxes para Celery. Instalalo en Debian é bastante sinxelo:
Agora imos instalar e configurar o último compoñente para a nosa aplicación - Redis. Usarase como backend para almacenar os resultados das tarefas de Celery.
Crearemos dous contedores Docker con Redis para entornos de desenvolvemento e produción usando a extensión Docker para Plesk.
Imos a Plesk, imos á sección Extensións, buscamos a extensión Docker e instalamos (necesitamos unha versión gratuíta):
Vaia á extensión instalada, busque a imaxe a través da busca redis bitnami e instala a última versión:
Entramos no contedor descargado e axustamos a configuración: especificamos o porto, o tamaño máximo de RAM asignado, o contrasinal nas variables de ambiente e montamos o volume:
Realizamos os pasos 2-3 para o contenedor de produtos, na configuración só cambiamos os parámetros: porto, contrasinal, tamaño da RAM e camiño ao cartafol de volumes do servidor:
Rexistro Docker
Ademais dos servizos básicos, sería bo poñer o teu propio repositorio de imaxes Docker no servidor. Afortunadamente, agora o espazo do servidor é bastante barato (sen dúbida máis barato que unha subscrición a DockerHub) e o proceso de configuración dun repositorio privado é moi sinxelo.
Creemos dous subdominios en Plesk na nosa subscrición: docker.helloworld.ru e docker-ui.helloworld.ru, e configuremos os certificados Let's Encrypt para eles.
Engade o ficheiro ao cartafol do subdominio docker.helloworld.ru docker-compose.yml con contido coma este:
E necesitamos redirixir Nginx aos nosos contedores. Isto pódese facer a través de Plesk.
Deben realizarse os seguintes pasos para os subdominios docker.helloworld.ru e docker-ui.helloworld.ru:
Na sección Ferramentas Dev ir ao noso sitio Regras do proxy de Docker:
E engade unha regra para proxy o tráfico entrante ao noso contedor:
Comprobamos que podemos iniciar sesión no noso contedor desde a máquina local:
$ 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
Comprobemos tamén o funcionamento do subdominio docker-ui.helloworld.ru:
Cando fas clic en Explorar repositorios, o navegador mostrará unha xanela de autorización na que terás que introducir o nome de usuario e o contrasinal do repositorio. Despois diso, trasladarémonos a unha páxina cunha lista de repositorios (polo momento, estará baleira para ti):
Apertura de portos en Plesk Firewall
Despois de instalar e configurar os compoñentes, necesitamos abrir portos para que os compoñentes sexan accesibles desde os contedores Docker e a rede externa.
Vexamos como facelo usando a extensión Firewall para Plesk que instalamos anteriormente.
Ir a Ferramentas e configuración > Configuración > Firewall:
Ir a Modificar as regras do Firewall de Plesk > Engadir unha regra personalizada e abra os seguintes portos TCP para a subrede Docker (172.0.0.0 / 8):
RabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
Redis: 32785, 32786
Tamén engadiremos unha regra que abrirá os portos PostgreSQL e os paneis de xestión de RabbitMQ ao mundo exterior:
Aplica as regras usando o botón Aplicar cambios:
Configurando CI/CD en Github Actions
Pasemos á parte máis interesante: configurar unha canalización de integración continua e entregar o noso proxecto ao servidor.
Esta canalización constará de dúas partes:
construír unha imaxe e realizar probas (para o backend) - no lado de Github;
executando migracións (para o backend) e despregando contedores no servidor.
Implementar en Plesk
Ocupémonos primeiro do segundo punto (porque o primeiro depende del).
Configuraremos o proceso de implantación usando a extensión Git para Plesk.
Considere un exemplo cun ambiente Prod para un repositorio de backend.
Imos á subscrición do noso sitio web de Helloworld e imos á subsección de Git:
Insira unha ligazón ao noso repositorio Github no campo "Repositorio Git remoto" e cambia o cartafol predeterminado httpdocs a outro (p. ex. /httpdocs/hw_back):
Copia a chave pública SSH do paso anterior e engadir está na configuración de Github.
Fai clic en Aceptar na pantalla no paso 2, despois de que seremos redirixidos á páxina do repositorio en Plesk. Agora necesitamos configurar o repositorio para que se actualice nos commits na rama mestra. Para iso, vai a Configuración do repositorio e gardar o valor Webhook URL (necesitarémolo máis tarde cando configuremos Github Actions):
No campo Accións da pantalla do parágrafo anterior, introduza o script para iniciar a implementación:
cd {REPOSITORY_ABSOLUTE_PATH}
.ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID}
en que:
{REPOSITORY_ABSOLUTE_PATH} - ruta ao cartafol prod do repositorio de backend no servidor; {ENV} - ambiente (dev/prod), no noso caso prod; {DOCKER_REGISTRY_HOST} - o anfitrión do noso repositorio docker {TG_BOT_TOKEN} — Token de bot de Telegram; {TG_CHAT_ID} — ID do chat/canle para enviar notificacións.
Exemplo de guión:
cd /var/www/vhosts/helloworld.ru/httpdocs/hw_back/
.ci-cd/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890
Engade un usuario da nosa subscrición ao grupo Docker (para que poida xestionar contedores):
sudo usermod -aG docker helloworld_admin
O ambiente de desenvolvemento para o repositorio de backend e o frontend confírmanse da mesma forma.
Canalización de implantación en Github Actions
Pasemos a configurar a primeira parte da nosa canalización de CI/CD en Github Actions.
Pero antes de analizalo, imos cubrir as variables secretas que necesitamos en Github. Para iso, vai a Configuración -> Segredos:
DOCKER_REGISTRY - o anfitrión do noso repositorio Docker (docker.helloworld.ru);
DOCKER_LOGIN - iniciar sesión no repositorio de Docker;
DOCKER_PASSWORD - contrasinal para el;
DEPLOY_HOST — host onde o panel de administración de Plesk está dispoñible (exemplo: olaworld.com: 8443 ou 123.4.56.78:8443);
DEPLOY_BACK_PROD_TOKEN - un token para a implantación no repositorio de produtos no servidor (obtemos en Implementación en Plesk, p. 4);
DEPLOY_BACK_DEV_TOKEN - token para a súa implantación no repositorio de desenvolvemento no servidor.
O proceso de implantación é sinxelo e consta de tres pasos principais:
construír e publicar a imaxe no noso repositorio;
realizar probas nun contedor baseado nunha imaxe recén construída;
despregamento no ambiente desexado dependendo da rama (dev/master).
Interface
O ficheiro deploy.yml para o repositorio frontal pouco diferente ao de Beck. Falta un paso para executar probas e cambia os nomes dos tokens para a súa implantación. Por certo, os segredos para o repositorio frontal deben cubrirse por separado.
Configuración do sitio
Proxy de tráfico a través de Nginx
Ben, chegamos ao final. Só queda configurar o proxy do tráfico entrante e saínte ao noso contedor a través de Nginx. Xa cubrimos este proceso no paso 5 da configuración do Rexistro de Docker. O mesmo debe repetirse para as partes traseira e frontal en ambientes de desenvolvemento e produción.
Vou proporcionar capturas de pantalla da configuración.
motor
Interface
Importante aclaración. Todos os URL serán enviados ao contenedor frontend, excepto os que comezan por /api/ - estarán aproximados ao recipiente traseiro (así no contedor traseiro, todos os manipuladores deben comezar /api/).
Resultados de
Agora o noso sitio debería estar dispoñible en helloworld.ru e dev.helloworld.ru (entornos de produción e desenvolvemento, respectivamente).
En total, aprendemos a preparar unha aplicación sinxela en Flask e Angular e a configurar unha canalización en Github Actions para implementala nun servidor que executa Plesk.
Vou duplicar as ligazóns aos repositorios co código: backend, frontend.