ติดตั้ง Drone CI CD Pipeline บน VPS
Drone CI เป็น platform สำหรับ continuous integration และ continuous deployment (CI/CD) ที่ใช้งานง่ายและมีความยืดหยุ่นสูง รองรับการเชื่อมต่อกับ GitHub, GitLab, Gitea และ Bitbucket ได้ทำให้เป็นตัวเลือกยอดนิยมสำหรับการ automate build, test และ deploy ของโปรเจกต์ ในบทความนี้เราจะสอนวิธีการติดตั้ง Drone CI บน VPS แบบ self-hosted พร้อมการตั้งค่า Docker runner เพื่อ execute pipeline ของคุณ
ความต้องการของระบบ
ก่อนเริ่มติดตั้ง Drone CI คุณจำเป็นต้องมีสิ่งต่อไปนี้:
- Docker Engine 18.09+ สำหรับ run Drone server และ runner
- Docker Compose 1.25+ (optional แต่แนะนำเพื่อความสะดวก)
- CPU cores อย่างน้อย 2 cores (4+ ขึ้นไปจะดีกว่า)
- RAM อย่างน้อย 2GB (4GB+ ขึ้นไปสำหรับการใช้งานหนักๆ)
- Disk space อย่างน้อย 10GB สำหรับ container images และ logs
- Ports เปิด 80 และ 443 สำหรับ web interface และ webhooks
- Git repository host GitHub, Gitea, GitLab หรือ Bitbucket
ติดตั้ง Docker และ Docker Compose
Drone CI ทำงานบน Docker ดังนั้นจำเป็นต้องติดตั้ง Docker ก่อน หากคุณยังไม่มี Docker ให้รัน commands ต่อไปนี้:
สำหรับ Ubuntu/Debian:
sudo apt-get update
sudo apt-get install -y docker.io docker-compose
sudo usermod -aG docker $USER
newgrp docker
สำหรับ CentOS/RHEL 7:
sudo yum install -y docker
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo systemctl start docker
sudo usermod -aG docker $USER
สำหรับ CentOS/RHEL 8+:
sudo dnf install -y docker podman-docker
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
sudo systemctl start docker
sudo usermod -aG docker $USER
ตรวจสอบว่า Docker ทำงานได้:
docker --version
docker-compose --version
docker run hello-world
ดาวน์โหลดและติดตั้ง Drone Server
เราจะสร้าง directory สำหรับ Drone server และเตรียม docker-compose configuration file:
mkdir -p ~/drone-ci
cd ~/drone-ci
สร้าง docker-compose.yml ด้วย command ต่อไปนี้:
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
drone-server:
image: drone/drone:latest
container_name: drone-server
ports:
- "80:80"
- "443:443"
environment:
DRONE_SERVER_HOST: ci.yourdomain.com
DRONE_SERVER_PROTO: https
DRONE_RPC_SECRET: $(openssl rand -hex 16)
DRONE_GITHUB_CLIENT_ID: your_github_client_id
DRONE_GITHUB_CLIENT_SECRET: your_github_client_secret
DRONE_AGENTS_ENABLED: true
DRONE_USER_CREATE: username:admin,machine:false,admin:true
volumes:
- ./data:/data
- /var/run/docker.sock:/var/run/docker.sock
restart: always
drone-runner:
image: drone/drone-runner-docker:latest
container_name: drone-runner
depends_on:
- drone-server
environment:
DRONE_RPC_HOST: drone-server
DRONE_RPC_PROTO: http
DRONE_RPC_SECRET: $(openssl rand -hex 16)
DRONE_RUNNER_CAPACITY: 2
DRONE_RUNNER_NAME: runner-1
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: always
networks:
- drone-network
networks:
drone-network:
driver: bridge
EOF
ci.yourdomain.com เป็นโดเมนจริงของคุณ และเพิ่มค่า GitHub OAuth credentials ลงไปตั้งค่า Drone Server กับ GitHub
หากคุณต้องการเชื่อมต่อ Drone กับ GitHub จะต้องสร้าง OAuth application ก่อน:
- ไปที่ GitHub Settings › Developer settings › OAuth Apps
- คลิก "New OAuth App"
- ใส่ข้อมูลดังนี้:
- Application name: Drone CI
- Homepage URL: https://ci.yourdomain.com
- Authorization callback URL: https://ci.yourdomain.com/login/oauth/github
- คลิก "Register application" เพื่อรับ Client ID และ Client Secret
นำค่า Client ID และ Client Secret ไปใส่ในไฟล์ docker-compose.yml:
DRONE_GITHUB_CLIENT_ID: [your-github-client-id]
DRONE_GITHUB_CLIENT_SECRET: [your-github-client-secret]
สำหรับการเชื่อมต่อกับ Gitea ให้แทนที่ environment variables เหล่านี้:
DRONE_GITEA_SERVER: https://gitea.yourdomain.com
DRONE_GITEA_CLIENT_ID: your_gitea_client_id
DRONE_GITEA_CLIENT_SECRET: your_gitea_client_secret
เริ่มต้นบริการ Drone Server
เมื่อตั้งค่า docker-compose.yml เสร็จแล้ว ให้เริ่มบริการด้วย command:
cd ~/drone-ci
docker-compose up -d
ตรวจสอบว่า container ทำงานอยู่:
docker-compose ps
docker logs drone-server
docker logs drone-runner
ติดตั้ง Drone Runner
Drone Runner เป็น agent ที่รับหน้าที่ execute pipeline jobs หากใช้ docker-compose setup ข้างต้นแล้ว runner จะติดตั้งไปพร้อมกันเลย แต่หากต้องการติดตั้ง runner แยกต่างหากบนเครื่องอื่น สามารถทำได้ดังนี้:
mkdir -p ~/drone-runner
cd ~/drone-runner
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
drone-runner:
image: drone/drone-runner-docker:latest
container_name: drone-runner
environment:
DRONE_RPC_HOST: drone-server-ip:80
DRONE_RPC_PROTO: http
DRONE_RPC_SECRET: your-rpc-secret-here
DRONE_RUNNER_CAPACITY: 2
DRONE_RUNNER_NAME: runner-remote-1
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: always
EOF
docker-compose up -d
DRONE_RPC_SECRET ต้องตรงกับที่กำหนดใน drone-server ถึงจะสื่อสารกันได้สร้าง .drone.yml Pipeline Configuration
ในหน้าที่ repository ของคุณ สร้างไฟล์ .drone.yml เพื่อกำหนด pipeline steps:
kind: pipeline
type: docker
name: default
steps:
- name: test
image: node:16
commands:
- npm install
- npm run test
- name: build
image: node:16
commands:
- npm run build
- name: deploy
image: alpine:latest
commands:
- echo "Deploying to production..."
- apk add --no-cache curl
- curl -X POST https://deploy.yourdomain.com/webhook
trigger:
branch:
- main
event:
- push
- pull_request
ตัวอย่าง pipeline ที่มีหลายขั้นตอนและเงื่อนไข:
kind: pipeline
type: docker
name: full-pipeline
steps:
- name: checkout
image: alpine/git
commands:
- git clone $DRONE_GIT_HTTP_URL .
- git checkout $DRONE_COMMIT
- name: lint
image: node:16
commands:
- npm install
- npm run lint
- name: unit-tests
image: node:16
commands:
- npm test
- name: build-image
image: plugins/docker
settings:
username:
from_secret: docker_username
password:
from_secret: docker_password
repo: your-docker-repo/app
tags: latest,${DRONE_COMMIT_SHA:0:7}
- name: deploy-staging
image: alpine:latest
environment:
DEPLOY_TOKEN:
from_secret: deploy_token
commands:
- apk add --no-cache curl
- curl -X POST https://staging-deploy.yourdomain.com/webhook -d "token=$DEPLOY_TOKEN"
when:
branch: main
event: push
- name: notify
image: plugins/slack
settings:
webhook:
from_secret: slack_webhook
message: "Pipeline completed for $${DRONE_BRANCH}"
when:
status:
- success
- failure
trigger:
branch:
- main
- develop
event:
- push
- pull_request
- tag
ตรวจสอบว่า Drone ทำงานถูกต้อง
เมื่อติดตั้งเสร็จแล้ว ให้ตรวจสอบว่า Drone ทำงานถูกต้องด้วยคำสั่งต่อไปนี้:
ตรวจสอบ Drone Server API:
curl -s http://localhost/api/version | jq .
ผลลัพธ์ที่เป็นปกติจะเป็นเช่นนี้:
{
"version": "2.11.0"
}
ตรวจสอบ Docker logs:
docker logs drone-server | tail -20
docker logs drone-runner | tail -20
เข้าถึง Web Interface:
เปิด browser และเข้าที่ https://ci.yourdomain.com จากนั้นใช้บัญชี GitHub หรือ Gitea ของคุณเข้าสู่ระบบ
ทดสอบ Pipeline:
cd /path/to/your-repo
git add .drone.yml
git commit -m "Add Drone CI configuration"
git push origin main
ไปที่ Drone web UI และตรวจสอบว่า pipeline trigger ทำงานโดยอัตโนมัติเมื่อ push code
แก้ปัญหาที่พบบ่อย
ข้อผิดพลาด: DRONE_RPC_SECRET mismatch
เมื่อ drone-runner ไม่สามารถเชื่อมต่อกับ drone-server ได้ log จะแสดงข้อความเช่น:
ERROR client: 401 Unauthorized: invalid rpc secret
วิธีแก้: ตรวจสอบว่า DRONE_RPC_SECRET ใน docker-compose.yml ของ server และ runner ตรงกันหรือไม่ ทั้งสองต้องใช้ค่าเดียวกันเท่านั้น
ข้อผิดพลาด: GitHub OAuth not working
ถ้าเมื่อ login ด้วย GitHub ปรากฏข้อผิดพลาด ให้ตรวจสอบ:
docker logs drone-server | grep -i "oauth\|auth\|github"
วิธีแก้: ตรวจสอบว่า Client ID และ Client Secret ถูกต้องและตรงกับที่กำหนดไว้ใน GitHub Developer Settings นอกจากนี้ต้องแน่ใจว่า Authorization callback URL ตรงกับ https://ci.yourdomain.com/login/oauth/github
ข้อผิดพลาด: Pipeline not triggering
ถ้าสร้าง .drone.yml แล้ว push code แต่ pipeline ไม่ trigger ให้ตรวจสอบ:
docker logs drone-server | grep webhook
docker logs drone-server | grep trigger
วิธีแก้: ไปยัง GitHub repository Settings › Webhooks และตรวจสอบว่ามี webhook ของ Drone อยู่ หากไม่มี ให้ดำเนินการ re-sync ใน Drone UI โดยไปที่ repository settings และคลิก "Sync"
ข้อผิดพลาด: Docker image pull timeout
เมื่อ pipeline ติด error เช่น:
Error response from daemon: pull access denied for node:16, repository does not exist
วิธีแก้: ตรวจสอบการเชื่อมต่อ internet ของ VPS ว่าสามารถ pull docker images ได้หรือไม่ ลองทดสอบด้วยคำสั่ง:
docker pull node:16
คำถามที่พบบ่อย
สามารถใช้ Drone CI กับหลายๆ repository พร้อมกันได้หรือไม่?
ได้ครับ Drone CI สามารถใช้ได้กับหลายๆ repository พร้อมกัน แต่ความสามารถในการ execute job พร้อมกันจะขึ้นอยู่กับค่า DRONE_RUNNER_CAPACITY หากคุณตั้ง capacity เป็น 2 แสดงว่าสามารถ execute 2 jobs พร้อมกันได้เท่านั้น หากต้องการ execute มากกว่านั้น ให้เพิ่มค่านี้หรือเพิ่ม runners เพิ่มเติม
วิธีตั้งค่า HTTPS/SSL สำหรับ Drone CI ด้วย Let's Encrypt?
สามารถใช้ reverse proxy อย่าง Nginx หรือ Caddy เพื่อ terminate SSL ได้ ตัวอย่างการใช้ Caddy:
cat > ~/drone-ci/Caddyfile << 'EOF'
ci.yourdomain.com {
reverse_proxy localhost:80
}
EOF
จากนั้นเพิ่ม Caddy service ในไฟล์ docker-compose.yml และเพิ่ม Caddy container ในการเริ่มบริการ
วิธีเชื่อมต่อ Drone CI กับ self-hosted Git server เช่น Gitea?
ใช้ environment variables ต่อไปนี้แทน GitHub:
DRONE_GITEA_SERVER: https://gitea.yourdomain.com
DRONE_GITEA_CLIENT_ID: [your-gitea-oauth-client-id]
DRONE_GITEA_CLIENT_SECRET: [your-gitea-oauth-client-secret]
วิธีสร้าง OAuth application ใน Gitea นั้นให้ไปที่ Gitea Admin › Applications › Create OAuth 2.0 Application และกรอกข้อมูลคล้ายกับการสร้างใน GitHub