CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

CI/CD in Github-Aktionen für ein Flask+Angular-Projekt
In diesem Artikel werde ich meine Erfahrungen mit der Einrichtung von CI/CD über das Plesk Control Panel und Github Actions teilen. Heute lernen wir, wie man ein einfaches Projekt mit dem unkomplizierten Namen „Helloworld“ bereitstellt. Es ist im Flask Python-Framework geschrieben, mit Celery-Workern und einem Angular 8-Frontend.

Links zu Repositories: Backend, Frontend.

Im ersten Teil des Artikels werden wir uns unser Projekt und seine Teile ansehen. Im zweiten Schritt erfahren Sie, wie Sie Plesk einrichten und die erforderlichen Erweiterungen und Komponenten (DB, RabbitMQ, Redis, Docker usw.) installieren.

Im dritten Teil werden wir endlich herausfinden, wie wir eine Pipeline für die Bereitstellung unseres Projekts auf einem Server in einer Entwicklungs- und Produktionsumgebung einrichten. Und dann starten wir die Site auf dem Server.

Und ja, ich habe vergessen, mich vorzustellen. Mein Name ist Oleg Borzov, ich bin Fullstack-Entwickler im CRM-Team für Hypothekenmanager bei Domclick.

Projektübersicht

Schauen wir uns zunächst zwei Projekt-Repositorys an – Backend und Front – und gehen wir den Code durch.

Backend: Flasche+Sellerie

Für den hinteren Teil habe ich einen Haufen genommen, der bei Python-Entwicklern sehr beliebt ist: das Flask-Framework (für die API) und Celery (für die Aufgabenwarteschlange). Als ORM wird SQLAchemy verwendet. Alembic wird für Migrationen verwendet. Für die JSON-Validierung in Handles – Marshmallow.

В Lagerstätten Es gibt eine Readme.md-Datei mit einer detaillierten Beschreibung der Struktur und Anweisungen zum Ausführen des Projekts.

Webpart-API Ganz unkompliziert, bestehend aus 6 Stiften:

  • /ping - um die Verfügbarkeit zu prüfen;
  • Handles für die Registrierung, Autorisierung, Deautorisierung und Erlangung eines autorisierten Benutzers;
  • ein E-Mail-Handle, das eine Aufgabe in die Celery-Warteschlange stellt.

Sellerieteil noch einfacher, es gibt nur ein Problem send_mail_task.

Im Ordner /conf Es gibt zwei Unterordner:

  • docker mit zwei Dockerfiles (base.dockerfile ein sich selten änderndes Basisimage zu erstellen und Dockerfile für Hauptversammlungen);
  • .env_files - mit Dateien mit Umgebungsvariablen für verschiedene Umgebungen.

Im Stammverzeichnis des Projekts befinden sich vier Docker-Compose-Dateien:

  • docker-compose.local.db.yml eine lokale Datenbank für die Entwicklung aufzubauen;
  • docker-compose.local.workers.yml für die lokale Erhöhung des Workers, der Datenbank, Redis und RabbitMQ;
  • docker-compose.test.yml um Tests während der Bereitstellung durchzuführen;
  • docker-compose.yml für den Einsatz.

Und der letzte Ordner, der uns interessiert - .ci-cd. Es enthält Shell-Skripte für die Bereitstellung:

  • deploy.sh — Beginn der Migration und Bereitstellung. Läuft auf dem Server nach dem Erstellen und Ausführen von Tests in Github Actions;
  • rollback.sh - Rollback von Containern auf die vorherige Version der Baugruppe;
  • curl_tg.sh - Senden von Bereitstellungsbenachrichtigungen an Telegram.

Frontend auf Angular

Ablage mit Front viel einfacher als Becks. Die Vorderseite besteht aus drei Seiten:

  • Hauptseite mit einem Formular zum Versenden von E-Mails und einer Schaltfläche zum Beenden.
  • Loginseite.
  • Registrierungsseite.

Die Hauptseite sieht asketisch aus:

CI/CD in Github-Aktionen für ein Flask+Angular-Projekt
Es gibt zwei Dateien im Stammverzeichnis Dockerfile и docker-compose.yml, sowie der bekannte Ordner .ci-cd mit etwas weniger Skripten als im Back-Repository (entfernte Skripte zum Ausführen von Tests).

Ein Projekt in Plesk starten

Beginnen wir mit der Einrichtung von Plesk und der Erstellung eines Abonnements für unsere Website.

Erweiterungen installieren

In Plesk benötigen wir vier Erweiterungen:

  • Docker um den Status von Containern im Plesk-Admin-Panel zu verwalten und visuell anzuzeigen;
  • Git um den Bereitstellungsschritt auf dem Server zu konfigurieren;
  • Let's Encrypt um kostenlose TLS-Zertifikate zu generieren (und automatisch zu erneuern);
  • Firewall um die Filterung des eingehenden Datenverkehrs zu konfigurieren.

Sie können sie über das Plesk-Admin-Panel im Abschnitt „Erweiterungen“ installieren:

CI/CD in Github-Aktionen für ein Flask+Angular-Projekt
Auf die Detaileinstellungen für Erweiterungen gehen wir nicht ein, für unsere Demozwecke genügen die Standardeinstellungen.

Erstellen Sie ein Abonnement und eine Website

Als nächstes müssen wir ein Abonnement für unsere Website helloworld.ru erstellen und dort die Subdomain dev.helloworld.ru hinzufügen.

  1. Erstellen Sie ein Abonnement für die Domain helloworld.ru und geben Sie das Login-Passwort für den Systembenutzer an:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt
    Aktivieren Sie das Kontrollkästchen unten auf der Seite Sichern Sie die Domain mit Let's EncryptWenn wir HTTPS für die Site einrichten möchten:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  2. Als nächstes erstellen Sie in diesem Abonnement eine Subdomain dev.helloworld.ru (für die Sie auch ein kostenloses TLS-Zertifikat ausstellen können):

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

Installieren von Serverkomponenten

Wir haben einen Server mit Betriebssystem Debian Stretch 9.12 und installiertes Bedienfeld Plesk Obsidian 18.0.27.

Wir müssen für unser Projekt Folgendes installieren und konfigurieren:

  • PostgreSQL (in unserem Fall wird es einen Server mit zwei Datenbanken für Entwicklungs- und Produktionsumgebungen geben).
  • RabbitMQ (gleiche, gleiche Instanz mit unterschiedlichen Vhosts für Umgebungen).
  • Zwei Redis-Instanzen (für Entwicklungs- und Produktionsumgebungen).
  • Docker Registry (zur lokalen Speicherung erstellter Docker-Images).
  • Benutzeroberfläche für die Docker-Registrierung.

PostgreSQL

Plesk wird bereits mit dem PostgreSQL-DBMS geliefert, jedoch nicht mit der neuesten Version (zum Zeitpunkt des Schreibens Plesk Obsidian). unterstützt Postgres-Versionen 8.4–10.8). Wir möchten die neueste Version für unsere Anwendung (12.3 zum Zeitpunkt des Verfassens dieses Artikels) und werden sie daher manuell installieren.

Es gibt viele detaillierte Anleitungen zur Installation von Postgres unter Debian im Netz (Beispiel), daher werde ich sie nicht im Detail beschreiben, sondern nur die Befehle geben:

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

Da PostgreSQL über eher mittelmäßige Standardeinstellungen verfügt, ist eine Korrektur der Konfiguration erforderlich. Das wird uns helfen Rechner: Sie müssen die Parameter Ihres Servers eingeben und die Einstellungen in der Datei ersetzen /etc/postgresql/12/main/postgresql.confzu den angebotenen. Hierbei ist zu beachten, dass es sich bei solchen Rechnern nicht um Wundermittel handelt und die Basis genauer auf Ihre Hardware, Anwendung und Abfragekomplexität abgestimmt werden sollte. Aber das reicht für den Anfang.

Zusätzlich zu den vom Rechner vorgeschlagenen Einstellungen ändern wir auch postgresql.confden Standardport 5432 zu einem anderen (in unserem Beispiel - 53983).

Nachdem Sie die Konfigurationsdatei geändert haben, starten Sie den Postgresql-Server mit dem folgenden Befehl neu:

service postgresql restart

Wir haben PostgreSQL installiert und konfiguriert. Jetzt erstellen wir eine Datenbank, Benutzer für Entwicklungs- und Produktionsumgebungen und erteilen den Benutzern Rechte zum Verwalten der Datenbank:

$ 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

Fahren wir mit der Installation von RabbitMQ fort, einem Nachrichtenbroker für Celery. Die Installation unter Debian ist ganz einfach:

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

Nach der Installation müssen wir erstellen vhosts, Benutzer und gewähren Sie die erforderlichen Rechte:

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

Jetzt installieren und konfigurieren wir die letzte Komponente für unsere Anwendung – Redis. Es wird als Backend zum Speichern der Ergebnisse von Celery-Aufgaben verwendet.

Wir werden mithilfe der Erweiterung zwei Docker-Container mit Redis für Entwicklungs- und Produktionsumgebungen erstellen Docker für Plesk.

  1. Wir gehen zu Plesk, gehen zum Abschnitt „Erweiterungen“, suchen nach der Docker-Erweiterung und installieren sie (wir benötigen eine kostenlose Version):

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  2. Gehen Sie zur installierten Erweiterung und suchen Sie das Bild über die Suche redis bitnami und installieren Sie die neueste Version:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  3. Wir gehen in den heruntergeladenen Container und passen die Konfiguration an: Geben Sie den Port, die maximal zugewiesene RAM-Größe, das Passwort in den Umgebungsvariablen an und mounten Sie das Volume:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  4. Wir führen die Schritte 2-3 für den Prod-Container durch, in den Einstellungen ändern wir nur die Parameter: Port, Passwort, RAM-Größe und Pfad zum Volume-Ordner auf dem Server:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

Docker-Registrierung

Zusätzlich zu den Basisdiensten wäre es schön, ein eigenes Docker-Image-Repository auf dem Server zu platzieren. Glücklicherweise ist Serverplatz mittlerweile recht günstig (sicherlich günstiger als ein DockerHub-Abonnement) und die Einrichtung eines privaten Repositorys ist sehr einfach.

Wir wollen haben:

Um dies zu tun:

  1. Lassen Sie uns in unserem Abonnement zwei Subdomains in Plesk erstellen: docker.helloworld.ru und docker-ui.helloworld.ru und konfigurieren Sie Let's Encrypt-Zertifikate für sie.
  2. Fügen Sie die Datei zum Subdomain-Ordner docker.helloworld.ru hinzu docker-compose.yml mit Inhalten wie diesem:
    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. Unter SSH generieren wir die .htpasswd-Datei für die Basic-Autorisierung im Docker-Repository:
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Behälter sammeln und heben:
    docker-compose up -d
  5. Und wir müssen Nginx auf unsere Container umleiten. Dies kann über Plesk erfolgen.

Die folgenden Schritte müssen für die Subdomains docker.helloworld.ru und docker-ui.helloworld.ru durchgeführt werden:

Im Abschnitt Dev Tools Besuchen Sie unsere Website Docker-Proxy-Regeln:

CI/CD in Github-Aktionen für ein Flask+Angular-Projekt
Und fügen Sie eine Regel hinzu, um eingehenden Datenverkehr an unseren Container weiterzuleiten:

CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  1. Wir prüfen, ob wir uns vom lokalen Rechner aus bei unserem Container anmelden können:
    $ 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. Lassen Sie uns auch die Funktion der Subdomain docker-ui.helloworld.ru überprüfen:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt
    Wenn Sie auf „Repositorys durchsuchen“ klicken, zeigt der Browser ein Autorisierungsfenster an, in dem Sie den Benutzernamen und das Passwort für das Repository eingeben müssen. Danach werden wir auf eine Seite mit einer Liste von Repositories weitergeleitet (vorerst ist sie für Sie leer):

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

Ports in der Plesk Firewall öffnen

Nach der Installation und Konfiguration der Komponenten müssen wir Ports öffnen, damit die Komponenten von Docker-Containern und dem externen Netzwerk aus zugänglich sind.

Sehen wir uns an, wie das mit der Firewall-Erweiterung für Plesk geht, die wir zuvor installiert haben.

  1. Wir gehen zu Extras & Einstellungen > Einstellungen > Firewall:
    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt
  2. Wir gehen zu Plesk Firewall-Regeln ändern > Benutzerdefinierte Regel hinzufügen und öffnen Sie die folgenden TCP-Ports für das Docker-Subnetz (172.0.0.0 / 8):
    RabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
    Redis: 32785, 32786

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  3. Wir werden außerdem eine Regel hinzufügen, die PostgreSQL-Ports und RabbitMQ-Verwaltungspanels für die Außenwelt öffnet:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  4. Wenden Sie die Regeln über die Schaltfläche „Änderungen übernehmen“ an:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

CI/CD in Github Actions einrichten

Kommen wir zum interessantesten Teil – dem Einrichten einer kontinuierlichen Integrationspipeline und der Bereitstellung unseres Projekts auf dem Server.

Diese Pipeline wird aus zwei Teilen bestehen:

  • Erstellen eines Images und Ausführen von Tests (für das Backend) – auf der Github-Seite;
  • Ausführen von Migrationen (für das Backend) und Bereitstellen von Containern – auf dem Server.

Bereitstellung in Plesk

Befassen wir uns zunächst mit dem zweiten Punkt (denn der erste hängt davon ab).

Wir werden den Bereitstellungsprozess mithilfe der Git-Erweiterung für Plesk konfigurieren.

Betrachten Sie ein Beispiel mit einer Prod-Umgebung für ein Backend-Repository.

  1. Wir gehen zum Abonnement unserer Helloworld-Website und gehen zum Git-Unterabschnitt:

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  2. Fügen Sie einen Link zu unserem Github-Repository in das Feld „Remote-Git-Repository“ ein und ändern Sie den Standardordner httpdocs zu einem anderen (z. /httpdocs/hw_back):

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  3. Kopieren Sie den öffentlichen SSH-Schlüssel aus dem vorherigen Schritt und hinzufügen Es ist in den Github-Einstellungen.
  4. Klicken Sie in Schritt 2 auf dem Bildschirm auf OK. Anschließend werden wir zur Repository-Seite in Plesk weitergeleitet. Jetzt müssen wir das Repository so konfigurieren, dass es bei Commits an den Master-Zweig aktualisiert wird. Gehen Sie dazu zu Repository-Einstellungen und speichern Sie den Wert Webhook URL (Wir werden es später beim Einrichten von Github-Aktionen benötigen):

    CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

  5. Geben Sie im Feld „Aktionen“ auf dem Bildschirm aus dem vorherigen Absatz das Skript zum Starten der Bereitstellung ein:
    cd {REPOSITORY_ABSOLUTE_PATH}
    .ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} 

    wo:

    {REPOSITORY_ABSOLUTE_PATH} - Pfad zum Prod-Ordner des Backend-Repositorys auf dem Server;
    {ENV} - Umgebung (dev / prod), in unserem Fall prod;
    {DOCKER_REGISTRY_HOST} – der Host unseres Docker-Repositorys
    {TG_BOT_TOKEN} – Telegram-Bot-Token;
    {TG_CHAT_ID} — ID des Chats/Kanals zum Versenden von Benachrichtigungen.

    Skriptbeispiel:

    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. Fügen Sie einen Benutzer aus unserem Abonnement zur Docker-Gruppe hinzu (damit er Container verwalten kann):
    sudo usermod -aG docker helloworld_admin

Die Entwicklungsumgebung für das Backend-Repository und das Frontend werden auf die gleiche Weise eingerichtet.

Bereitstellungspipeline in Github Actions

Fahren wir mit der Einrichtung des ersten Teils unserer CI/CD-Pipeline in Github Actions fort.

Backend

Die Pipeline ist in beschrieben Deploy.yml-Datei.

Aber bevor wir es analysieren, füllen wir die geheimen Variablen aus, die wir in Github benötigen. Gehen Sie dazu zu Einstellungen -> Geheimnisse:

  • DOCKER_REGISTRY - der Host unseres Docker-Repositorys (docker.helloworld.ru);
  • DOCKER_LOGIN - Melden Sie sich beim Docker-Repository an;
  • DOCKER_PASSWORD - Passwort dazu;
  • DEPLOY_HOST – Host, auf dem das Plesk-Admin-Panel verfügbar ist (Beispiel: helloworld.com:8443 oder 123.4.56.78:8443);
  • DEPLOY_BACK_PROD_TOKEN - ein Token für die Bereitstellung im Prod-Repository auf dem Server (wir haben es in Bereitstellung in Plesk S. 4 erhalten);
  • DEPLOY_BACK_DEV_TOKEN – Token für die Bereitstellung im Entwicklungs-Repository auf dem Server.

Der Bereitstellungsprozess ist einfach und besteht aus drei Hauptschritten:

  • Erstellen und Veröffentlichen des Bildes in unserem Repository;
  • Ausführen von Tests in einem Container basierend auf einem frisch erstellten Image;
  • Bereitstellung in der gewünschten Umgebung je nach Zweig (Dev/Master).

Frontend

Die Datei „deploy.yml“ für das Front-Repository kaum anders als bei Beck. Es fehlt ein Schritt zum Ausführen von Tests und es werden die Namen der Token für die Bereitstellung geändert. Secrets für das Front-Repository müssen übrigens separat ausgefüllt werden.

Site-Einrichtung

Proxy-Verkehr über Nginx

Nun, wir sind am Ende angelangt. Es bleibt nur noch, das Proxying des ein- und ausgehenden Datenverkehrs zu unserem Container über Nginx zu konfigurieren. Wir haben diesen Vorgang bereits in Schritt 5 des Docker Registry-Setups behandelt. Das Gleiche sollte für den hinteren und vorderen Teil in Entwicklungs- und Produktionsumgebungen wiederholt werden.

Ich werde Screenshots der Einstellungen bereitstellen.

Backend

CI/CD in Github-Aktionen für ein Flask+Angular-Projekt

Frontend

CI/CD in Github-Aktionen für ein Flask+Angular-Projekt
Wichtige Klarstellung. Alle URLs werden per Proxy an den Frontend-Container weitergeleitet, mit Ausnahme derjenigen, die mit beginnen /api/ - Sie werden an den hinteren Container weitergeleitet (so Im hinteren Container müssen alle Handler mit beginnen /api/).

Ergebnisse

Jetzt sollte unsere Website unter helloworld.ru und dev.helloworld.ru (Produkt- bzw. Entwicklungsumgebung) verfügbar sein.

Insgesamt haben wir gelernt, wie man eine einfache Anwendung in Flask und Angular vorbereitet und eine Pipeline in Github Actions einrichtet, um sie auf einem Server auszurollen, auf dem Plesk läuft.

Ich werde die Links zu den Repositories mit dem Code duplizieren: Backend, Frontend.

Source: habr.com

Kommentar hinzufügen