Giới thiệu tổng quan về CI/CD cho ứng dụng Flask
Trong môi trường phát triển phần mềm hiện đại, việc tự động hoá quá trình xây dựng, kiểm thử và triển khai (CI/CD) đã trở thành tiêu chuẩn bắt buộc để giảm thiểu rủi ro và tăng tốc độ đưa sản phẩm ra thị trường. Bài viết này sẽ tập trung vào việc thiết kế một pipeline CI/CD hoàn chỉnh cho dự án Python Flask chạy trên máy chủ ảo (VPS) bằng cách kết hợp Docker và GitHub Actions. Chúng ta sẽ đi qua từng bước chi tiết, từ cấu hình môi trường phát triển, viết Dockerfile, thiết lập GitHub Actions workflow, tới triển khai tự động lên VPS.
Kiến trúc tổng quan của pipeline
Pipeline CI/CD cho Flask trên VPS bao gồm các thành phần chính sau:
- Repository GitHub chứa mã nguồn và các file cấu hình.
- Dockerfile mô tả cách xây dựng image Docker cho ứng dụng.
- Docker Compose (tùy chọn) để quản lý các service phụ trợ như database.
- GitHub Actions workflow định nghĩa các job:
build,test,push,deploy. - VPS chạy Docker Engine, nhận image mới và khởi động container.
Mỗi job sẽ được thực thi trên runner của GitHub, và cuối cùng sẽ sử dụng SSH để truyền image tới VPS và thực thi lệnh docker-compose up -d.
Chuẩn bị môi trường phát triển
1. Tạo project Flask cơ bản
Giả sử chúng ta có một project Flask đơn giản với cấu trúc sau:
my_flask_app/ ├── app.py ├── requirements.txt └── .gitignore
Nội dung app.py:
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/')
def index():
return jsonify(message='Hello, CI/CD!')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
File .txt chỉ chứa:
Flask==2.3.2
2. Viết Dockerfile cho Flask
Dockerfile sẽ dựa trên image python:3.11-slim, cài đặt các phụ thuộc và sao chép mã nguồn.
# syntax=docker/dockerfile:1
FROM python:3.11-slim
# Thiết lập biến môi trường không hiển thị cảnh báo buôn bán
ENV PYTHONDONTWRITEBYTECODE=1 \
PYTHONUNBUFFERED=1
# Tạo thư mục làm việc
WORKDIR /app
# Cài đặt gcc để biên dịch các package nếu cần
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc && \
rm -rf /var/lib/apt/lists/*
# Sao chép file requirements và cài đặt
COPY requirements.txt .
RUN pip install --upgrade pip && \
pip install -r requirements.txt
# Sao chép toàn bộ mã nguồn
COPY . .
# Expose cổng Flask
EXPOSE 5000
# Lệnh khởi chạy
CMD ["python", "app.py"]
3. (Tùy chọn) Docker Compose để quản lý database
Nếu ứng dụng cần một database (ví dụ PostgreSQL), chúng ta có thể tạo file docker-compose.yml như sau:
version: '3.8'
services:
web:
build: .
ports:
- "5000:5000"
environment:
- DATABASE_URL=postgresql://postgres:secret@db:5432/mydb
depends_on:
- db
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
volumes:
pgdata:
Trong bài viết này, để tập trung vào CI/CD, chúng ta sẽ chỉ sử dụng service web mà không có database.
Thiết lập GitHub Actions workflow
1. Tạo file workflow
Trong repository, tạo thư mục .github/workflows và thêm file ci-cd.yml:
name: CI/CD Pipeline for Flask
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
build-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install -r requirements.txt
- name: Run unit tests
run: |
# Giả sử có file tests/test_app.py
pip install pytest
pytest tests
build-image:
needs: build-test
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
- name: Log in to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: ${{ secrets.DOCKER_USERNAME }}/flask-ci-cd:latest
deploy:
needs: build-image
runs-on: ubuntu-latest
steps:
- name: Deploy to VPS via SSH
uses: appleboy/[email protected]
with:
host: ${{ secrets.VPS_HOST }}
username: ${{ secrets.VPS_USER }}
key: ${{ secrets.VPS_SSH_KEY }}
port: ${{ secrets.VPS_PORT }}
script: |
docker pull ${{ secrets.DOCKER_USERNAME }}/flask-ci-cd:latest
docker stop flask_app || true
docker rm flask_app || true
docker run -d --name flask_app -p 80:5000 ${{ secrets.DOCKER_USERNAME }}/flask-ci-cd:latest
2. Giải thích chi tiết từng job
- build-test: Kiểm tra mã nguồn bằng Python, cài đặt phụ thuộc và chạy unit test (sử dụng
pytest). Nếu test thất bại, pipeline sẽ dừng lại. - build-image: Sau khi test thành công, Docker image được xây dựng và đẩy lên Docker Hub (hoặc GitHub Container Registry). Các thông tin đăng nhập được lưu trong
secretsđể bảo mật. - deploy: Sử dụng action
appleboy/ssh-actionđể SSH vào VPS, kéo image mới, dừng container cũ (nếu có) và khởi chạy container mới. Lệnhdocker run -d --name flask_app -p 80:5000sẽ ánh xạ cổng 80 của VPS tới cổng 5000 trong container.
3. Cấu hình Secrets trên GitHub
Để pipeline hoạt động, cần tạo các secret sau trong repository Settings > Secrets > Actions:
DOCKER_USERNAMEvàDOCKER_PASSWORD– tài khoản Docker Hub.VPS_HOST,VPS_USER,VPS_SSH_KEY,VPS_PORT– thông tin kết nối SSH tới VPS.VPS_SSH_KEYlà private key đã được thêm vào~/.ssh/authorized_keystrên VPS.
Triển khai trên VPS: Cài đặt Docker và cấu hình bảo mật
1. Cài đặt Docker Engine
Trên VPS (Ubuntu 22.04), thực hiện các lệnh sau:
sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo \$VERSION_ID) stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin sudo usermod -aG docker $USER newgrp docker
Sau khi cài đặt, kiểm tra bằng docker version và docker run hello-world để xác nhận Docker hoạt động.
2. Thiết lập tường lửa (ufw)
Đảm bảo chỉ mở cổng cần thiết (80, 443 nếu có SSL) và cổng SSH.
sudo ufw allow OpenSSH sudo ufw allow 80/tcp sudo ufw enable
3. Tối ưu bảo mật SSH
Trong file /etc/ssh/sshd_config, tắt đăng nhập bằng mật khẩu và chỉ cho phép key authentication:
PasswordAuthentication no PubkeyAuthentication yes PermitRootLogin prohibit-password
Khởi động lại dịch vụ:
sudo systemctl restart sshd
Thực hành: Kiểm tra pipeline trên môi trường thực tế
Để xác nhận pipeline hoạt động, thực hiện các bước sau:
- Push một commit mới lên nhánh
main(hoặc tạo pull request). GitHub Actions sẽ tự động chạy. - Theo dõi log của từng job trên tab Actions. Đảm bảo không có lỗi ở bước
testvàbuild-image. - Khi job
deployhoàn thành, mở trình duyệt và truy cập địa chỉ IP của VPS. Bạn sẽ thấy phản hồi JSON{"message":"Hello, CI/CD!"}.
Nếu có lỗi trong quá trình pull image hoặc khởi chạy container, kiểm tra log của action appleboy/ssh-action để xem chi tiết lệnh SSH đã thực thi.
Best practices và các lưu ý quan trọng
- Sử dụng multi‑stage build trong Dockerfile để giảm kích thước image. Ví dụ, xây dựng phụ thuộc trong stage
builderrồi copy chỉ các file cần thiết vào stage cuối. - Tag version cho mỗi release (ví dụ
v1.0.0) thay vì luôn dùnglatest. Điều này giúp rollback dễ dàng hơn. - Quản lý secret bằng GitHub Secrets hoặc HashiCorp Vault để tránh rò rỉ thông tin nhạy cảm.
- Giám sát container bằng công cụ như
cAdvisorhoặcPrometheus + Grafanađể phát hiện vấn đề tài nguyên. - Thêm healthcheck trong Dockerfile hoặc docker‑compose để Docker tự động restart container khi ứng dụng không phản hồi.
Ví dụ healthcheck trong Dockerfile
HEALTHCHECK --interval=30s --timeout=5s \ CMD curl -f http://localhost:5000/ || exit 1
Healthcheck này sẽ gửi request tới endpoint gốc mỗi 30 giây, nếu không nhận được phản hồi, container sẽ được đánh dấu là không khỏe mạnh.
Kết luận
Việc xây dựng một pipeline CI/CD cho ứng dụng Flask trên VPS không chỉ giúp giảm thiểu lỗi con người mà còn tăng tốc độ đưa tính năng mới vào môi trường production. Từ việc viết Dockerfile tối ưu, cấu hình GitHub Actions cho tới bảo mật VPS, mỗi bước đều đóng góp vào một quy trình triển khai mượt mà và an toàn. Đối với những ai muốn nâng cao kiến thức triển khai web thực tế, Tham khảo khóa học "Deploy Web - Triển khai website lên môi trường Internet" tại đây sẽ cung cấp nền tảng vững chắc về Server, VPS, Hosting và các kỹ thuật Deploy chuyên sâu.
.png)





