Gitea: 一个用Go语言编写的轻量级代码托管平台,可以看作是极度轻量化的GitLab。功能包括Git仓库管理、Issue、PR、Webhook等,核心功能一个不少。其内存占用通常在50-100MB左右,非常适合小服务器。
Drone: 一个用Go语言编写的基于Docker容器的CI/CD平台。它通过Gitea的Webhook触发构建流程。它的运行模式是每个构建步骤都在一个独立的临时容器中运行,构建完成后容器销毁,资源立即释放,非常高效。
1. 创建持久化数据目录
1 # 创建主目录 2 mkdir -p /opt/docker/gitea 3 mkdir -p /opt/docker/drone 4 5 # 创建数据目录 6 mkdir -p /opt/docker/gitea/data 7 mkdir -p /opt/docker/gitea/config 8 mkdir -p /opt/docker/drone/data
2. 拉取gitea,drone镜像 (https://hub.docker.com 查询版本)
#镜像拉取失败,可使用阿里云镜像加速服务 sudo vim /etc/docker/daemon.json "registry-mirrors": [ "https://<你的ID,去容器镜像服务-镜像工具-镜像加速器获取>.mirror.aliyuncs.com"]
sudo docker pull gitea/gitea
sudo docker pull drone/drone
# 设置目录权限
sudo chown -R 1000:1000 /opt/docker/gitea
sudo chown -R 1000:1000 /opt/docker/drone
3. 直接使用docker-compose.yaml
version: '3.8'services:# Gitea 服务gitea:image: gitea/gitea:latestcontainer_name: giteaenvironment:- USER_UID=1000- USER_GID=1000- DB_TYPE=sqlite3restart: alwaysvolumes:- /opt/docker/gitea/data:/data- /opt/docker/gitea/config:/etc/gitea- /etc/timezone:/etc/timezone:ro- /etc/localtime:/etc/localtime:roports:- "3000:3000"- "2222:22"networks:- gitea-network# Drone Serverdrone:image: drone/drone:latestcontainer_name: droneenvironment:- DRONE_GITEA_SERVER=http://gitea的IP:3000- DRONE_GITEA_CLIENT_ID=gitea中auth2.0的客户端ID- DRONE_GITEA_CLIENT_SECRET=gitea中auth2.0的客户端密钥- DRONE_RPC_SECRET=RPC密钥- DRONE_SERVER_HOST=服务器IP:8080- DRONE_SERVER_PROTO=httpvolumes:- /opt/docker/drone/data:/datarestart: alwaysports:- "8080:80"depends_on:- giteanetworks:- gitea-network# Drone Runnerdrone-runner:image: drone/drone-runner-docker:latestcontainer_name: drone-runnerenvironment:- DRONE_RPC_PROTO=http- DRONE_RPC_HOST=drone- DRONE_RPC_SECRET=RPC密钥- DRONE_RUNNER_CAPACITY=2- DRONE_RUNNER_NAME=my-runnervolumes:- /var/run/docker.sock:/var/run/docker.sockrestart: alwaysdepends_on:- dronenetworks:- gitea-networknetworks:gitea-network:driver: bridge
3.1 先运行gitea容器后访问 http://your-server-ip:3000 完成基本配置
# 先运行gitea容器
sudo docker-compose up -d gitea
# 配置Gitea OAuth应用
# 登录Gitea后,点击右上角用户头像 -> 设置 -> 应用
# 创建新的OAuth2应用程序:
# 应用名称: Drone CI
# 重定向URI: http://your-server-ip:8080/login,这里的地址由docker-compose.yaml中的drone里的DRONE_SERVER_PROTO+DRONE_SERVER_HOST/login组成
# 记录生成的客户端ID和客户端密钥
# 修改docker-compose.yaml中对应的值
sudo docker-compose up -d
3.2 访问drone:8080,首次访问Drone时,需要使用Gitea授权
3.3 在Drone中同步Gitea的仓库
3.4 在Gitea仓库中添加.drone.yaml文件来定义CI/CD流程, 文档地址 https://docs.drone.io/
# 示例
kind: pipeline
type: docker
name: nodejs-ci-cd# 触发条件
trigger:branch:- masterevent:- push- pull_request# 环境变量
environment:NODE_VERSION: 22APP_NAME: my-node-appDOCKER_IMAGE: your-username/${APP_NAME}REGISTRY: registry.example.com# 步骤定义
steps:# 第一步:安装依赖并缓存- name: install-dependenciesimage: node:${NODE_VERSION}-alpinecommands:- npm ci- npm cache verifyvolumes:- name: npm-cachepath: /root/.npm# 第二步:代码质量检查- name: code-qualityimage: node:${NODE_VERSION}-alpinecommands:- npm run lintdepends_on: [install-dependencies]# 第三步:运行测试- name: run-testsimage: node:${NODE_VERSION}-alpinecommands:- npm test- npm run test:coveragedepends_on: [install-dependencies]environment:NODE_ENV: testDATABASE_URL: postgresql://test:test@postgres:5432/testwhen:event: [push, pull_request]# 第四步:安全扫描- name: security-scanimage: node:${NODE_VERSION}-alpinecommands:- npm audit --audit-level=moderate- npx snyk test --severity-threshold=highdepends_on: [install-dependencies]when:event: pushbranch: [master, develop]# 第五步:构建应用程序- name: build-appimage: node:${NODE_VERSION}-alpinecommands:- npm run builddepends_on: [run-tests]environment:NODE_ENV: productionwhen:event: pushbranch: [master, develop]# 第六步:构建 Docker 镜像- name: build-docker-imageimage: plugins/dockersettings:repo: ${DOCKER_IMAGE}tags:- latest- ${DRONE_COMMIT_SHA:0:8}- ${DRONE_BRANCH//\//-}registry: ${REGISTRY}username:from_secret: docker_usernamepassword:from_secret: docker_passwordbuild_args:- NODE_ENV=productiondepends_on: [build-app]when:event: pushbranch: [master, develop]# 第七步:扫描 Docker 镜像安全漏洞- name: scan-docker-imageimage: aquasec/trivy:latestcommands:- trivy image --exit-code 1 --severity HIGH,CRITICAL ${REGISTRY}/${DOCKER_IMAGE}:${DRONE_COMMIT_SHA:0:8}depends_on: [build-docker-image]when:event: pushbranch: master# 第八步:部署到开发环境- name: deploy-to-devimage: appleboy/drone-sshsettings:host: dev.example.comusername: deploykey:from_secret: ssh_key_devscript:- docker pull ${REGISTRY}/${DOCKER_IMAGE}:${DRONE_COMMIT_SHA:0:8}- docker stop ${APP_NAME} || true- docker rm ${APP_NAME} || true- docker run -d --name ${APP_NAME} -p 3000:3000 --env-file /app/.env ${REGISTRY}/${DOCKER_IMAGE}:${DRONE_COMMIT_SHA:0:8}depends_on: [build-docker-image]when:event: pushbranch: develop# 第九步:部署到生产环境- name: deploy-to-prodimage: appleboy/drone-sshsettings:host: prod.example.comusername: deploykey:from_secret: ssh_key_prodscript:- docker pull ${REGISTRY}/${DOCKER_IMAGE}:${DRONE_COMMIT_SHA:0:8}- docker stop ${APP_NAME} || true- docker rm ${APP_NAME} || true- docker run -d --name ${APP_NAME} -p 3000:3000 --env-file /app/.env ${REGISTRY}/${DOCKER_IMAGE}:${DRONE_COMMIT_SHA:0:8}- docker system prune -afdepends_on: [scan-docker-image]when:event: pushbranch: master# 第十步:发送通知- name: notify-slackimage: plugins/slacksettings:webhook:from_secret: slack_webhookchannel: deploymentstemplate: >{{#success build.status}}✅ 部署成功! {{repo.name}} #{{build.number}} ({{commit.branch}}) 已部署到{{#eq commit.branch "master"}}生产环境{{else}}开发环境{{/eq}}Commit: {{commit.message}} by {{commit.author}}{{else}}❌ 部署失败! {{repo.name}} #{{build.number}} ({{commit.branch}}) 需要检查Commit: {{commit.message}} by {{commit.author}}{{/success}}when:status: [success, failure]# 缓存配置
volumes:- name: npm-cachetemp: {}# 服务容器(用于测试)
services:- name: postgresimage: postgres:13-alpineenvironment:POSTGRES_USER: testPOSTGRES_PASSWORD: testPOSTGRES_DB: test- name: redisimage: redis:6-alpine
不使用docker-compose的话,先部署Gitea(代码托管平台)
# 运行Gitea容器 docker run -d \--name=gitea \--network=gitea-network \-p 3001:3000 \-p 2222:22 \-v /opt/docker/gitea/data:/data \-v /opt/docker/gitea/config:/etc/gitea \-e USER_UID=1000 \-e USER_GID=1000 \-e DB_TYPE=sqlite3 \--restart=always \gitea/gitea:latest
4.1 也是一样先启动gitea容器 完成基本配置
# 创建Docker网络
sudo docker network create gitea-network
4.2 部署Drone Server(CI/CD平台的服务端)
sudo docker run -d \--name=drone \--network=gitea-network \-v /opt/docker/drone/data:/data \-e DRONE_GITEA_SERVER=http://gitea服务器地址:3001 \-e DRONE_GITEA_CLIENT_ID=gitea客户端ID\-e DRONE_GITEA_CLIENT_SECRET=gitea客户端密钥\-e DRONE_RPC_SECRET=RPC密钥\-e DRONE_SERVER_HOST=drone服务器地址:8080 \-e DRONE_SERVER_PROTO=http \-p 8080:80 \--restart=always \drone/drone:latest
# 运行drone runner容器 sudo docker run -d \--name=drone-runner \--network=gitea-network \-v /var/run/docker.sock:/var/run/docker.sock \-e DRONE_RPC_PROTO=http \-e DRONE_RPC_HOST=drone \-e DRONE_RPC_SECRET=RPC密钥\-e DRONE_RUNNER_CAPACITY=2 \-e DRONE_RUNNER_NAME=my-runner \--restart=always \drone/drone-runner-docker:latest