CI/CD no Github Actions para um projeto Flask+Angular
Neste artigo, compartilharei minha experiência de configuração de CI/CD usando o Plesk Control Panel e o Github Actions. Hoje vamos aprender como implantar um projeto simples com o nome descomplicado "Helloworld". Ele é escrito na estrutura Flask Python, com trabalhadores Celery e um frontend Angular 8.
Na primeira parte do artigo, veremos nosso projeto e suas partes. Na segunda, descobriremos como configurar o Plesk e instalar as extensões e componentes necessários (DB, RabbitMQ, Redis, Docker, etc.).
Na terceira parte, finalmente descobriremos como configurar um pipeline para implantar nosso projeto em um servidor em um ambiente de desenvolvimento e produção. E então vamos lançar o site no servidor.
E sim, esqueci de me apresentar. Meu nome é Oleg Borzov, sou desenvolvedor fullstack na equipe de CRM para gerentes de hipotecas da Domclick.
Visão geral do projeto
Primeiro, vamos olhar para dois repositórios de projeto - back-end e front-end - e examinar o código.
Back-end: Frasco + Aipo
Para a parte de trás, peguei um monte bastante popular entre os desenvolvedores Python: a estrutura Flask (para a API) e Celery (para a fila de tarefas). SQLAchemy é usado como ORM. O alambique é usado para migrações. Para validação JSON em handles - Marshmallow.
В repositórios existe um arquivo Readme.md com uma descrição detalhada da estrutura e instruções para executar o projeto.
docker com dois Dockerfiles (base.dockerfile para construir uma imagem base que raramente muda e Dockerfile para montagens principais);
.env_files - com arquivos com variáveis de ambiente para diferentes ambientes.
Existem quatro arquivos docker-compose na raiz do projeto:
docker-compose.local.db.yml levantar um banco de dados local para desenvolvimento;
docker-compose.local.workers.yml para levantamento local do worker, banco de dados, Redis e RabbitMQ;
docker-compose.test.yml para executar testes durante a implantação;
docker-compose.yml para implantação.
E a última pasta em que estamos interessados - .ci-cd. Ele contém scripts de shell para implantação:
deploy.sh — lançamento da migração e implantação. Executa no servidor após construir e executar testes no Github Actions;
rollback.sh - reversão de contêineres para a versão anterior do assembly;
curl_tg.sh - envio de notificações de implantação para o Telegram.
Front-end em Angular
Repositório com frente muito mais simples do que o de Beck. A frente é composta por três páginas:
Página principal com formulário para envio de e-mail e botão de saída.
Página de login.
Página de registro.
A página principal parece ascética:
Existem dois arquivos na raiz Dockerfile и docker-compose.yml, bem como a pasta familiar .ci-cd com um pouco menos de scripts do que no repositório anterior (scripts removidos para execução de testes).
Iniciando um projeto no Plesk
Vamos começar configurando o Plesk e criando uma assinatura para nosso site.
Instalando extensões
No Plesk, precisamos de quatro extensões:
Docker para gerenciar e exibir visualmente o status dos contêineres no painel de administração do Plesk;
Git configurar a etapa de implantação no servidor;
Let's Encrypt para gerar (e renovar automaticamente) certificados TLS gratuitos;
Firewall para configurar a filtragem do tráfego de entrada.
Você pode instalá-los através do painel de administração do Plesk na seção Extensões:
Não vamos considerar as configurações detalhadas para extensões, as configurações padrão servirão para nossos propósitos de demonstração.
Crie uma assinatura e um site
Em seguida, precisamos criar uma assinatura para nosso site helloworld.ru e adicionar o subdomínio dev.helloworld.ru lá.
Crie uma assinatura para o domínio helloworld.ru e especifique a senha de login para o usuário do sistema:
Marque a caixa na parte inferior da página Proteja o domínio com Let's Encryptse quisermos configurar HTTPS para o site:
Em seguida, nesta assinatura, crie um subdomínio dev.helloworld.ru (para o qual você também pode emitir um certificado TLS gratuito):
Instalando componentes do servidor
Temos um servidor com SO Debian Stretch 9.12 e painel de controle instalado Plesk Obsidiana 18.0.27.
Precisamos instalar e configurar para o nosso projeto:
PostgreSQL (no nosso caso, haverá um servidor com dois bancos de dados para ambientes dev e prod).
RabbitMQ (mesmo, mesma instância com diferentes vhosts para ambientes).
Duas instâncias do Redis (para ambientes de desenvolvimento e produção).
Docker Registry (para armazenamento local de imagens Docker construídas).
Interface do usuário para o registro do Docker.
PostgreSQL
O Plesk já vem com o PostgreSQL DBMS, mas não a versão mais recente (no momento em que escrevi o Plesk Obsidian suportado Postgres versões 8.4–10.8). Queremos a versão mais recente do nosso aplicativo (12.3 no momento em que este livro foi escrito), então vamos instalá-lo manualmente.
Existem muitas instruções detalhadas para instalar o Postgres no Debian na rede (exemplo), então não vou descrevê-los em detalhes, apenas darei os comandos:
Considerando que o PostgreSQL possui configurações padrão bastante medíocres, é necessário corrigir a configuração. Isso vai nos ajudar calculadora: você precisa dirigir nos parâmetros do seu servidor e substituir as configurações no arquivo /etc/postgresql/12/main/postgresql.confaos oferecidos. Deve-se observar aqui que essas calculadoras não são mágicas e a base deve ser ajustada com mais precisão, com base no hardware, no aplicativo e na complexidade da consulta. Mas isso é o suficiente para começar.
Além das configurações propostas pela calculadora, também alteramos postgresql.confa porta padrão 5432 para outra (no nosso exemplo - 53983).
Após alterar o arquivo de configuração, reinicie o postgresql-server com o comando:
service postgresql restart
Instalamos e configuramos o PostgreSQL. Agora vamos criar um banco de dados, usuários para ambientes de desenvolvimento e produção, e dar aos usuários direitos para gerenciar o banco de dados:
$ 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
Vamos instalar o RabbitMQ, um corretor de mensagens para Celery. Instalá-lo no Debian é bem simples:
Agora vamos instalar e configurar o último componente do nosso aplicativo - Redis. Ele será usado como um back-end para armazenar os resultados das tarefas do Celery.
Levantaremos dois containers Docker com Redis para ambientes dev e prod usando a extensão Docker para Plesk.
Vamos ao Plesk, vamos à seção Extensões, procuramos a extensão Docker e a instalamos (precisamos de uma versão gratuita):
Vá para a extensão instalada, encontre a imagem através da pesquisa redis bitnami e instale a versão mais recente:
Entramos no contêiner baixado e ajustamos a configuração: especifique a porta, o tamanho máximo de RAM alocado, a senha nas variáveis de ambiente e monte o volume:
Executamos as etapas 2 a 3 para o contêiner prod, nas configurações alteramos apenas os parâmetros: porta, senha, tamanho da RAM e caminho para a pasta do volume no servidor:
Registro Docker
Além dos serviços básicos, seria bom colocar seu próprio repositório de imagens do Docker no servidor. Felizmente, o espaço do servidor agora é bastante barato (certamente mais barato do que uma assinatura do DockerHub) e o processo de configuração de um repositório privado é muito simples.
Vamos criar dois subdomínios no Plesk em nossa assinatura: docker.helloworld.ru e docker-ui.helloworld.ru e configurar os certificados Let's Encrypt para eles.
Adicione o arquivo à pasta do subdomínio docker.helloworld.ru docker-compose.yml com conteúdo como este:
E precisamos redirecionar o Nginx para nossos contêineres. Isso pode ser feito através do Plesk.
As etapas a seguir precisam ser executadas para os subdomínios docker.helloworld.ru e docker-ui.helloworld.ru:
Na seção Dev Tools nosso site ir para Regras de proxy do Docker:
E adicione uma regra para fazer proxy do tráfego de entrada para nosso contêiner:
Verificamos se podemos fazer login em nosso contêiner a partir da 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
Vamos também verificar o funcionamento do subdomínio docker-ui.helloworld.ru:
Ao clicar em Procurar repositórios, o navegador exibirá uma janela de autorização onde será necessário inserir o nome de usuário e a senha do repositório. Após isso, seremos redirecionados para uma página com uma lista de repositórios (por enquanto, ela estará vazia para você):
Abrindo portas no Firewall Plesk
Depois de instalar e configurar os componentes, precisamos abrir portas para que os componentes sejam acessíveis a partir de contêineres Docker e da rede externa.
Vamos ver como fazer isso usando a extensão do Firewall para Plesk que instalamos anteriormente.
Ir para Ferramentas e configurações > Configurações > Firewall:
Ir para Modificar regras de firewall do Plesk > Adicionar regra personalizada e abra as seguintes portas TCP para a sub-rede Docker (172.0.0.0 / 8):
CoelhoMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
Redes: 32785, 32786
Também adicionaremos uma regra que abrirá portas PostgreSQL e painéis de gerenciamento RabbitMQ para o mundo externo:
Aplique as regras usando o botão Aplicar alterações:
Configurando CI/CD no Github Actions
Vamos à parte mais interessante - configurar um pipeline de integração contínua e entregar nosso projeto ao servidor.
Este pipeline será composto por duas partes:
construindo uma imagem e executando testes (para o backend) - no lado do Github;
executando migrações (para o back-end) e implantando contêineres - no servidor.
Implantar no Plesk
Vamos lidar primeiro com o segundo ponto (porque o primeiro depende disso).
Vamos configurar o processo de implantação usando a extensão Git para Plesk.
Considere um exemplo com um ambiente Prod para um repositório Backend.
Vamos para a assinatura do nosso site Helloworld e vamos para a subseção Git:
Insira um link para nosso repositório Github no campo "Repositório Git Remoto" e altere a pasta padrão httpdocs para outro (ex. /httpdocs/hw_back):
Copie a chave pública SSH da etapa anterior e adicionar está nas configurações do Github.
Clique em OK na tela do passo 2, após o qual seremos redirecionados para a página do repositório no Plesk. Agora precisamos configurar o repositório para ser atualizado nos commits do branch master. Para fazer isso, vá para Configurações do repositório e salve o valor Webhook URL (vamos precisar dele mais tarde ao configurar as ações do Github):
No campo Ações da tela do parágrafo anterior, insira o script para iniciar a implantação:
cd {REPOSITORY_ABSOLUTE_PATH}
.ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID}
em que:
{REPOSITORY_ABSOLUTE_PATH} - caminho para a pasta prod do repositório back-end no servidor; {ENV} - ambiente (dev/prod), no nosso caso prod; {DOCKER_REGISTRY_HOST} - o host do nosso repositório docker {TG_BOT_TOKEN} — Token do bot do Telegram; {TG_CHAT_ID} — ID do chat/canal para envio de notificações.
Exemplo de roteiro:
cd /var/www/vhosts/helloworld.ru/httpdocs/hw_back/
.ci-cd/deploy.sh dev docker.helloworld.ru docker_user docker_password 12345678:AAbcdEfghCH1vGbCasdfSAs0K5PALDsaw -1001234567890
Adicione um usuário de nossa assinatura ao grupo Docker (para que ele possa gerenciar contêineres):
sudo usermod -aG docker helloworld_admin
O ambiente de desenvolvimento para o repositório de back-end e o front-end são configurados da mesma maneira.
Pipeline de implantação no Github Actions
Vamos configurar a primeira parte do nosso pipeline de CI/CD no Github Actions.
Mas antes de analisá-lo, vamos preencher as variáveis secretas que precisamos no Github. Para fazer isso, vá para Configurações -> Segredos:
DOCKER_REGISTRY - o host do nosso repositório Docker (docker.helloworld.ru);
DOCKER_LOGIN - faça login no repositório do Docker;
DOCKER_PASSWORD - senha para ele;
DEPLOY_HOST — host onde o painel de administração do Plesk está disponível (exemplo: helloworld.com: 8443 ou 123.4.56.78:8443);
DEPLOY_BACK_PROD_TOKEN - um token para implantação no repositório prod no servidor (obtemos em Implantação no Plesk p. 4);
DEPLOY_BACK_DEV_TOKEN - token para implantação no repositório dev no servidor.
O processo de implantação é simples e consiste em três etapas principais:
construir e publicar a imagem em nosso repositório;
executar testes em um contêiner com base em uma imagem recém-criada;
implantação no ambiente desejado dependendo da ramificação (dev/master).
Frontend
O arquivo deploy.yml para o repositório frontal pouco diferente do de Beck. Falta uma etapa com execução de testes e alteração dos nomes dos tokens para implantação. A propósito, os segredos do repositório frontal precisam ser preenchidos separadamente.
Configuração do site
Proxy de tráfego através do Nginx
Bem, chegamos ao fim. Resta apenas configurar o proxy do tráfego de entrada e saída para nosso contêiner por meio do Nginx. Já cobrimos esse processo na etapa 5 da configuração do Docker Registry. O mesmo deve ser repetido para as partes traseira e frontal em ambientes de desenvolvimento e produção.
Fornecerei capturas de tela das configurações.
Backend
Frontend
Esclarecimento importante. Todos os URLs terão proxy para o contêiner de front-end, exceto aqueles que começam com /api/ - eles serão proxy para o contêiner traseiro (assim no contêiner traseiro, todos os manipuladores devem começar com /api/).
Resultados de
Agora nosso site deve estar disponível em helloworld.ru e dev.helloworld.ru (prod- e dev-environments, respectivamente).
No total, aprendemos como preparar um aplicativo simples em Flask e Angular e configurar um pipeline no Github Actions para implementá-lo em um servidor executando o Plesk.