CI/CD no Github Actions para um projeto Flask+Angular

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.

Links para repositórios: Processo interno, front-end.

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.

API de Web Parts bastante simples, consiste em 6 canetas:

  • /ping - para verificar a disponibilidade;
  • trata de registro, autorização, desautorização e obtenção de um usuário autorizado;
  • um identificador de e-mail que coloca uma tarefa na fila do aipo.

parte de aipo ainda mais fácil, só há um problema send_mail_task.

Na pasta / conf existem duas subpastas:

  • 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:

CI/CD no Github Actions para um projeto Flask+Angular
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:

CI/CD no Github Actions para um projeto Flask+Angular
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á.

  1. Crie uma assinatura para o domínio helloworld.ru e especifique a senha de login para o usuário do sistema:

    CI/CD no Github Actions para um projeto Flask+Angular
    Marque a caixa na parte inferior da página Proteja o domínio com Let's Encryptse quisermos configurar HTTPS para o site:

    CI/CD no Github Actions para um projeto Flask+Angular

  2. Em seguida, nesta assinatura, crie um subdomínio dev.helloworld.ru (para o qual você também pode emitir um certificado TLS gratuito):

    CI/CD no Github Actions para um projeto Flask+Angular

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:

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

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:

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

Após a instalação, precisamos criar vhosts, usuários e conceder os direitos necessários:

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

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.

  1. Vamos ao Plesk, vamos à seção Extensões, procuramos a extensão Docker e a instalamos (precisamos de uma versão gratuita):

    CI/CD no Github Actions para um projeto Flask+Angular

  2. Vá para a extensão instalada, encontre a imagem através da pesquisa redis bitnami e instale a versão mais recente:

    CI/CD no Github Actions para um projeto Flask+Angular

  3. 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:

    CI/CD no Github Actions para um projeto Flask+Angular

  4. 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:

    CI/CD no Github Actions para um projeto Flask+Angular

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.

Queremos ter:

Para fazer isso:

  1. 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.
  2. Adicione o arquivo à pasta do subdomínio docker.helloworld.ru docker-compose.yml com conteúdo como este:
    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'
    

  3. Sob SSH, iremos gerar o arquivo .htpasswd para autorização Basic no repositório Docker:
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Recolher e levantar recipientes:
    docker-compose up -d
  5. 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:

CI/CD no Github Actions para um projeto Flask+Angular
E adicione uma regra para fazer proxy do tráfego de entrada para nosso contêiner:

CI/CD no Github Actions para um projeto Flask+Angular

  1. 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
  2. Vamos também verificar o funcionamento do subdomínio docker-ui.helloworld.ru:

    CI/CD no Github Actions para um projeto Flask+Angular
    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ê):

    CI/CD no Github Actions para um projeto Flask+Angular

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.

  1. Ir para Ferramentas e configurações > Configurações > Firewall:
    CI/CD no Github Actions para um projeto Flask+Angular
  2. 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

    CI/CD no Github Actions para um projeto Flask+Angular

  3. Também adicionaremos uma regra que abrirá portas PostgreSQL e painéis de gerenciamento RabbitMQ para o mundo externo:

    CI/CD no Github Actions para um projeto Flask+Angular

  4. Aplique as regras usando o botão Aplicar alterações:

    CI/CD no Github Actions para um projeto Flask+Angular

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.

  1. Vamos para a assinatura do nosso site Helloworld e vamos para a subseção Git:

    CI/CD no Github Actions para um projeto Flask+Angular

  2. 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):

    CI/CD no Github Actions para um projeto Flask+Angular

  3. Copie a chave pública SSH da etapa anterior e adicionar está nas configurações do Github.
  4. 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):

    CI/CD no Github Actions para um projeto Flask+Angular

  5. 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
  6. 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.

Backend

O pipeline é descrito em arquivo deploy.yml.

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

CI/CD no Github Actions para um projeto Flask+Angular

Frontend

CI/CD no Github Actions para um projeto Flask+Angular
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.

Vou duplicar os links para os repositórios com o código: Processo interno, front-end.

Fonte: habr.com

Adicionar um comentário