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.
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.
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:
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 đó.
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:
Đá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:
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í):
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:
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:
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.
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í):
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:
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:
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ủ:
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ó:
kho lưu trữ Docker được bảo vệ bằng mật khẩu có thể truy cập được qua tên miền phụ https://docker.helloworld.ru;
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.
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:
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:
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:
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
Chúng ta cũng hãy kiểm tra hoạt động của tên miền phụ docker-ui.helloworld.ru:
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):
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 đó.
Đi đến Công cụ & Cài đặt > Cài đặt > Tường lửa:
Đ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
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:
Áp dụng các quy tắc bằng nút Áp dụng thay đổi:
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.
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:
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):
Sao chép khóa công khai SSH từ bước trước và thêm nó trong cài đặt Github.
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):
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
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.
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
lối vào
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.