Tự build GitHub Actions Runner với Docker: Nhanh, Bảo mật và Tiết kiệm 100% chi phí

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

Triển khai Runner đầu tiên trong 5 phút

Cần một cỗ máy CI/CD “của nhà trồng được” ngay lập tức? Chỉ với một vài câu lệnh Docker, bạn có thể biến chiếc laptop cá nhân hay con VPS 5$/tháng thành một trợ lý đắc lực cho GitHub Actions. Mình mặc định bạn đã cài sẵn Docker trên máy nhé.

Bước 1: Lấy Token từ GitHub

Đầu tiên, hãy cấp “giấy thông hành” cho runner của bạn:

  1. Mở Repository trên GitHub.
  2. Tìm đến Settings > Actions > Runners.
  3. Click New self-hosted runner và chọn hệ điều hành Linux.
  4. Copy đoạn mã TOKEN ở cuối lệnh cấu hình. Đừng chạy mấy lệnh tải file .tar.gz rườm rà đó, chúng ta sẽ dùng Docker.

Bước 2: Kích hoạt Docker Container

Thay vì cài đặt thủ công, mình sẽ dùng Image từ cộng đồng đã được tối ưu cực tốt. Mở Terminal và dán lệnh sau:

docker run -d --restart always --name github-runner \
  -e REPO_URL="https://github.com/user/your-repo" \
  -e RUNNER_NAME="docker-runner-01" \
  -e RUNNER_TOKEN="TOKEN_CUA_BAN" \
  -v /var/run/docker.sock:/var/run/docker.sock \
  myoung34/github-runner:latest

Quay lại tab Settings trên trình duyệt. Nếu thấy chấm tròn màu xanh Idle hiện lên, chúc mừng bạn đã thành công!

Tại sao bạn nên chuyển sang Self-hosted Runner?

Mặc định, GitHub cấp cho mỗi tài khoản Free khoảng 2.000 phút build mỗi tháng trên máy ảo của họ. Nghe thì nhiều, nhưng thực tế sẽ rất nhanh hết nếu bạn chạy test liên tục. Dưới đây là 3 lý do mình quyết định tự build runner:

  • Vượt rào giới hạn: Không còn lo lắng về quota 2.000 phút. Bạn có thể build 24/7 mà không tốn thêm đồng nào.
  • Tăng tốc đáng kể: Máy ảo GitHub thường chỉ có 2 vCPU và 7GB RAM. Thử nghiệm trên dự án Java của mình, thời gian build giảm từ 12 phút xuống còn 4 phút khi chạy trên con server riêng có ổ NVMe.
  • Truy cập mạng nội bộ: Bạn có thể deploy trực tiếp vào database hoặc server nằm trong mạng LAN/VPC mà không cần mở port ra Internet.

Tại sao lại là Docker mà không phải Bare-metal?

Cài trực tiếp runner lên hệ điều hành (Bare-metal) là cách nhanh nhất để khiến server của bạn trở thành một “bãi rác”. Sau vài chục lần build, các thư viện thừa và file tạm sẽ chiếm sạch ổ cứng.

Dùng Docker mang lại ba lợi thế sống còn:

1. Môi trường luôn sạch (Clean Environment)

Mỗi lần restart container, bạn có ngay một môi trường mới tinh. Tình trạng “máy em chạy được mà server không chạy được” do xung đột phiên bản Node.js hay Python sẽ biến mất hoàn toàn.

2. Khả năng mở rộng tức thì

Khi dự án bước vào giai đoạn cao điểm với hàng chục Pull Request mỗi ngày, bạn chỉ cần nâng số lượng container lên. Hệ thống sẽ tự động chia tải mà không cần cấu hình lại từ đầu.

3. Phép thuật Docker-in-Docker (DinD)

Nhờ dòng lệnh mapping /var/run/docker.sock, runner bên trong container có thể điều khiển Docker của máy chủ. Điều này cho phép bạn build, tag và push các Docker Image khác một cách mượt mà như đang thao tác trực tiếp trên host.

Quản lý chuyên nghiệp bằng Docker Compose

Gõ lệnh docker run mãi thì rất mất thời gian. Hãy đóng gói cấu hình vào file docker-compose.yml để dễ quản lý và backup.

version: '3.8'
services:
  runner:
    image: myoung34/github-runner:latest
    restart: always
    environment:
      - REPO_URL=https://github.com/your-org/your-repo
      - RUNNER_TOKEN=ABC123XYZ
      - RUNNER_NAME=prod-runner
      - RUNNER_LABELS=linux,docker,high-perf
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./runner-data:/data # Cache dữ liệu để tăng tốc lần build sau

Chỉ cần docker-compose up -d, mọi thứ sẽ tự động vận hành ổn định.

Kinh nghiệm “xương máu” khi vận hành thực tế

Sau hơn một năm duy trì hệ thống runner cho team, mình rút ra 3 bài học quan trọng:

1. Đừng để ổ cứng “chết chìm” trong rác

Mỗi lần build Docker image, các layer cũ sẽ tích tụ rất nhanh. Có tuần mình quên kiểm tra, ổ cứng 100GB đã đầy sạch chỉ sau 3 ngày. Hãy thiết lập một cronjob chạy docker system prune -f vào 3 giờ sáng mỗi ngày để dọn dẹp tự động.

2. Cảnh báo bảo mật với Repo Public

Lưu ý đặc biệt: Tuyệt đối không dùng self-hosted runner cho các dự án Public. Kẻ xấu có thể tạo Pull Request chứa mã độc (như rm -rf /) và runner của bạn sẽ thực thi nó ngay trên server nhà. Chỉ dùng cho Repo Private thôi nhé.

3. Gắn Label thông minh

Để chỉ định đúng runner cho từng job, hãy dùng Label trong file workflow .github/workflows/main.yml:

jobs:
  deploy:
    runs-on: [self-hosted, high-perf]
    steps:
      - uses: actions/checkout@v3
      - name: Build App
        run: docker build -t my-app .

Việc tự vận hành runner ban đầu có vẻ tốn công, nhưng sự tự do và hiệu suất mà nó mang lại hoàn toàn xứng đáng. Hy vọng hướng dẫn này giúp bạn tối ưu hóa được quy trình CI/CD của mình hiệu quả hơn.

Share: