CI/CD trong Github Actions cho dự án Flask+Angular

CI/CD trong Github Actions cho dự án Flask+Angular
Trong bài viết này, tôi sẽ chia sẻ kinh nghiệm thiết lập CI/CD bằng bảng điều khiển Plesk và Github Actions. Hôm nay chúng ta sẽ học cách triển khai một dự án đơn giản với cái tên đơn giản “Helloworld”. Nó được viết bằng Flask framework Python, với các công nhân ở Celery và giao diện người dùng trong Angular 8.

Liên kết đến các kho lưu trữ: phụ trợ, lối vào.

Trong phần đầu tiên của bài viết, chúng ta sẽ xem xét dự án của chúng ta và các phần của nó. Trong phần thứ hai, chúng ta sẽ tìm hiểu cách định cấu hình Plesk cũng như cài đặt các tiện ích mở rộng và thành phần cần thiết (DB, RabbitMQ, Redis, Docker, v.v.).

Trong phần thứ ba, cuối cùng chúng ta sẽ tìm ra cách thiết lập quy trình triển khai dự án của mình đến máy chủ trong môi trường nhà phát triển và sản xuất. Và sau đó chúng tôi sẽ khởi chạy trang web trên máy chủ.

Và vâng, tôi quên giới thiệu bản thân mình. Tên tôi là Oleg Borzov, tôi là nhà phát triển toàn diện trong nhóm CRM dành cho người quản lý cho vay thế chấp tại Domklik.

dự án Tổng quan

Trước tiên, chúng ta hãy xem xét hai kho lưu trữ của dự án - phần phụ trợ và phần trước - và xem qua mã.

Phần phụ trợ: Bình + Cần tây

Đối với phần back-end, tôi đã sử dụng một sự kết hợp khá phổ biến đối với các nhà phát triển Python: khung Flask (cho API) và Celery (cho hàng đợi tác vụ). SQLAchemy được sử dụng làm ORM. Alembic được sử dụng để di chuyển. Để xác thực JSON trong các thẻ điều khiển - Marshmallow.

В kho lưu trữ Có một tệp Readme.md với mô tả chi tiết về cấu trúc và hướng dẫn bắt đầu dự án.

API phần web khá đơn giản, gồm 6 tay cầm:

  • /ping - để kiểm tra tính sẵn có;
  • xử lý việc đăng ký, ủy quyền, hủy ủy quyền và có được người dùng được ủy quyền;
  • một tay cầm để gửi email đưa tác vụ vào hàng Celery.

Phần cần tây Nó thậm chí còn đơn giản hơn, chỉ có một vấn đề send_mail_task.

Trong thư mục / conf có hai thư mục con:

  • docker với hai Dockerfiles (base.dockerfile để xây dựng một hình ảnh cơ bản hiếm khi thay đổi và Dockerfile cho các cụm chính);
  • .env_files - với các tệp có biến môi trường cho các môi trường khác nhau.

Có bốn tệp docker-compose trong thư mục gốc của dự án:

  • docker-compose.local.db.yml xây dựng cơ sở dữ liệu địa phương để phát triển;
  • docker-compose.local.workers.yml để nâng cao nhân viên, cơ sở dữ liệu, Redis và RabbitMQ cục bộ;
  • docker-compose.test.yml để chạy thử nghiệm trong quá trình triển khai;
  • docker-compose.yml để triển khai.

Và thư mục cuối cùng mà chúng tôi quan tâm là .ci-cd. Nó chứa các tập lệnh shell để triển khai:

  • deploy.sh — khởi động quá trình di chuyển và triển khai. Ra mắt trên máy chủ sau khi xây dựng và chạy thử nghiệm trong Github Actions;
  • rollback.sh — khôi phục các thùng chứa về phiên bản trước của cụm lắp ráp;
  • curl_tg.sh — gửi thông báo triển khai tới Telegram.

Giao diện người dùng trong góc

Kho lưu trữ có mặt trước đơn giản hơn nhiều so với Bekov. Mặt trước gồm có ba trang:

  • Trang chủ có biểu mẫu gửi email và nút đăng xuất.
  • Trang đăng nhập.
  • Trang đăng ký.

Trang chính có vẻ khổ hạnh:

CI/CD trong Github Actions cho dự án Flask+Angular
Có hai tập tin trong thư mục gốc Dockerfile и docker-compose.yml, cũng như thư mục quen thuộc .ci-cd với số lượng tập lệnh nhỏ hơn một chút so với kho lưu trữ phía sau (các tập lệnh để chạy thử nghiệm đã bị xóa).

Bắt đầu một dự án ở Plesk

Hãy bắt đầu bằng cách thiết lập Plesk và tạo đăng ký cho trang web của chúng tôi.

Cài đặt tiện ích mở rộng

Trong Plesk chúng ta cần bốn phần mở rộng:

  • Docker để quản lý và hiển thị trực quan trạng thái của vùng chứa trong bảng quản trị Plesk;
  • Git để cấu hình bước triển khai trên máy chủ;
  • Let's Encrypt để tạo (và tự động gia hạn) chứng chỉ TLS miễn phí;
  • Firewall để cấu hình lọc lưu lượng truy cập đến.

Bạn có thể cài đặt chúng thông qua bảng quản trị Plesk trong phần Tiện ích mở rộng:

CI/CD trong Github Actions cho dự án Flask+Angular
Chúng tôi sẽ không xem xét cấu hình chi tiết của tiện ích mở rộng; vì mục đích demo của chúng tôi, cài đặt mặc định sẽ phù hợp.

Tạo đăng ký và trang web

Tiếp theo, chúng ta cần tạo một đăng ký cho trang web helloworld.ru của mình và thêm tên miền phụ dev.helloworld.ru vào đó.

  1. Chúng tôi tạo một đăng ký cho miền helloworld.ru và chỉ định mật khẩu đăng nhập cho người dùng hệ thống:

    CI/CD trong Github Actions cho dự án Flask+Angular
    Đánh dấu vào ô ở cuối trang Bảo mật miền với Let's Encrypt, nếu chúng tôi muốn định cấu hình HTTPS cho trang web:

    CI/CD trong Github Actions cho dự án Flask+Angular

  2. Tiếp theo, trong đăng ký này, chúng tôi tạo một tên miền phụ dev.helloworld.ru (bạn cũng có thể cấp chứng chỉ TLS miễn phí):

    CI/CD trong Github Actions cho dự án Flask+Angular

Cài đặt các thành phần máy chủ

Chúng tôi có một máy chủ với Hệ điều hành Debian Stretch 9.12 và bảng điều khiển được cài đặt Plesk Obsidian 18.0.27.

Chúng ta cần cài đặt và cấu hình cho dự án của mình:

  • PostgreSQL (trong trường hợp của chúng tôi sẽ có một máy chủ có hai cơ sở dữ liệu cho môi trường dev và prod).
  • RabbitMQ (điều tương tự, một phiên bản có vhost khác nhau cho môi trường).
  • Hai phiên bản Redis (dành cho môi trường dev và prod).
  • Docker Đăng ký (để lưu trữ cục bộ các hình ảnh Docker đã biên dịch).
  • Giao diện UI cho đăng ký Docker.

PostgreSQL

Plesk đã có sẵn Hệ quản trị cơ sở dữ liệu PostgreSQL, nhưng chưa có phiên bản mới nhất (tại thời điểm viết bài Plesk Obsidian được hỗ trợ Phiên bản Postgres 8.4–10.8). Chúng tôi muốn có phiên bản mới nhất cho ứng dụng của mình (12.3 tại thời điểm viết bài), vì vậy chúng tôi sẽ cài đặt nó theo cách thủ công.

Có rất nhiều hướng dẫn chi tiết để cài đặt Postgres trên Debian trực tuyến (Ví dụ), nên tôi sẽ không mô tả chi tiết mà chỉ đưa ra các lệnh:

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

Vì PostgreSQL có cài đặt mặc định khá tầm thường nên cần phải điều chỉnh cấu hình. Điều này sẽ giúp chúng tôi máy tính: bạn cần nhập thông số máy chủ của mình và thay thế các cài đặt trong tệp /etc/postgresql/12/main/postgresql.confđối với những người được đề xuất. Ở đây cần lưu ý rằng những máy tính như vậy không phải là một viên đạn ma thuật và cơ sở phải được điều chỉnh chính xác hơn, dựa trên phần cứng, ứng dụng và độ phức tạp của các truy vấn của bạn. Nhưng điều này là đủ để bắt đầu.

Ngoài các cài đặt được máy tính đề xuất, chúng tôi cũng thay đổi postgresql.confcổng mặc định 5432 được gán cho cổng khác (trong ví dụ của chúng tôi - 53983).

Sau khi thay đổi file cấu hình, khởi động lại postgresql-server bằng lệnh:

service postgresql restart

Chúng tôi đã cài đặt và định cấu hình PostgreSQL. Bây giờ, hãy tạo cơ sở dữ liệu, người dùng cho môi trường dev và prod, đồng thời cấp cho người dùng quyền quản lý cơ sở dữ liệu:

$ 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

ThỏMQ

Hãy chuyển sang cài đặt RabbitMQ, nhà môi giới tin nhắn cho Celery. Cài đặt nó trên Debian khá đơn giản:

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

Sau khi cài đặt chúng ta cần tạo vhosts, người dùng và cấp các quyền cần thiết:

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

Bây giờ hãy cài đặt và định cấu hình thành phần cuối cùng cho ứng dụng của chúng ta - Redis. Nó sẽ được sử dụng như một phần phụ trợ để lưu trữ kết quả của các nhiệm vụ Celery.

Chúng tôi sẽ nâng cao hai vùng chứa Docker với Redis cho môi trường dev và prod bằng cách sử dụng tiện ích mở rộng Docker cho Plesk.

  1. Vào Plesk, vào phần Tiện ích mở rộng, tìm tiện ích mở rộng Docker và cài đặt nó (chúng tôi cần phiên bản miễn phí):

    CI/CD trong Github Actions cho dự án Flask+Angular

  2. Vào tiện ích mở rộng đã cài đặt, tìm hình ảnh thông qua tìm kiếm redis bitnami và cài đặt phiên bản mới nhất:

    CI/CD trong Github Actions cho dự án Flask+Angular

  3. Chúng tôi đi vào vùng chứa đã tải xuống và điều chỉnh cấu hình: chỉ định cổng, kích thước RAM được phân bổ tối đa, mật khẩu trong các biến môi trường và gắn ổ đĩa:

    CI/CD trong Github Actions cho dự án Flask+Angular

  4. Chúng tôi thực hiện các bước 2-3 cho prod container, trong cài đặt chúng tôi chỉ thay đổi các tham số: cổng, mật khẩu, kích thước RAM và đường dẫn đến thư mục ổ đĩa trên máy chủ:

    CI/CD trong Github Actions cho dự án Flask+Angular

Cơ quan đăng ký Docker

Ngoài các dịch vụ cơ bản, sẽ rất tuyệt nếu cài đặt kho lưu trữ hình ảnh Docker của riêng bạn trên máy chủ. May mắn thay, dung lượng trên máy chủ hiện khá rẻ (chắc chắn rẻ hơn so với đăng ký DockerHub) và quá trình cài đặt kho lưu trữ riêng rất đơn giản.

Chúng tôi muốn có:

Để làm điều này:

  1. Hãy tạo hai tên miền phụ trong đăng ký của chúng tôi trong Plesk: docker.helloworld.ru và docker-ui.helloworld.ru, đồng thời định cấu hình chứng chỉ Let's Encrypt cho chúng.
  2. Thêm tệp vào thư mục tên miền phụ docker.helloworld.ru docker-compose.yml với nội dung như thế này:
    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. Trong SSH, chúng tôi sẽ tạo tệp .htpasswd để ủy quyền Cơ bản trong kho Docker:
    htpasswd -bBc .htpasswd hw_docker_admin hw_docker_password
  4. Hãy thu thập và nâng các thùng chứa:
    docker-compose up -d
  5. Và chúng ta cần chuyển hướng Nginx đến vùng chứa của mình. Điều này có thể được thực hiện thông qua Plesk.

Các bước sau đây cần được thực hiện cho tên miền phụ docker.helloworld.ru và docker-ui.helloworld.ru:

Trong phần Những công cụ của nhà phát triển trang web của chúng tôi đi đến Quy tắc proxy của Docker:

CI/CD trong Github Actions cho dự án Flask+Angular
Và thêm quy tắc để ủy quyền lưu lượng truy cập đến vùng chứa của chúng tôi:

CI/CD trong Github Actions cho dự án Flask+Angular

  1. Chúng tôi kiểm tra xem chúng tôi có thể đăng nhập vào vùng chứa của mình từ máy cục bộ hay không:
    $ 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. Chúng ta cũng hãy kiểm tra hoạt động của tên miền phụ docker-ui.helloworld.ru:

    CI/CD trong Github Actions cho dự án Flask+Angular
    Khi bạn nhấp vào Duyệt qua kho lưu trữ, trình duyệt sẽ hiển thị cửa sổ ủy quyền nơi bạn sẽ cần nhập thông tin đăng nhập và mật khẩu cho kho lưu trữ. Sau đó, chúng ta sẽ được chuyển hướng đến một trang có danh sách các kho lưu trữ (hiện tại nó sẽ trống):

    CI/CD trong Github Actions cho dự án Flask+Angular

Mở cổng trong Tường lửa Plesk

Sau khi cài đặt và cấu hình các thành phần, chúng ta cần mở các cổng để có thể truy cập các thành phần từ bộ chứa Docker và mạng bên ngoài.

Hãy xem cách thực hiện việc này bằng ví dụ về tiện ích mở rộng Tường lửa cho Plesk mà chúng tôi đã cài đặt trước đó.

  1. Đi đến Công cụ & Cài đặt > Cài đặt > Tường lửa:
    CI/CD trong Github Actions cho dự án Flask+Angular
  2. Đi đến Sửa đổi quy tắc tường lửa Plesk > Thêm quy tắc tùy chỉnh và mở các cổng TCP sau cho mạng con Docker (172.0.0.0 / 8):
    RabbitMQ: 1883, 4369, 5671-5672, 25672, 61613-61614
    Làm lại: 32785, 32786

    CI/CD trong Github Actions cho dự án Flask+Angular

  3. Chúng tôi cũng sẽ thêm một quy tắc sẽ mở các cổng PostgreSQL và bảng quản lý RabbitMQ với thế giới bên ngoài:

    CI/CD trong Github Actions cho dự án Flask+Angular

  4. Áp dụng các quy tắc bằng nút Áp dụng thay đổi:

    CI/CD trong Github Actions cho dự án Flask+Angular

Thiết lập CI/CD trong Hành động Github

Hãy đến phần thú vị nhất - thiết lập quy trình tích hợp liên tục và phân phối dự án của chúng tôi tới máy chủ.

Đường ống này sẽ bao gồm hai phần:

  • xây dựng hình ảnh và chạy thử nghiệm (cho phần phụ trợ) - về phía Github;
  • khởi chạy quá trình di chuyển (cho phần phụ trợ) và triển khai các vùng chứa trên máy chủ.

Triển khai lên Plesk

Trước tiên hãy giải quyết điểm thứ hai (vì điểm đầu tiên phụ thuộc vào nó).

Chúng tôi sẽ định cấu hình quy trình triển khai bằng tiện ích mở rộng Git cho Plesk.

Hãy xem một ví dụ với môi trường Prod cho kho lưu trữ Backend.

  1. Chúng tôi đi đến đăng ký trang web Helloworld của chúng tôi và đi đến tiểu mục Git:

    CI/CD trong Github Actions cho dự án Flask+Angular

  2. Dán liên kết đến kho lưu trữ Github của chúng tôi vào trường “Kho lưu trữ Git từ xa” và thay đổi thư mục mặc định httpdocs sang cái khác (ví dụ, /httpdocs/hw_back):

    CI/CD trong Github Actions cho dự án Flask+Angular

  3. Sao chép khóa công khai SSH từ bước trước và thêm nó trong cài đặt Github.
  4. Nhấn OK trên màn hình ở bước 2, sau đó chúng ta được chuyển hướng đến trang kho lưu trữ trong Plesk. Bây giờ chúng ta cần cấu hình kho lưu trữ để cập nhật khi chuyển sang nhánh chính. Để thực hiện việc này, hãy truy cập Cài đặt kho lưu trữ và lưu giá trị Webhook URL (chúng tôi sẽ cần điều này sau khi thiết lập Tác vụ Github):

    CI/CD trong Github Actions cho dự án Flask+Angular

  5. Trong trường Hành động trên màn hình ở đoạn trước, nhập tập lệnh để bắt đầu triển khai:
    cd {REPOSITORY_ABSOLUTE_PATH}
    .ci-cd/deploy.sh {ENV} {DOCKER_REGISTRY_HOST} {DOCKER_USER} {DOCKER_PASSWORD} {TG_BOT_TOKEN} {TG_CHAT_ID} 

    Trong đó:

    {REPOSITORY_ABSOLUTE_PATH} — đường dẫn đến thư mục kho lưu trữ phụ trợ sản phẩm trên máy chủ;
    {ENV} - môi trường (dev/prod), trong trường hợp của chúng tôi prod;
    {DOCKER_REGISTRY_HOST} — máy chủ lưu trữ docker của chúng tôi
    {TG_BOT_TOKEN} — Mã thông báo bot Telegram;
    {TG_CHAT_ID} — ID trò chuyện/kênh để gửi thông báo.

    Kịch bản ví dụ:

    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. Chúng tôi thêm người dùng từ đăng ký của mình vào nhóm Docker (để anh ấy có thể quản lý vùng chứa):
    sudo usermod -aG docker helloworld_admin

Môi trường Dev cho kho lưu trữ phụ trợ và giao diện người dùng được cấu hình theo cùng một cách.

Đường ống triển khai đến các hành động trên Github

Hãy chuyển sang thiết lập phần đầu tiên của quy trình CI/CD trong Github Actions.

Backend

Đường ống được mô tả trong tập tin triển khai.yml.

Nhưng trước khi phân tích cú pháp, hãy điền vào các biến Bí mật mà chúng ta cần trong Github. Để thực hiện việc này, hãy truy cập Cài đặt -> Bí mật:

  • DOCKER_REGISTRY — máy chủ lưu trữ Docker của chúng tôi (docker.helloworld.ru);
  • DOCKER_LOGIN — đăng nhập vào kho Docker;
  • DOCKER_PASSWORD - mật khẩu cho nó;
  • DEPLOY_HOST — một máy chủ có sẵn bảng quản trị Plesk (ví dụ: xin chàoworld.ru: 8443 hoặc 123.4.56.78:8443);
  • DEPLOY_BACK_PROD_TOKEN — mã thông báo để triển khai tới kho lưu trữ sản phẩm trên máy chủ (chúng tôi đã nhận được nó trong Triển khai ở Plesk, bước 4);
  • DEPLOY_BACK_DEV_TOKEN — mã thông báo để triển khai tới kho lưu trữ dành cho nhà phát triển trên máy chủ.

Quá trình triển khai rất đơn giản và bao gồm ba bước chính:

  • xây dựng và xuất bản hình ảnh trong kho lưu trữ của chúng tôi;
  • chạy thử nghiệm trong vùng chứa dựa trên hình ảnh mới được biên dịch;
  • triển khai đến môi trường mong muốn tùy thuộc vào nhánh (dev/master).

lối vào

Tệp Deploy.yml cho kho lưu trữ phía trước không khác nhiều so với Bekov. Nó bỏ lỡ bước chạy thử nghiệm và thay đổi tên của các token để triển khai. Nhân tiện, các bí mật cho kho lưu trữ phía trước cần phải được điền riêng.

Thiết lập trang web

Ủy quyền lưu lượng truy cập qua Nginx

Vâng, chúng tôi đã đi đến cuối cùng. Tất cả những gì còn lại là định cấu hình ủy quyền lưu lượng truy cập đến và đi tới vùng chứa của chúng tôi thông qua Nginx. Chúng tôi đã đề cập đến quy trình này ở bước 5 khi thiết lập Docker Register. Điều tương tự cần được lặp lại cho phần sau và phần trước trong môi trường dev và prod.

Tôi sẽ cung cấp ảnh chụp màn hình của các cài đặt.

Backend

CI/CD trong Github Actions cho dự án Flask+Angular

lối vào

CI/CD trong Github Actions cho dự án Flask+Angular
Làm rõ quan trọng. Tất cả các URL sẽ được ủy quyền cho vùng chứa giao diện người dùng, ngoại trừ những URL bắt đầu bằng /api/ - chúng sẽ được ủy quyền cho vùng chứa phía sau (vì vậy trong vùng chứa phía sau, tất cả các trình xử lý phải bắt đầu bằng /api/).

Kết quả

Bây giờ, trang web của chúng tôi có thể truy cập được tại helloworld.ru và dev.helloworld.ru (tương ứng với môi trường prod và dev).

Tổng cộng, chúng tôi đã học cách chuẩn bị một ứng dụng đơn giản trong Flask và Angular, đồng thời thiết lập quy trình trong Github Actions để triển khai ứng dụng đó tới máy chủ chạy Plesk.

Tôi sẽ sao chép các liên kết đến kho lưu trữ bằng mã: phụ trợ, lối vào.

Nguồn: www.habr.com

Thêm một lời nhận xét