Files
mqtt_power/DEPLOYMENT_GUIDE.md
2025-05-23 15:02:01 +08:00

201 lines
16 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CI/CD 部署指南 (OneDev + Docker Compose)
## 1. 简介
本文档旨在指导如何为 `mqtt-charging-system` 项目(包含 `springboot-init-main` 后端和 `charging_web_app` 前端)配置一套基于 OneDev 和 Docker Compose 的持续集成与持续部署 (CI/CD) 流程。实现目标是当代码提交到 OneDev 内置 Git 仓库的特定分支后,自动触发 OneDev 流水线,该流水线负责在部署服务器上构建应用 Docker 镜像,并使用 Docker Compose 重启包括数据库、MQTT Broker 和应用在内的所有服务。
**采用技术栈:**
* **CI/CD 平台与代码仓库**: OneDev (自建,包含内置 Git 服务)
* **构建与部署脚本**: `.onedev-buildspec.yml` (OneDev 流水线定义)
* **容器化**: Docker
* **服务编排**: Docker Compose
* **部署目标**: 运行 OneDev Agent 和 Docker 的 Linux 服务器
## 2. 先决条件
在开始配置此部署流程之前,请确保以下条件已满足:
* **OneDev 服务器**:
* 已在一台服务器上成功安装并运行 OneDev 服务。参考 OneDev 官方文档 ([https://onedev.io/docs/installation](https://onedev.io/docs/installation)) 进行安装。
* OneDev 服务器应具有足够的资源CPU、内存、磁盘
* **线上应用/部署服务器 (OneDev Agent 服务器)**:
* 一台 Linux 服务器,用于运行 OneDev Agent、构建 Docker 镜像以及通过 Docker Compose 运行所有服务容器 (数据库、Broker、后端、前端)。此服务器可以是 OneDev 服务器本身(不推荐用于生产),也可以是独立的机器。
* 服务器已安装 Docker Engine, Docker Compose, 和 Git。
* 服务器防火墙已配置,允许访问应用所需端口(例如后端 7529前端 3000MQTT 1883, 18083 等),以及 OneDev Agent 与 OneDev Server 通信的端口。
* **对 Docker, Docker Compose, Git, YAML 和 OneDev 有基本了解**
## 3. CI/CD 流程概览
1. **代码提交**: 开发者将代码改动推送到 OneDev 内置 Git 仓库的 `master` 分支 (或其他配置的触发分支)。
2. **OneDev 流水线触发**: OneDev 检测到其内置仓库的变更,根据 `.onedev-buildspec.yml` 中的定义触发相应的流水线。
3. **Agent 执行作业**: OneDev Server 将流水线中的作业分配给匹配的 Agent (运行在部署服务器上)。
4. **流水线执行 (`.onedev-buildspec.yml`)**:
* **检出代码**: Agent 从仓库拉取最新的代码。
* **构建应用 Docker 镜像**: Agent 在本地构建后端和前端应用的新 Docker 镜像 (例如 `mqtt-springboot-app:latest`, `mqtt-nextjs-app:latest`)。
* **准备 `.env` 文件**: Agent 从 OneDev 项目配置的 Secrets 中获取敏感数据 (如数据库密码),并生成 `.env` 文件。
* **重启服务**: Agent 使用项目中的 `docker-compose.yml` 和新生成的 `.env` 文件,通过 `docker-compose` 命令停止旧服务,并基于新的镜像和配置启动所有服务。
5. **监控与日志**: 开发者可以在 OneDev 的 Web 界面上实时监控流水线执行状态、查看各步骤的详细日志。
## 4. 详细步骤
### 步骤 4.1: 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按照向导完成管理员账户设置和基本配置。
### 步骤 4.2: OneDev Agent 安装与配置 (在部署服务器上)
OneDev Agent 负责执行流水线中定义的作业。您可以选择直接在部署服务器上运行 Agent (通过 `java -jar agent.jar ...`),或者更推荐的方式是 **通过 Docker 容器运行 Agent**。您已确认使用 Docker 容器运行 Agent。
1. **登录 OneDev**: 使用管理员账户登录您的 OneDev 服务器。
2. **导航到 Agents 管理页面**: 通常在 `Administration` -> `Agents` (或者新版可能是 `Administration` -> `Job Executors`)。
3. **连接新 Agent/Executor 指引**: OneDev 界面会提供如何连接新 Agent/Executor 的指引。选择 "Connect an agent by running agent docker container" (或类似描述)。
4. **运行 Agent Docker 容器 (在部署服务器上)**:
* OneDev 会提供一个 `docker run` 命令示例,类似如下 (请从您的 OneDev 界面复制准确命令,它会包含特定的服务器 URL 和 Agent 令牌):
```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>
```
* **关键参数解释**:
* `--rm`: 容器停止后自动删除 (可选,但常用于 Agent)。
* `-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。
* `-v <path_to_agent_data_on_host>:/opt/onedev/agent` (或 OneDev 推荐的其他挂载点): 用于持久化 Agent 的配置和工作数据。例如,您可以设置为 `-v /opt/onedev_agent_data:/opt/onedev/agent`。
* `<onedev_agent_image>`: OneDev 官方提供的 Agent Docker 镜像,例如 `1dev/agent` 或 `onedev/agent` (请参考 OneDev 界面的准确镜像名称)。
* `<OneDev Server URL>` 和 `<Agent Token>`: 由您的 OneDev 服务器提供,用于 Agent 连接和认证。
* **Agent 容器所需的工具**:
* OneDev 官方的 Agent 镜像通常已包含 `git`。
* 为了执行 `.onedev-buildspec.yml` 中的 `docker-compose` 命令,您需要确保 Agent 使用的 Docker 镜像**内部也包含 `docker-compose` CLI** (或者较新版本的 `docker compose` 插件)。如果官方 Agent 镜像不包含,您可能需要:
* 在 `.onedev-buildspec.yml` 的 `executeShell` 步骤开始前,先在 Agent 容器内安装 `docker-compose`。
* 或者,构建一个自定义的 Agent Docker 镜像,该镜像基于 OneDev 官方 Agent 镜像,并额外安装 `docker-compose`。
* 或者,修改 `.onedev-buildspec.yml` 中的命令为 `docker compose` (注意空格),如果 Agent 容器的 Docker CLI 支持 Compose V2 插件。
* 我们当前的 `.onedev-buildspec.yml` 中的 `executeShell` 使用 `docker-compose` (带连字符)。
5. **为 Agent 添加标签**:
* Agent Docker 容器启动并成功连接到 OneDev Server 后,它会出现在 OneDev 的 Agents/Executors 列表中。
* 点击该 Agent/Executor进入其配置页面添加一个标签例如 `agent-for-mqtt-power`。这个标签将用于 `.onedev-buildspec.yml` 中的 `agentMatcher`,以确保作业在此 Agent 上运行。
6. **确保宿主机 Docker 环境**: Agent 容器通过 DooD 控制宿主机的 Docker所以确保部署服务器宿主机上已正确安装和配置了 Docker Engine 和 Docker Compose (如果 `docker-compose.yml` 依赖于宿主机上的 `docker-compose` CLI 版本特性)。
7. **持久化运行 Agent Docker 容器 (推荐)**:
* 为了确保 Agent 在服务器重启后也能自动运行,建议使用 Docker 的重启策略或通过 `systemd` 管理 Agent Docker 容器的启动。
* **使用 Docker 重启策略**:
在 `docker run` 命令中添加 `--restart unless-stopped` 或 `--restart always`。
```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
[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
[Install]
WantedBy=multi-user.target
```
* **重要**: 替换占位符。确保路径和镜像是正确的。
* 然后 `sudo systemctl daemon-reload`, `sudo systemctl start onedev-agent-docker`, `sudo systemctl enable onedev-agent-docker`。
### 步骤 4.3: 在 OneDev 中创建项目并配置 Secrets
1. **创建项目**:
* 登录 OneDev点击 `+ New Project`。
* 填写项目名称 (例如 `mqtt-charging-system`)。
* **代码库**:
* 选择 `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.4: 将项目代码和配置文件推送到仓库
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` 分支。
### 步骤 4.5: 触发与监控部署
1. **触发构建**:
* 当您向 OneDev 内置仓库的 `master` 分支 (或其他在 OneDev 项目构建设置中配置的触发分支) 推送代码时OneDev 应该会自动触发 `.onedev-buildspec.yml` 中定义的流水线。
* 您也可以在 OneDev 项目的 `Builds` 页面手动触发特定分支 (如 `master`) 的构建。
2. **监控构建**:
* 在 OneDev 项目的 `Builds` 页面,您可以看到正在运行和已完成的构建列表。
* 点击特定的构建,可以查看其详细步骤、可视化流程、以及每个步骤的实时日志输出。
* 如果构建失败,日志中会包含错误信息,帮助您排查问题。
3. **验证部署**: 构建成功完成后,在部署服务器上:
* 使用 `docker ps -a` 查看所有容器的状态。
* 使用 `docker-compose logs -f <service_name>` (在 Agent 的工作区项目目录下) 或 `docker logs <container_name_or_id>` 查看各服务日志。
* 尝试访问您的前端和后端应用。
## 5. `.onedev-buildspec.yml` 文件详解 (关键点)
(已在之前创建,此处为回顾和说明)
* **`version: 8`**: 指定 buildspec 的版本。
* **`jobs`**: 定义一个或多个作业。
* **`name`**: 作业的名称。
* **`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` 分支的代码回滚到某个稳定版本,然后推送到 OneDevOneDev 将会基于旧代码重新构建和部署。
* **(如果镜像打了 commit hash 标签)**: 如果您的镜像标签包含 commit hash (例如 `@commit_hash@`变量),并且您知道某个稳定版本的 commit hash理论上可以手动修改部署服务器上的 `docker-compose.yml` (或通过 OneDev 参数化构建传递镜像标签) 来指向旧镜像并重启,但这通常不如通过 OneDev 流水线管理方便。
## 7. 注意事项与常见问题
* **Agent 资源与权限**: 确保 OneDev Agent 运行的用户有足够的权限(特别是 Docker 命令执行权限和系统资源CPU, 内存, 磁盘空间)来完成构建和部署任务。
* **Secrets 管理**: 严格管理 OneDev 中的 Secrets不要在日志中暴露它们。
* **`.onedev-buildspec.yml` 语法**: YAML 格式对缩进敏感,编写时需注意。
* **Docker 构建上下文**: `buildImage` 步骤中的 `buildPath` 很重要,它决定了 Docker 构建时的上下文环境。
* **网络配置**: 确保 OneDev Server, OneDev Agent, 以及部署服务器上的 Docker 容器之间网络通畅。
* **首次构建**: 第一次触发构建时,请密切关注 OneDev 中的日志,以便快速定位和解决可能出现的配置问题。
* **日志**: OneDev 提供了非常详细的构建日志,是排查问题的首要工具。
---
本文档提供了使用 OneDev (及其内置 Git 服务) 和 Docker Compose 配置 CI/CD 的框架。OneDev 提供了强大的可视化管理和流水线定义能力,可以显著简化部署流程的管理和监控。