小型团队 CI/CD 快速搭建指南
30 分钟搭建一套完整的自动化交付流水线,适合 5-20 人团队
目录
前言
对于小型技术团队(5-20人),CI/CD 的选型往往面临两难:
- GitLab CE 功能全面但资源占用高(至少8GB内存)
- Jenkins 插件丰富但配置复杂、维护成本高
- 云托管方案(GitHub Actions、阿里云效)虽然便捷,但代码需托管在第三方平台
本文介绍一套轻量级自托管方案 ,使用 Gitea + Drone CI ,只需 2GB 内存即可运行,30分钟内完成搭建。
方案选型
核心组件
| 组件 | 选择 | 说明 |
|---|---|---|
| 代码托管 | Gitea | 轻量级 Git 服务,功能媲美 GitLab,资源占用仅为其 10% |
| CI/CD 引擎 | Drone CI | 云原生流水线引擎,基于 Docker,配置简单直观 |
| 镜像仓库 | Registry | Docker 官方分发版,轻量可靠 |
| 可视化管理 | Portainer | Docker 容器管理面板,降低运维门槛 |
架构图
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 开发者 │────▶│ Gitea │────▶│ Drone Server│
│ (Git Push) │ │ (代码仓库) │ │ (调度中心) │
└─────────────┘ └─────────────┘ └──────┬──────┘
│
▼
┌─────────────┐
│ Docker Runner│
│ (执行构建) │
└──────┬──────┘
│
┌──────────────────────────┼──────────────────────────┐
▼ ▼ ▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 单元测试 │ │ 构建镜像 │ │ 部署应用 │
│ (npm test) │ │(docker build)│ │ (SSH/RSYNC)│
└─────────────┘ └──────┬──────┘ └─────────────┘
│
▼
┌─────────────┐
│ Registry │
│ (镜像仓库) │
└─────────────┘
快速搭建步骤
第一步:准备环境
硬件要求:
- CPU:4核+
- 内存:8GB+(运行后实际占用约 2GB)
- 磁盘:100GB SSD
- 系统:Ubuntu 20.04+ / CentOS 7+ / 任意支持 Docker 的系统
安装 Docker & Docker Compose:
bash
# 安装 Docker
curl -fsSL https://get.docker.com | sh
sudo systemctl enable docker && sudo systemctl start docker
# 安装 Docker Compose
sudo curl -L "https://github.com/docker/compose/releases/download/v2.24.0/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
# 验证安装
docker --version
docker-compose --version
第二步:一键启动所有服务
创建项目目录并编写 docker-compose.yml:
bash
mkdir -p ~/cicd && cd ~/cicd
cat > docker-compose.yml << 'EOF'
version: '3.8'
services:
# 1. 代码仓库 - Gitea
gitea:
image: gitea/gitea:1.21
container_name: gitea
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=sqlite3
- GITEA__server__DOMAIN=${SERVER_IP:-localhost}
- GITEA__server__ROOT_URL=http://${SERVER_IP:-localhost}:3000
- GITEA__server__SSH_PORT=2222
- GITEA__security__INSTALL_LOCK=true
- GITEA__service__DISABLE_REGISTRATION=false
volumes:
- ./gitea/data:/data
ports:
- "3000:3000"
- "2222:22"
restart: unless-stopped
# 2. CI/CD 引擎 - Drone Server
drone-server:
image: drone/drone:2
container_name: drone-server
ports:
- "8080:80"
volumes:
- ./drone/data:/data
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_GITEA_SERVER=http://gitea:3000
- DRONE_GITEA_CLIENT_ID=${DRONE_GITEA_CLIENT_ID}
- DRONE_GITEA_CLIENT_SECRET=${DRONE_GITEA_CLIENT_SECRET}
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
- DRONE_SERVER_HOST=${SERVER_IP:-localhost}:8080
- DRONE_SERVER_PROTO=http
- DRONE_USER_CREATE=username:admin,admin:true
restart: unless-stopped
# 3. Drone 执行器
drone-runner:
image: drone/drone-runner-docker:1
container_name: drone-runner
volumes:
- /var/run/docker.sock:/var/run/docker.sock
environment:
- DRONE_RPC_PROTO=http
- DRONE_RPC_HOST=drone-server
- DRONE_RPC_SECRET=${DRONE_RPC_SECRET}
- DRONE_RUNNER_CAPACITY=2
- DRONE_RUNNER_NAME=runner-1
restart: unless-stopped
depends_on:
- drone-server
# 4. Docker 镜像仓库
registry:
image: registry:2
container_name: registry
ports:
- "5000:5000"
volumes:
- ./registry/data:/var/lib/registry
environment:
- REGISTRY_STORAGE_DELETE_ENABLED=true
restart: unless-stopped
# 5. Docker 管理面板
portainer:
image: portainer/portainer-ce:latest
container_name: portainer
ports:
- "9000:9000"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./portainer/data:/data
restart: unless-stopped
EOF
创建环境变量文件:
bash
cat > .env << 'EOF'
# 服务器IP地址(改成你的服务器IP或域名)
SERVER_IP=192.168.1.100
# Drone RPC 密钥(自动生成)
DRONE_RPC_SECRET=$(openssl rand -hex 16)
# Gitea OAuth 配置(首次启动后获取)
DRONE_GITEA_CLIENT_ID=your-client-id
DRONE_GITEA_CLIENT_SECRET=your-client-secret
EOF
启动服务:
bash
docker-compose up -d
# 查看服务状态
docker-compose ps
第三步:配置 Gitea OAuth
- 访问 Gitea:http://your-server-ip:3000
- 首次配置:按向导创建管理员账号
- 创建 OAuth 应用 :
- 进入 管理后台 → 应用管理 → 创建 OAuth2 应用
- 应用名称:
Drone CI - 重定向 URI:
http://your-server-ip:8080/login
- 获取密钥 :复制生成的 Client ID 和 Client Secret
- 更新配置 :修改
.env文件,填入获取的密钥 - 重启 Drone :
docker-compose restart drone-server
第四步:配置项目流水线
在代码仓库根目录创建 .drone.yml:
yaml
kind: pipeline
type: docker
name: build-and-deploy
# 全局环境变量
environment:
APP_NAME: myapp
REGISTRY: registry:5000
steps:
# 步骤1:依赖安装与单元测试
- name: test
image: node:20-alpine
commands:
- npm ci --cache .npm --prefer-offline
- npm run lint
- npm run test:unit
volumes:
- name: npm-cache
path: /root/.npm
# 步骤2:构建应用
- name: build
image: node:20-alpine
commands:
- npm ci
- npm run build
when:
event: [push, tag]
# 步骤3:构建并推送 Docker 镜像
- name: docker
image: plugins/docker
settings:
repo: ${DRONE_REPO_NAME}
tags:
- ${DRONE_COMMIT_SHA:0:8}
- latest
registry: registry:5000
insecure: true
when:
branch: [main, develop]
# 步骤4:部署到测试环境(develop分支自动部署)
- name: deploy-staging
image: appleboy/drone-ssh
settings:
host: staging.yourcompany.com
username: deploy
password:
from_secret: ssh_password
script:
- docker pull registry:5000/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA:0:8}
- docker stop ${DRONE_REPO_NAME} || true
- docker rm ${DRONE_REPO_NAME} || true
- docker run -d --name ${DRONE_REPO_NAME} -p 8080:8080 registry:5000/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA:0:8}
when:
branch: develop
# 步骤5:部署到生产环境(main分支需手动确认)
- name: deploy-production
image: appleboy/drone-ssh
settings:
host: prod.yourcompany.com
username: deploy
key:
from_secret: ssh_key
script:
- docker pull registry:5000/${DRONE_REPO_NAME}:${DRONE_COMMIT_SHA:0:8}
- docker-compose -f /opt/app/docker-compose.yml up -d
when:
branch: main
# 步骤6:发送通知
- name: notify
image: plugins/webhook
settings:
urls:
from_secret: webhook_url
template: |
{
"msgtype": "text",
"text": {
"content": "构建{{#success build.status}}成功✅{{else}}失败❌{{/success}}: {{repo.name}} #{{build.number}}"
}
}
when:
status: [success, failure]
# 缓存配置
volumes:
- name: npm-cache
host:
path: /tmp/npm-cache
# 触发条件
trigger:
branch:
- main
- develop
- feature/*
第五步:配置 Secrets
在 Drone Web 界面(http://your-server-ip:8080)中为项目添加 Secrets:
| Secret 名称 | 说明 | 获取方式 |
|---|---|---|
ssh_password |
服务器 SSH 密码 | 部署服务器密码 |
ssh_key |
SSH 私钥 | cat ~/.ssh/id_rsa |
webhook_url |
钉钉/飞书机器人地址 | 群设置 → 机器人管理 |
流水线配置详解
目录结构示例
myproject/
├── .drone.yml # CI/CD 配置文件
├── Dockerfile # 应用容器化
├── docker-compose.yml # 生产部署配置
├── package.json
├── src/
└── tests/
Dockerfile 示例
dockerfile
# 构建阶段
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# 运行阶段
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules ./node_modules
COPY package.json ./
EXPOSE 8080
CMD ["node", "dist/main.js"]
多环境部署策略
┌─────────┐ ┌──────────┐ ┌─────────┐
│ Feature │────▶│ Develop │────▶│ Main │
│ Branch │ │ Branch │ │ Branch │
└────┬────┘ └────┬─────┘ └────┬────┘
│ │ │
▼ ▼ ▼
┌─────────┐ ┌──────────┐ ┌─────────┐
│ CI测试 │ │ 测试环境 │ │ 生产环境 │
│ (自动化) │ │(自动部署) │ │(手动确认)│
└─────────┘ └──────────┘ └─────────┘
替代方案对比
| 方案 | 适用场景 | 资源占用 | 搭建时间 | 维护成本 |
|---|---|---|---|---|
| Gitea + Drone | 小团队自托管 | 2GB 内存 | 30分钟 | ⭐⭐ 低 |
| GitLab CE | 需要完整 DevOps 平台 | 8GB+ 内存 | 2小时+ | ⭐⭐⭐⭐ 高 |
| GitHub Actions | 代码已在 GitHub | 0(托管) | 10分钟 | ⭐ 极低 |
| 阿里云效 | 国内团队、一站式 | 0(托管) | 30分钟 | ⭐⭐ 低 |
| Jenkins | 复杂定制需求 | 4GB+ 内存 | 1小时+ | ⭐⭐⭐⭐⭐ 极高 |
| 极狐 GitLab | 国内企业合规 | 托管/自建 | 1小时 | ⭐⭐⭐ 中 |
硬件配置建议
最低配置(5人以下团队)
yaml
服务器配置:
CPU: 4核
内存: 8GB
磁盘: 100GB SSD
带宽: 5Mbps
预估成本:
云服务器: 约 3000元/年
域名+证书: 约 500元/年
推荐配置(5-20人团队)
yaml
服务器配置:
CPU: 8核
内存: 16GB
磁盘: 200GB SSD
带宽: 10Mbps
预估成本:
云服务器: 约 6000元/年
域名+证书: 约 500元/年
备份存储: 约 1000元/年
极简方案:纯 Git Hook(1-3人团队)
如果团队规模极小,可使用以下 Shell 脚本方案:
部署脚本 (保存到服务器 /opt/cicd/deploy.sh):
bash
#!/bin/bash
set -e
APP_NAME=$1
GIT_URL=$2
BRANCH=$3
PORT=$4
DEPLOY_DIR="/opt/apps/$APP_NAME"
echo "=== 开始部署 $APP_NAME ==="
# 更新代码
if [ ! -d "$DEPLOY_DIR" ]; then
git clone -b $BRANCH $GIT_URL $DEPLOY_DIR
else
cd $DEPLOY_DIR && git pull origin $BRANCH
fi
# 构建
cd $DEPLOY_DIR
docker build -t $APP_NAME:latest .
# 重启容器
docker stop $APP_NAME 2>/dev/null || true
docker rm $APP_NAME 2>/dev/null || true
docker run -d --name $APP_NAME -p $PORT:8080 --restart always $APP_NAME:latest
echo "=== 部署完成 ==="
客户端 Git Hook (.git/hooks/post-push):
bash
#!/bin/bash
ssh user@server "/opt/cicd/deploy.sh myapp git@server:team/myapp.git main 8080"
总结
本文介绍了三种适合小型团队的 CI/CD 方案:
| 方案 | 适用人数 | 搭建时间 | 核心优势 |
|---|---|---|---|
| Shell Hook | 1-3人 | 5分钟 | 极简,零依赖 |
| Gitea + Drone | 5-20人 | 30分钟 | 功能完整,资源友好 |
| 云托管服务 | 任意规模 | 10分钟 | 零维护,弹性扩容 |
对于大多数小型团队,Gitea + Drone 是最佳平衡点:
- ✅ 代码自主可控(自托管)
- ✅ 资源占用低(2GB内存足够)
- ✅ 配置简单(YAML声明式配置)
- ✅ 扩展性强(基于Docker插件生态)
当团队规模扩大到 20人以上,或需要更复杂的项目管理功能时,可以考虑迁移到 GitLab 或采用云托管方案。