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

16 KiB
Raw Permalink Blame History

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) 进行安装。
    • 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),选择适合您环境的安装方法 (例如 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 令牌):
      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/agentonedev/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.ymlexecuteShell 步骤开始前,先在 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
      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):
        [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 提供了强大的可视化管理和流水线定义能力,可以显著简化部署流程的管理和监控。