@@ -1,312 +1,201 @@
# CI/CD 部署指南 (OneDev + Docker)
# CI/CD 部署指南 (OneDev + Docker Compose )
## 1. 简介
## 1. 简介
本文档旨在指导如何为 `mqtt-charging-system` 项目(包含 `springboot-init-main` 后端和 `charging_web_app` 前端)配置一套基于 OneDev 和 Docker 的持续集成与持续部署 (CI/CD) 流程。实现目标是当代码提交到 OneDev 管理的 Git 仓库的特定分支(如 `main` )后,自动触发构建、 Docker 镜像打包与推送,并最终自动部署到线上 服务器 。
本文档旨在指导如何为 `mqtt-charging-system` 项目(包含 `springboot-init-main` 后端和 `charging_web_app` 前端)配置一套基于 OneDev 和 Docker Compose 的持续集成与持续部署 (CI/CD) 流程。实现目标是当代码提交到 OneDev 内置 Git 仓库的特定分支后,自动触发 OneDev 流水线,该流水线负责在部署服务器上构建应用 Docker 镜像,并使用 Docker Compose 重启包括数据库、MQTT Broker 和应用在内的所有 服务。
**采用技术栈:**
**采用技术栈:**
* **一体化 DevOps 平台 ( 代码仓库, CI/CD) ** : OneDev
* **CI/CD 平台与 代码仓库** : OneDev (自建,包含内置 Git 服务)
* **容器化** : Docker & Docker Compose
* **构建与部署脚本** : `.onedev-buildspec.yml` (OneDev 流水线定义)
* **部署目标 ** : 运行 Docker 的 Linux 服务器
* **容器化 ** : Docker
* **服务编排** : Docker Compose
* **部署目标** : 运行 OneDev Agent 和 Docker 的 Linux 服务器
## 2. 先决条件
## 2. 先决条件
在开始配置 CI/CD 流程之前,请确保以下条件已满足:
在开始配置此部署 流程之前,请确保以下条件已满足:
* **OneDev 服务器** :
* **OneDev 服务器** :
* 已成功搭建 并运行 OneDev 服务。您可以从 [https://onedev.io/ ](https://onedev.io/ ) 下载并按照官方文档进行安装(通常作为 Docker 容器或直接运行 JAR 包) 。
* 已在一台服务器上成功安装 并运行 OneDev 服务。参考 OneDev 官方文档 ( [https://onedev.io/docs/installation ](https://onedev.io/docs/installation )) 进行安装 。
* 项目代码已在 OneDev 中创建或导入 。
* OneDev 服务器应具有足够的资源( CPU、内存、磁盘) 。
* **线上应用服务器 ** :
* **线上应用/部署服务器 (OneDev Agent 服务器) ** :
* 一台或多台 Linux 服务器,用于运行前端和后端应用容 器。
* 一台 Linux 服务器,用于运行 OneDev Agent、构建 Docker 镜像以及通过 Docker Compose 运行所有服务容器 (数据库、Broker、后端、前端)。此服务器可以是 OneDev 服务器本身(不推荐用于生产),也可以是独立的机 器。
* 服务器已安装 Docker Engine 和 Docker Compose。
* 服务器已安装 Docker Engine, Docker Compose, 和 Git 。
* 服务器具有 SSH 访问权限,并为 CI/CD 工具准备了 SSH 用户( 推荐使用密钥认证) 。OneDev 的执行器 (Executor) 将通过此用户连接服务器 。
* 服务器防火墙已配置,允许访问应用所需端口(例如后端 7529, 前端 3000, MQTT 1883, 18083 等),以及 OneDev Agent 与 OneDev Server 通信的端口 。
* 服务器防火墙已配置,允许访问应用所需端口(例如后端 7529, 前端 3000) 以及可能的反向代理端口( 如 80, 443) 。
* **对 Docker, Docker Compose, Git, YAML 和 OneDev 有基本了解** 。
* **Docker 镜像仓库** :
* 一个 Docker Registry 用于存储构建好的应用镜像。可以是:
* Docker Hub (公共或私有)
* OneDev 自带的容器镜像仓库 (如果 OneDev 版本支持并已启用,或者通过插件)
* Harbor, Quay.io 等私有化部署的 Registry
* 云服务商提供的 Registry (如阿里云 ACR, AWS ECR, Google GCR)
* 准备好访问该 Registry 的凭证 (用户名和密码/Access Token)。这些凭证将作为 Secrets 配置在 OneDev 中。
* **域名 (可选但推荐)** : 为您的 OneDev 服务器和应用准备域名,并配置好 DNS 解析。
* **对 Docker 和 Linux 基本命令有了解** 。
## 3. CI/CD 流程概览
## 3. CI/CD 流程概览
1. **代码提交** : 开发者将代码改动推送到 OneDev 仓库的指定分支 (例如 `main` )。
1. **代码提交** : 开发者将代码改动推送到 OneDev 内置 Git 仓库的 `master` 分支 (或其他配置的触发分支 )。
2. **构建 触发** : OneDev 自动 检测到代码 变更,并 根据项目根目录下的 `.onedev-buildspec.yml` 文件 中定义的 触发器 (Triggers) 和作业 (Jobs) 启动构建流程 。
2. **OneDev 流水线 触发** : OneDev 检测到其内置仓库的 变更,根据 `.onedev-buildspec.yml` 中的 定义触发相应的流水线 。
3. **作业执行 ** : OneDev 的执行器 (Executor) 根据构建规范执行定义的作业步骤:
3. **Agent 执行 作业** : OneDev Server 将流水线中的作业分配给匹配的 Agent (运行在部署服务器上)。
* **代码检出** : 执行器自动检出指定提交的代码。
4. **流水线执行 (`.onedev-buildspec.yml`)** :
* **应用构建** :
* **检出代码** : Agent 从仓库拉取最新的代码。
* **后端 (`springboot-init-main`)** : 使用 Maven 构建工具 (如 `mvn package` ) 打包成 JAR 文件 。
* **构建应用 Docker 镜像** : Agent 在本地构建后端和前端应用的新 Docker 镜像 (例如 `mqtt-springboot-app:latest` , `mqtt-nextjs-app:latest` ) 。
* **前端 (`charging_web_app`)** : 使用 Node.js 和 npm/yarn (如 `npm run build` ) 构建生产版本的静态文件和 Next.js 服务 。
* **准备 `.env` 文件** : Agent 从 OneDev 项目配置的 Secrets 中获取敏感数据 (如数据库密码),并生成 `.env` 文件 。
* **Docker 镜像构建与推送** :
* **重启服务** : Agent 使用项目中的 `docker-compose.yml` 和新生成的 `.env` 文件,通过 `docker-compose` 命令停止旧服务,并基于新的镜像和配置启动所有服务。
* 使用项目中的 `Dockerfile` 构建 Docker 镜像 。
5. **监控与日志** : 开发者可以在 OneDev 的 Web 界面上实时监控流水线执行状态、查看各步骤的详细日志 。
* 构建成功后,将镜像标记版本号并推送到指定的 Docker 镜像仓库。
* **应用部署** :
* 通过 SSH 连接到线上应用服务器。
* 在服务器上执行预设脚本(通常是 Docker Compose 命令)来拉取新镜像并重启服务。
4. **完成与反馈** : 构建完成后, OneDev 界面会显示构建状态、日志和产物。可以配置通知。
## 4. 详细步骤
## 4. 详细步骤
### 步骤 4.1: 服务器环境准备
### 步骤 4.1: OneDev 服务器安装与配置
(此部分与之前 Gitea+Drone CI 指南中的服务器准备基本一致,请确保应用服务器满足 Docker, Docker Compose 和 SSH 的要求。OneDev 服务器自身的安装请参考官方文档。)
1. **安装 OneDev** :
* 访问 OneDev 官方文档 ([https://onedev.io/docs/installation ](https://onedev.io/docs/installation )),选择适合您环境的安装方法 (例如 Docker 运行,或直接部署 WAR 包)。
* **强烈建议使用 Docker 运行 OneDev Server** ,方便管理和升级。官方文档提供了 Docker 命令示例。
* 确保 OneDev 数据持久化配置正确。
2. **初始化 OneDev** : 首次访问 OneDev URL, 按照向导完成管理员账户设置和基本配置。
1. **选择并配置 Linux 服务器 (应用服务器)** :
### 步骤 4.2: OneDev Agent 安装与配置 (在部署服务器上)
* 建议使用主流 Linux 发行版,如 Ubuntu, CentOS。
* 确保服务器资源充足( CPU, 内存, 磁盘空间)。
* **内存建议 (测试环境, OneDev 和应用分开部署或合并部署,不考虑高并发)** :
* **OneDev 服务器** : OneDev 自身运行(特别是包含 Elasticsearch 用于搜索)可能需要 **2GB-4GB RAM** 或更多,具体取决于仓库数量、用户数和活动情况。请参考 OneDev 官方的资源建议。
* **应用服务器 (仅运行后端和前端应用容器)** : **2GB RAM** 通常足够。
* **单服务器部署 (OneDev Server, 执行器, 后端应用, 前端应用均在同一台机器)** : 由于 OneDev 自身和构建过程的资源消耗,推荐至少 **4GB-8GB RAM** 。具体数值高度依赖 OneDev 的负载和构建任务的复杂度。对于纯测试且OneDev负载不高的情况, 4GB可能是底限。
* 如果服务器内存确实有限, 需要严格控制各进程的内存使用, 并可能遇到性能瓶颈或OOM问题。
2. **安装 Docker Engine (应用服务器)** : (同前)
3. **安装 Docker Compose (应用服务器)** : (同前)
4. **配置 SSH (应用服务器)** :
* 确保 SSH 服务正在运行。
* 为 OneDev 执行器创建一个专用的 SSH 用户,或使用现有用户。
* **强烈推荐使用 SSH 密钥对进行认证** 。私钥将作为 Secret 配置在 OneDev 中,用于部署作业。
* 在可以安全操作的地方生成 SSH 密钥对。
* 将公钥 (`~/.ssh/id_rsa.pub` ) 内容添加到应用服务器上对应用户的 `~/.ssh/authorized_keys` 文件中。
* 确保 `.ssh` 目录权限为 `700` , `authorized_keys` 文件权限为 `600` 。
5. **防火墙配置 (应用服务器)** : (同前)
### 步骤 4.2: OneDev 服务器安装与配置 (简述)
OneDev Agent 负责执行流水线中定义的作业。您可以选择直接在部署服务器上运行 Agent (通过 `java -jar agent.jar ...` ),或者更推荐的方式是 **通过 Docker 容器运行 Agent** 。您已确认使用 Docker 容器运行 Agent。
* **安装 OneDev** : 请遵循 OneDev 官方网站 ([https://onedev.io/ ](https://onedev.io/ )) 的最新安装指南。常见的安装方式包括:
1. **登录 OneDev** : 使用管理员账户登录您的 OneDev 服务器。
* **Docker 容器** : 这是推荐且较简单的方式。官方会提供 `docker run` 命令或 `docker-compose.yml` 示例 。
2. **导航到 Agents 管理页面** : 通常在 `Administration` -> `Agents` (或者新版可能是 `Administration` -> `Job Executors` ) 。
* **直接运行 JAR** : 下载 `server-bootstrap.jar` 并运行 。
3. **连接新 Agent/Executor 指引** : OneDev 界面会提供如何连接新 Agent/Executor 的指引。选择 "Connect an agent by running agent docker container" (或类似描述) 。
* **初始配置** : 安装完成后,首次访问 OneDev 服务会引导进行管理员账户创建和基本配置。
* **项目创建/导入** : 在 OneDev 中创建您的 `mqtt-charging-system` 项目,或从其他 Git 源导入。
* **执行器 (Executor) 配置** : OneDev 需要配置执行器来运行构建作业。默认情况下可能有一个内置的 Docker Executor, 但您也可以配置远程服务器作为 Shell Executor (通过 SSH) 或 Kubernetes Executor。对于 Docker 构建和 SSH 部署,确保执行器有能力运行 Docker 命令和 SSH 命令。
* 如果 OneDev 服务器自身资源充足且安装了 Docker, 可以使用其内置的 Docker Executor。
* 如果希望在专门的构建机或应用服务器上执行某些部署步骤,可能需要配置 Server Shell Executor 或 Agent Shell Executor, 并确保这些执行环境安装了必要的工具 (如 `docker-compose` , `ssh client` )。
### 步骤 4.3: 项目 Docker化
4. **运行 Agent Docker 容器 (在部署服务器上)** :
* OneDev 会提供一个 `docker run` 命令示例,类似如下 (请从您的 OneDev 界面复制准确命令,它会包含特定的服务器 URL 和 Agent 令牌):
(此部分与之前指南中的 Dockerfile 内容保持不变,因为 Dockerfile 本身与 CI/CD 工具无关。)
```bash
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock -v <path_to_agent_data_on_host>:/opt/onedev/agent <onedev_agent_image> <OneDev Server URL> <Agent Token>
* ** `springboot-init-main/Dockerfile` **: (同前)
* ** `charging_web_app/Dockerfile` **: (同前)
### 步骤 4.4: OneDev 构建规范配置 (`.onedev-buildspec.yml`)
在您的 OneDev 项目 (`mqtt-charging-system` ) 的根目录下创建 `.onedev-buildspec.yml` 文件 (或者通过 OneDev UI 配置构建规范)。
```yaml
# .onedev-buildspec.yml
# 定义构建作业 (Jobs)
jobs :
# --- 后端 Spring Boot 应用作业 ---
- name : "Backend CI/CD"
# 执行器选择:指定一个有能力运行 Maven 和 Docker 命令的执行器
# 这通常是一个配置了 Docker-in-Docker 或可以访问 Docker socket 的 Docker Executor
# 或者是一个安装了 Maven 和 Docker 的 Shell Executor
executor : "docker-executor" # 替换为你在 OneDev 中配置的执行器名称
# 触发器:当 main 分支有代码提交,且 springboot-init-main 目录下文件发生变化时触发
triggers :
- type : "branch-push"
branches : "main"
paths : "springboot-init-main/**"
# 构建步骤 (Steps)
steps :
# 1. 检出代码 (通常是隐式的,或由 OneDev 自动处理第一步)
- checkout # OneDev 内置的检出步骤
# 2. 构建 Spring Boot JAR
- group : "Build Backend JAR"
steps :
- image : "maven:3.8-openjdk-8" # 使用 Maven Docker 镜像执行命令
shell : "sh"
commands : |
echo "Building Spring Boot JAR..."
cd springboot-init-main
mvn clean package -DskipTests -B
# 3. 构建并推送后端 Docker 镜像
- group : "Publish Backend Docker Image"
steps :
# 使用 OneDev 内置的 Docker Build & Push 命令 (或手动 docker 命令)
# 假设 executor 有 docker cli
- shell : "sh"
# 需要将 Docker Hub 凭证配置为 Job Secrets: DOCKER_USER, DOCKER_PASSWORD
# 以及 Docker 仓库地址: DOCKER_REGISTRY (可选, 默认 docker.io)
commands : |
echo "Logging in to Docker Registry..."
echo $env.get(\'DOCKER_PASSWORD\') | docker login -u $env.get(\'DOCKER_USER\') --password-stdin $env.get(\'DOCKER_REGISTRY\', \'docker.io\')
echo "Building and Pushing Backend Docker Image..."
cd springboot-init-main
IMAGE_NAME="${env.get(\'DOCKER_REGISTRY\', \'docker.io\')}/your-docker-repo/mqtt-springboot-app"
# 使用 @file:job.commitHash 获取当前提交的短哈希
docker build -t ${IMAGE_NAME}:latest -t ${IMAGE_NAME}:$(echo \"@file:job.commitHash@\" | cut -c1-8) .
docker push ${IMAGE_NAME}:latest
docker push ${IMAGE_NAME}:$(echo \"@file:job.commitHash@\" | cut -c1-8)
echo "Logging out from Docker Registry..."
docker logout $env.get(\'DOCKER_REGISTRY\', \'docker.io\')
# OneDev 提供了更集成的 Docker 构建步骤,可以研究使用以简化脚本
# - build-docker-image: ... (参考 OneDev 文档)
# - push-docker-image: ... (参考 OneDev 文档)
# 4. 部署后端到服务器
- group : "Deploy Backend to Server"
steps :
- shell : "sh"
# 需要将 SSH 私钥配置为 Job Secret: SERVER_SSH_KEY
# 以及服务器地址: SERVER_HOST, SSH用户: SERVER_SSH_USER
# 服务器部署路径: BACKEND_DEPLOY_PATH (例如 /opt/deploy/mqtt-charging-system/backend)
commands : |
echo "Deploying Backend to Server..."
mkdir -p ~/.ssh
echo "$env.get(\'SERVER_SSH_KEY\')" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh -o StrictHostKeyChecking=no $env.get(\'SERVER_SSH_USER\')@$env.get(\'SERVER_HOST\') \
"cd $env.get(\'BACKEND_DEPLOY_PATH\') && docker-compose pull backend-app && docker-compose up -d --remove-orphans backend-app"
echo "Backend deployment completed."
# --- 前端 Next.js 应用作业 ---
- name : "Frontend CI/CD"
executor : "docker-executor" # 替换为合适的执行器
triggers :
- type : "branch-push"
branches : "main"
paths : "charging_web_app/**"
steps :
- checkout
# 2. 构建 Next.js 应用
- group : "Build Frontend App"
steps :
- image : "node:18-alpine"
shell : "sh"
commands : |
echo "Building Next.js App..."
cd charging_web_app
npm ci
npm run build
# 3. 构建并推送前端 Docker 镜像
- group : "Publish Frontend Docker Image"
steps :
- shell : "sh"
commands : |
echo "Logging in to Docker Registry..."
echo $env.get(\'DOCKER_PASSWORD\') | docker login -u $env.get(\'DOCKER_USER\') --password-stdin $env.get(\'DOCKER_REGISTRY\', \'docker.io\')
echo "Building and Pushing Frontend Docker Image..."
cd charging_web_app
IMAGE_NAME="${env.get(\'DOCKER_REGISTRY\', \'docker.io\')}/your-docker-repo/mqtt-nextjs-app"
docker build -t ${IMAGE_NAME}:latest -t ${IMAGE_NAME}:$(echo \"@file:job.commitHash@\" | cut -c1-8) .
docker push ${IMAGE_NAME}:latest
docker push ${IMAGE_NAME}:$(echo \"@file:job.commitHash@\" | cut -c1-8)
echo "Logging out from Docker Registry..."
docker logout $env.get(\'DOCKER_REGISTRY\', \'docker.io\')
# 4. 部署前端到服务器
- group : "Deploy Frontend to Server"
steps :
- shell : "sh"
commands : |
echo "Deploying Frontend to Server..."
mkdir -p ~/.ssh
echo "$env.get(\'SERVER_SSH_KEY\')" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh -o StrictHostKeyChecking=no $env.get(\'SERVER_SSH_USER\')@$env.get(\'SERVER_HOST\') \
"cd $env.get(\'FRONTEND_DEPLOY_PATH\') && docker-compose pull frontend-app && docker-compose up -d --remove-orphans frontend-app"
echo "Frontend deployment completed."
# 可以定义参数 (Parameters) 和属性 (Properties) 以供作业使用
# parameters:
# properties:
` ``
` ``
* * *重要说明 **:
* **关键参数解释 **:
* 上述 `.onedev-buildspec.yml` 是一个示例,具体语法和可用步骤请务必参考您正在使用的 OneDev 版本的官方文档 。
* ` --rm`: 容器停止后自动删除 (可选,但常用于 Agent) 。
* `executor` : 指定运行此作业的 OneDev 执行器。您需要在 OneDev 中预先配置好执行器 (例如 D ocker Executor, Shell Executor) 。
* ` -v /var/run/docker.sock:/var/run/docker.sock`: **非常重要 (Docker-out-of-Docker - DooD)**。这将宿主机的 Docker socket 挂载到 Agent 容器内部。这使得 Agent 容器可以控制宿主机的 Docker daemon 来执行 Docker 命令 (例如 ` docker build`, ` docker-compose up`)。我们当前的 ` .onedev-buildspec.yml` 依赖此设置来在宿主机本地构建镜像和运行 Docker Compose 。
* `triggers` : 定义了何时触发此作业 。
* ` -v < path_to_agent_data_on_host > :/opt/onedev/agent` (或 OneDev 推荐的其他挂载点): 用于持久化 Agent 的配置和工作数据。例如,您可以设置为 ` -v /opt/onedev_agent_data:/opt/onedev/agent` 。
* `steps` : 定义了作业的具体操作。OneDev 有很多内置的步骤类型 (如 `checkout` , `setup-jdk` , `run-docker-command` , `build-docker-image` , `ssh-command-step` 等),使用内置步骤通常比手写 shell 脚本更简洁和安全。**强烈建议查阅 OneDev 文档,使用其推荐的步骤来操作 Docker 和 SSH。**
* ` < onedev_agent_image > `: OneDev 官方提供的 Agent Docker 镜像,例如 ` 1dev/agent` 或 ` onedev/agent` (请参考 OneDev 界面的准确镜像名称)。
* **Secrets/Variables** :
* ` < OneDev Server URL > ` 和 ` < Agent Token > `: 由您的 OneDev 服务器提供,用于 Agent 连接和认证。
* `$env.get('SECRET_NAME')` 或 `$get('job_secret_name')` (具体语法看OneDev版本) 用于从 OneDev 作业 Secrets 中获取敏感信息 (如 `DOCKER_USER` , `DOCKER_PASSWORD` , `SERVER_SSH_KEY` )。
* **Agent 容器所需的工具**:
* `your-docker-repo` 需要替换为您的 Docker 仓库名/组织名 。
* OneDev 官方的 Agent 镜像通常已包含 ` git` 。
* `SERVER_HOST` , `SERVER_SSH_USER` , `BACKEND_DEPLOY_PATH` , `FRONTEND_DEPLOY_PATH` 等也应该是作为 Job Secrets 或 Parameters 传入。
* 为了执行 ` .onedev-buildspec.yml` 中的 ` docker-compose` 命令,您需要确保 Agent 使用的 Docker 镜像**内部也包含 ` docker-compose` CLI** (或者较新版本的 ` docker compose` 插件)。如果官方 Agent 镜像不包含,您可能需要:
* `@file:job.commitHash@` 是 OneDev 提供的一个变量,用于获取当前构建的 Git 提交哈希 。
* 在 ` .onedev-buildspec.yml` 的 ` executeShell` 步骤开始前,先在 Agent 容器内安装 ` docker-compose` 。
* **错误处理与健壮性** : 实际脚本中应添加错误检查和更完善的日志 。
* 或者,构建一个自定义的 Agent Docker 镜像,该镜像基于 OneDev 官方 Agent 镜像,并额外安装 ` docker-compose` 。
* **OneDev 内置步骤** : 对于 Docker 构建/推送和 SSH 命令执行, O neD ev 提供了专门的步骤类型,使用它们会比直接写 `shell` 命令更方便,并能更好地处理凭证和输出。例如,有专门的 `Push to Docker Registry` 步骤,可以直接配置仓库、凭证等 。
* 或者,修改 ` .oned ev-buildspec.yml` 中的命令为 ` docker compose` (注意空格),如果 Agent 容器的 Docker CLI 支持 Compose V2 插件 。
* 我们当前的 ` .onedev-buildspec.yml` 中的 ` executeShell` 使用 ` docker-compose` (带连字符)。
### 步骤 4.5: 服务器部署配置 (Docker Compose)
5. **为 Agent 添加标签**:
* Agent Docker 容器启动并成功连接到 OneDev Server 后,它会出现在 OneDev 的 Agents/Executors 列表中。
* 点击该 Agent/Executor, 进入其配置页面, 添加一个标签, 例如 ` agent-for-mqtt-power`。这个标签将用于 ` .onedev-buildspec.yml` 中的 ` agentMatcher`,以确保作业在此 Agent 上运行。
在您的应用服务器上,创建一个部署根目录(例如 `/opt/deploy/mqtt-charging-system/` ),并在该目录下放置一个统一的 `docker-compose.yml` 文件。这个文件将管理所有服务, 包括数据库、MQTT Broker 以及您的后端和前端应用 。
6. **确保宿主机 Docker 环境**: Agent 容器通过 DooD 控制宿主机的 Docker, 所以确保部署服务器( 宿主机) 上已正确安装和配置了 Docker Engine 和 Docker Compose (如果 ` docker-compose.yml` 依赖于宿主机上的 ` docker-compose` CLI 版本特性) 。
* **统一的 `docker-compose.yml` (示例路径: `/opt/deploy/mqtt-charging-system/docker-compose.yml`)** :
7. **持久化运行 Agent Docker 容器 (推荐)**:
* 该文件的内容已在本指南前文(或作为单独文件)提供。它应包含 `mysql-db` , `emqx` , `backend-app` , 和 `frontend-app` 服务 。
* 为了确保 Agent 在服务器重启后也能自动运行,建议使用 Docker 的重启策略或通过 ` systemd` 管理 Agent Docker 容器的启动 。
* 确保 `backend-app` 和 `frontend-app` 服务中的 `image` 指向您在 CI/CD 流程中构建和推送到 Docker Registry 的镜像地址。
* **使用 Docker 重启策略**:
* 通过 `environment` 部分为 `backend-app` 注入数据库连接信息(如 `DB_HOST: mysql-db` , `DB_USER` , `DB_PASSWORD` , `DB_NAME` )和 MQTT Broker 信息 (`MQTT_BROKER_URL: tcp://emqx:1883` ),使其连接到 Compose 网络内的相应服务 。
在 ` docker run` 命令中添加 ` --restart unless-stopped` 或 ` --restart always` 。
* MySQL 和 EMQX 的敏感配置(如密码)应通过环境变量从外部(例如服务器上的 `.env` 文件或 CI 工具注入的环境变量)设置,而不是硬编码在 `docker-compose.yml` 的默认值中。
` ``bash
docker run --restart unless-stopped --name onedev-agent-mqtt -d \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /opt/onedev_agent_data_mqtt:/opt/onedev/agent \
<onedev_agent_image> <OneDev Server URL> <Agent Token>
` ``
* ` --name onedev-agent-mqtt`: 为容器指定一个名称,方便管理。
* ` -d`: 后台运行容器。
* **通过 systemd 管理 (更灵活,但略复杂)**: 您可以创建一个 systemd 服务单元来启动和管理这个 Agent Docker 容器。
* 示例 (` /etc/systemd/system/onedev-agent-docker.service`):
` ``ini
[Unit]
Description=OneDev Agent Docker Container
Requires=docker.service
After=docker.service
### 步骤 4.6: OneDev Secrets 管理
[Service]
Restart=always
ExecStartPre=-/usr/bin/docker stop onedev-agent-mqtt
ExecStartPre=-/usr/bin/docker rm onedev-agent-mqtt
ExecStart=/usr/bin/docker run --name onedev-agent-mqtt \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /opt/onedev_agent_data_mqtt:/opt/onedev/agent \
<onedev_agent_image> <OneDev Server URL> <Agent Token>
ExecStop=/usr/bin/docker stop onedev-agent-mqtt
OneDev 提供了强大的 Secrets 管理功能,用于安全地存储 CI/CD 流程中所需的敏感信息。
[Install]
WantedBy=multi-user.target
` ``
* **重要**: 替换占位符。确保路径和镜像是正确的。
* 然后 ` sudo systemctl daemon-reload`, ` sudo systemctl start onedev-agent-docker`, ` sudo systemctl enable onedev-agent-docker`。
1. 打开 OneDev 上的 `mqtt-charging-system` 项目。
### 步骤 4.3: 在 OneDev 中创建项目并配置 Secrets
2. 导航到项目 `设置` (Settings) -> `构建设置` (Build Settings) -> `作业密秘` (Job Secrets)。
3. 点击 `添加密秘` (Add Secret) 来创建以下 Secrets (名称需与 `.onedev-buildspec.yml` 中引用的名称一致):
* `DOCKER_USER` : 你的 Docker 镜像仓库的用户名。
* `DOCKER_PASSWORD` : 你的 Docker 镜像仓库的密码或 Access Token (标记为密码类型)。
* `SERVER_SSH_KEY` : 部署服务器的 SSH 私钥内容 (标记为文件类型或多行文本)。
* `SERVER_HOST` : 部署服务器的 IP 地址或主机名。
* `SERVER_SSH_USER` : 用于 SSH 连接的用户名。
* `DEPLOY_PATH` : 应用在服务器上的统一部署路径 (例如 `/opt/deploy/mqtt-charging-system` ).
* `DOCKER_REGISTRY` (可选): 如果不是 Docker Hub, 则为您的 Docker 仓库地址 (例如 `gitea.yourdomain.com:5000` )。
* **新增Secrets (用于 `docker-compose.yml` 中的数据库和Broker)** :
* `MYSQL_ROOT_PASSWORD_SECRET` : MySQL root用户的密码。
* `MYSQL_DATABASE_SECRET` : 数据库名称 (例如 `mqtt_power` )。
* `MYSQL_USER_SECRET` : 应用连接数据库的用户名 (例如 `appuser` )。
* `MYSQL_PASSWORD_SECRET` : 应用连接数据库的密码。
* (如果 EMQX 需要认证,则添加相应 Secrets)
4. **授权** : 确保这些 Secrets 仅被授权给需要它们的构建作业或分支访问。
**注意 ** : 在 `.onedev-buildspec.yml` 的部署脚本中,您需要一种方式将这些 Secrets (如 `MYSQL_ROOT_PASSWORD_SECRET` ) 传递给部署服务器,以便 `docker-compose up` 命令可以访问它们作为环境变量。这可以通过以下几种方式实现:
1. **创建项目 **:
* **通过 SSH 动态创建 `.env` 文件** : 在 SSH 部署脚本中,从 OneDev Secrets 读取值,并在部署目录动态生成一个 `.env` 文件,`docker-compose` 会自动加载它 。
* 登录 OneDev, 点击 ` + New Project` 。
* **直接在 `docker-compose up` 命令前导出环境变量** : `export MYSQL_ROOT_PASSWORD=$env.get('MYSQL_ROOT_PASSWORD_SECRET'); docker-compose up -d` (这种方式环境变量仅对当前 SSH 会话的该命令有效,需要小心处理引号和转义 )。
* 填写项目名称 (例如 ` mqtt-charging-system` )。
* OneDev 可能有更高级的方法来处理部署时的环境变量注入,请查阅其文档。
* **代码库**:
* 选择 ` Create an empty repository` (如果您想在 OneDev 中开始一个全新的项目,并将 ` master` 作为默认分支) 或 ` Import from an existing repository` (如果您想将现有的 Git 仓库——例如本地的或之前 Gitea 上的,其主分支为 ` master`——导入到 OneDev 中进行管理)。**本项目将使用 OneDev 内置的 Git 服务。**
* (可选) 配置项目的默认分支为 ` master` (如果通过导入创建且需要更改,或新建时指定)。
2. **配置项目 Secrets**: 这些 Secrets 将被 ` .onedev-buildspec.yml` 用于生成 ` .env` 文件。
* 进入项目 -> ` Settings` -> ` Secrets`。
* 点击 ` New Secret`。
* 为每个需要的敏感信息创建一个 Secret。**确保 Secret 名称与 ` .onedev-buildspec.yml` 中 ` @secrets .< SecretName > @` 的 ` < SecretName > ` 部分完全一致**。
* ` MYSQL_ROOT_PASSWORD`: 您的 MySQL root 密码。
* ` MYSQL_DATABASE`: 数据库名称 (例如 ` mqtt_power`)。
* ` MYSQL_USER`: 应用连接数据库的用户名 (例如 ` appuser`)。
* ` MYSQL_PASSWORD`: 应用连接数据库的密码。
* (可选) ` EMQX_ADMIN_PASSWORD`: 如果 EMQX 需要管理密码。
* 勾选 ` Available to all branches` (除非您有特定分支的特殊需求,例如只允许 ` master` 分支的构建访问生产密码)。
* 确保这些 Secrets **不允许在构建日志中显示**。
### 步骤 4.7 : (移除/简化 Gitea Webhook 配置)
### 步骤 4.4 : 将项目代码和配置文件推送到仓库
由于 OneDev 是一体化平台,它会自动监控其管理的 Git 仓库的变更。当符合 `.onedev-buildspec.yml` 中定义的 `triggers` 条件时,构建会自动触发。因此,不需要像 Gitea+Drone CI 那样手动配置外部 Webhook。
1. 确保您的项目代码已克隆/推送到 OneDev 内置的 Git 仓库中,并且根目录包含以下文件:
* **` .onedev-buildspec.yml`**: (已创建) 定义 CI/CD 流水线。
* **` docker-compose.yml`**: (已创建和修改) 定义所有服务,应用镜像使用本地构建名称。
* **` springboot-init-main/Dockerfile`**: (已创建) 用于构建后端镜像。
* **` charging_web_app/Dockerfile`**: (已创建) 用于构建前端镜像。
* **` springboot-init-main/src/main/resources/application.yml`**: (已修改) 数据库和 MQTT 连接信息通过环境变量配置。
2. 将这些文件提交并推送到 OneDev 内置 Git 仓库的 ` master` 分支。
## 5. 部署 触发与监控
### 步骤 4.5: 触发与监控部署
* **触发** : 当所有配置完成后,向 OneDev 项目的 `main` 分支(或其他在构建规范中配置的分支)推送代码提交,并且提交包含了相应目录 (`springboot-init-main/**` 或 `charging_web_app/**` ) 的文件变更,将自动触发 OneDev 中定义的相应 CI/CD 作业。
1. **触发构建**:
* **监控** :
* 当您向 OneDev 内置仓库的 ` master` 分支 (或其他在 OneDev 项目构建设置中配置的触发分支) 推送代码时, OneDev 应该会自动触发 ` .onedev-buildspec.yml` 中定义的流水线。
* 在 OneDev 界面,您可以进入项目的 `构建` (Builds) 标签页,实时查看构建列表、每个构建的详细步骤、日志、状态以及最终结果 。
* 您也可以 在 OneDev 项目的 ` Builds` 页面手动触发特定分支 (如 ` master`) 的构建 。
* OneDev 允许配置构建完成后的通知 (例如 Email, Webhook 到其他系统等)。
2. **监控构建**:
* 在应用服务器上,使用 `docker ps` 和 `docker logs` 进行容器监控 。
* 在 OneDev 项目的 ` Builds` 页面,您可以看到正在运行和已完成的构建列表 。
* 点击特定的构建,可以查看其详细步骤、可视化流程、以及每个步骤的实时日志输出。
* 如果构建失败,日志中会包含错误信息,帮助您排查问题。
3. **验证部署**: 构建成功完成后,在部署服务器上:
* 使用 ` docker ps -a` 查看所有容器的状态。
* 使用 ` docker-compose logs -f < service_name > ` (在 Agent 的工作区项目目录下) 或 ` docker logs < container_name_or_id > ` 查看各服务日志。
* 尝试访问您的前端和后端应用。
## 6 . 回滚策略 (简述 )
## 5 . ` .onedev-buildspec.yml` 文件详解 (关键点 )
(与之前类似, OneDev 也支持通过标签重新运行旧的构建,或手动部署旧的 Docker 镜像版本。 )
(已在之前创建,此处为回顾和说明 )
* **手动回滚** :
* **` version: 8`**: 指定 buildspec 的版本。
* 使用 OneDev 构建产出的 Docker 镜像标签 (例如基于 commit hash 的标签) 在服务器上手动通过 `docker-compose.yml` 指向旧版本并重启服务 。
* **` jobs`**: 定义一个或多个作业 。
* 在 OneDev 的构建历史中,找到上一个成功的部署构建,检查其使用的 commit, 并可能基于该 commit 创建一个新的部署或重新运行(如果构建规范支持参数化部署特定版本) 。
* **` name`**: 作业的名称 。
* **自动化回滚 (高级)** : 可以在 `.onedev-buildspec.yml` 中设计更复杂的逻辑,例如部署后运行健康检查,如果失败则自动触发另一个作业来部署上一个稳定版本 。
* **` agentMatcher`**: 指定运行此作业的 Agent 必须拥有的标签 (例如 ` agent-for-mqtt-power`) 。
* **` steps`**: 作业中执行的步骤。
* **` checkout`**: 检出代码到 Agent 的工作区。
* **` setupVariables`**: 定义变量,可以引用 Secrets (` @secrets .MySecret@`) 或其他 OneDev 内置变量 (` @commit_hash @` 等)。
* **` buildImage`**: OneDev 内置步骤,用于构建 Docker 镜像。
* ` dockerfile`: Dockerfile 的路径。
* ` imageName`, ` imageTag`: 构建的镜像名称和标签。
* ` buildPath`: Docker build context 路径。
* **` writeFile`**: 将内容写入 Agent 工作区的文件 (例如生成 ` .env` 文件)。
* **` executeShell`**: 执行 shell 命令 (例如 ` docker-compose up -d`)。
* **` dependencies`**: 定义作业之间的依赖关系 (例如,部署作业依赖于构建作业)。
* **` triggers`**: 定义触发作业的条件 (例如,特定路径的文件变更、其他作业成功等)。
## 6. 回滚策略
* **重新运行旧的成功构建**: OneDev 保存了所有构建的历史记录。如果新部署出现问题,您可以找到上一个基于 ` master` 分支的成功部署构建,并点击 "Rebuild" (或类似选项) 来重新运行该构建,从而回滚到之前的状态。
* **代码回滚并触发新构建**: 在 Git 中将 ` master` 分支的代码回滚到某个稳定版本,然后推送到 OneDev, OneDev 将会基于旧代码重新构建和部署。
* **(如果镜像打了 commit hash 标签)**: 如果您的镜像标签包含 commit hash (例如 ` @commit_hash @`变量),并且您知道某个稳定版本的 commit hash, 理论上可以手动修改部署服务器上的 ` docker-compose.yml` (或通过 OneDev 参数化构建传递镜像标签) 来指向旧镜像并重启,但这通常不如通过 OneDev 流水线管理方便。
## 7. 注意事项与常见问题
## 7. 注意事项与常见问题
* **Secrets 安全 ** : 严格管理 OneDev 中的 Job Secrets。特别注意部署到服务器时, 如何安全地传递和使用 `docker-compose.yml` 所需的环境变量(如数据库密码) 。
* **Agent 资源与权限 **: 确保 OneDev Agent 运行的用户有足够的权限(特别是 Docker 命令执行权限) 和系统资源( CPU, 内存, 磁盘空间)来完成构建和部署任务 。
* **`.onedev-buildspec.yml` 语法**: YAML 语法对缩进敏感。强烈建议使用 OneDev UI 内置的编辑器来编写或校验构建规范,它通常会提供语法高亮和提示 。
* **Secrets 管理**: 严格管理 OneDev 中的 Secrets, 不要在日志中暴露它们 。
* **O neD ev 执行器 (Executor) ** : 正确配置和选择执行器至关重要。确保执行器有执行作业步骤所需的环境和权限 (如 Docker, Maven, Node.js, SSH客户端) 。
* **` .o ned ev-buildspec.yml` 语法 **: YAML 格式对缩进敏感,编写时需注意 。
* **OneDev 文档 ** : **OneDev 功能迭代较快,本文档中的构建规范示例可能不是最新的或最优的。请务必参考您正在使用的 OneDev 版本的官方文档,特别是关于 CI/CD 步骤、变量和 Secrets 的部分。**
* **Docker 构建上下文 **: ` buildImage` 步骤中的 ` buildPath` 很重要,它决定了 Docker 构建时的上下文环境。
* **路径与上下文 ** : 注意 OneDev 作业中执行命令时的工作目录 。
* * *网络配置 **: 确保 OneDev Server, OneDev Agent, 以及部署服务器上的 Docker 容器之间网络通畅 。
* **统一的 `docker-compose.yml`** : 确保所有服务定义正确,网络配置允许服务间通信,卷的挂载用于持久化数据 。
* * *首次构建**: 第一次触发构建时,请密切关注 OneDev 中的日志,以便快速定位和解决可能出现的配置问题 。
* **环境变量注入 ** : 仔细规划如何在部署时将 OneDev Job Secrets 安全地传递给 `docker-compose.yml` 使用的环境变量。避免在版本控制中存储包含敏感默认值的 `.env` 文件 。
* * *日志 **: OneDev 提供了非常详细的构建日志,是排查问题的首要工具 。
* ** (其他注意事项与之前类似,如 Dockerfile 优化, 权限, 网络, 资源消耗, 首次手动部署验证, 日志调试, 版本控制, 依赖缓存, Monorepo 策略, 数据库迁移等, 这些普适性的CI/CD原则依然适用。)**
---
---
本文档提供了使用 OneDev 配置 CI/CD 的基础 框架。根据实际需求和 OneDev 的具体版本功能,您可能需要调整和扩展这些步骤 。
本文档提供了使用 OneDev (及其内置 Git 服务) 和 Docker Compose 配置 CI/CD 的框架。OneDev 提供了强大的可视化管理和流水线定义能力,可以显著简化部署流程的管理和监控 。