Tự triển khai Woodpecker CI trên Docker: Giải pháp thay thế GitHub Actions nhẹ nhàng và bảo mật

DevOps tutorial - IT technology blog
DevOps tutorial - IT technology blog

Gánh nặng từ các Pipeline CI/CD cồng kềnh

Vận hành một pipeline CI/CD mượt mà là yêu cầu bắt buộc đối với phát triển phần mềm hiện đại, nhưng các công cụ chúng ta thường dựa vào thường đi kèm với những đánh đổi đáng kể. GitHub Actions rất tuyệt vời cho các kho lưu trữ công khai, nhưng khi bạn chuyển sang hạ tầng tự quản lý, riêng tư, chi phí và các vấn đề về quyền riêng tư bắt đầu tăng lên.

Mặt khác, những “gã khổng lồ” như GitLab hay Jenkins thường đòi hỏi nhiều RAM và CPU hơn cả chính các ứng dụng mà chúng đang build. Tôi đã gặp nhiều trường hợp một máy chủ VPS (Virtual Private Server) nhỏ với 2GB RAM bị treo chỉ vì bộ điều khiển CI/CD quyết định thực hiện một tác vụ chạy ngầm.

Bản chất tiêu tốn tài nguyên này là nguyên nhân gốc rễ của nhiều sự ức chế trong thế giới DevOps. Khi công cụ được thiết kế để tự động hóa công việc của bạn lại trở thành gánh nặng bảo trì, đã đến lúc tìm kiếm một giải pháp thay thế tinh gọn hơn. Woodpecker CI, một bản fork cộng đồng từ Drone CI, giải quyết vấn đề này bằng cách cung cấp một engine pipeline container-native cực kỳ nhẹ. Nó được viết bằng Go, nghĩa là nó tiêu thụ rất ít bộ nhớ trong khi vẫn cung cấp trải nghiệm dựa trên YAML tương tự như GitHub Actions.

Tôi đã áp dụng phương pháp này trong môi trường thực tế và kết quả đạt được luôn ổn định. Bằng cách chuyển từ các hệ thống CI nặng nề sang Woodpecker chạy trên Docker, tôi đã giảm bớt được gánh nặng hạ tầng trong khi vẫn duy trì quyền kiểm soát hoàn toàn đối với môi trường build.

Tại sao Woodpecker CI phù hợp với hạ tầng của bạn

Trước khi đi vào các câu lệnh, điều quan trọng là phải hiểu tại sao ngăn xếp (stack) cụ thể này lại hiệu quả. Woodpecker sử dụng kiến trúc Server-Agent. Server xử lý giao diện web, xác thực người dùng và các lệnh gọi API, trong khi agent (hoặc nhiều agent) đảm nhận công việc nặng nhọc là chạy các bước build bên trong các container Docker. Sự phân tách này cho phép bạn mở rộng theo chiều ngang bằng cách thêm nhiều agent trên các máy chủ khác nhau nếu khối lượng build tăng lên.

Cài đặt: Triển khai với Docker Compose

Để bắt đầu, bạn cần một máy chủ đã cài đặt Docker và Docker Compose. Chúng ta sẽ tạo một thư mục tập trung để lưu trữ các tệp cấu hình và cơ sở dữ liệu cho Woodpecker.

mkdir ~/woodpecker-ci
cd ~/woodpecker-ci
touch docker-compose.yml .env

Woodpecker yêu cầu một khóa bí mật (secret key) để giao tiếp giữa server và agent. Hãy tạo một khóa bằng openssl:

openssl rand -hex 32

Bây giờ, hãy cấu hình tệp docker-compose.yml. Thiết lập này sử dụng SQLite để đơn giản hóa, nhưng bạn có thể dễ dàng chuyển sang PostgreSQL cho các dự án quy mô lớn hơn.

version: '3'

services:
  woodpecker-server:
    image: woodpeckerci/woodpecker-server:latest
    volumes:
      - ./woodpecker-data:/var/lib/woodpecker/
    environment:
      - WOODPECKER_OPEN=true
      - WOODPECKER_HOST=${WOODPECKER_HOST}
      - WOODPECKER_GITHUB=true
      - WOODPECKER_GITHUB_CLIENT=${WOODPECKER_GITHUB_CLIENT}
      - WOODPECKER_GITHUB_SECRET=${WOODPECKER_GITHUB_SECRET}
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
    ports:
      - "8000:8000"
    restart: always

  woodpecker-agent:
    image: woodpeckerci/woodpecker-agent:latest
    command: agent
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - WOODPECKER_SERVER=woodpecker-server:8000
      - WOODPECKER_AGENT_SECRET=${WOODPECKER_AGENT_SECRET}
    restart: always
    depends_on:
      - woodpecker-server

Cấu hình: Kết nối với GitHub

Để Woodpecker có thể nhìn thấy các kho lưu trữ của bạn, bạn cần đăng ký nó như một OAuth Application trên GitHub. Truy cập Profile GitHub của bạn -> Settings -> Developer Settings -> OAuth Apps -> New OAuth App.

  • Application Name: My Woodpecker CI
  • Homepage URL: http://your-server-ip:8000
  • Authorization callback URL: http://your-server-ip:8000/authorize

Sau khi đăng ký, bạn sẽ nhận được Client ID và Client Secret. Hãy điền chúng vào tệp .env của bạn:

WOODPECKER_HOST=http://your-server-ip:8000
WOODPECKER_AGENT_SECRET=your_generated_hex_key
WOODPECKER_GITHUB_CLIENT=your_github_client_id
WOODPECKER_GITHUB_SECRET=your_github_client_secret

Khởi động các dịch vụ bằng một câu lệnh duy nhất:

docker-compose up -d

Tạo Pipeline đầu tiên của bạn

Sau khi đăng nhập vào giao diện Woodpecker và kích hoạt kho lưu trữ của bạn, bạn cần thêm một tệp cấu hình vào dự án. Woodpecker sẽ tìm kiếm tệp có tên .woodpecker.yml ở thư mục gốc của repo. Dưới đây là một ví dụ thực tế cho một dự án Python:

pipeline:
  test:
    image: python:3.11-slim
    commands:
      - pip install -r requirements.txt
      - pytest

  build:
    image: docker:24
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    commands:
      - docker build -t my-app:latest .
    when:
      branch: main
      event: push

Lưu ý rằng mỗi bước đều chạy trong container riêng của nó. Điều này đảm bảo môi trường build của bạn luôn sạch sẽ mỗi lần chạy. Không giống như Jenkins, nơi bạn thường phải quản lý thủ công các plugin và phiên bản công cụ trên máy chủ host, Woodpecker giữ mọi thứ cô lập bên trong các Docker image.

Kiểm tra và Giám sát

Khi bạn đẩy mã (push code) lên kho lưu trữ, Woodpecker sẽ nhận được một webhook và bắt đầu pipeline. Bạn có thể theo dõi tiến độ qua giao diện web. Tuy nhiên, từ góc độ quản trị hệ thống, việc kiểm tra tình trạng của các container cũng quan trọng không kém.

Nếu một pipeline không khởi động được, nơi đầu tiên cần kiểm tra là log của agent. Agent chịu trách nhiệm kéo (pull) các image và thực thi các câu lệnh. Nếu nó không thể kết nối với Docker socket hoặc server, log sẽ cho bạn biết ngay lập tức:

docker logs -f woodpecker-agent

Để ổn định lâu dài, tôi khuyên bạn nên thiết lập một reverse proxy như Nginx hoặc Traefik với SSL. Chạy CI/CD qua HTTP thông thường là một rủi ro bảo mật, đặc biệt là khi bạn truyền các bí mật (secrets) như thông tin đăng nhập Docker Hub hoặc API key trong các bước pipeline. Woodpecker hỗ trợ quản lý bí mật thông qua giao diện của nó, cho phép bạn chèn các biến môi trường vào container mà không cần commit chúng vào hệ thống quản lý phiên bản.

Việc duy trì một hệ thống CI tự triển khai đòi hỏi một chút kỷ luật. Hãy thường xuyên dọn dẹp hệ thống Docker trên máy chủ agent để ngăn các build image cũ chiếm hết dung lượng đĩa cứng. Một công việc định kỳ (cron job) chạy docker system prune -f mỗi tuần một lần thường là đủ để giữ cho hệ thống luôn tinh gọn và nhanh chóng.

Share: