news 2026/4/23 14:29:07

小团队 CI/CD 实践:无需运维,Java Web应用的自动化部署

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
小团队 CI/CD 实践:无需运维,Java Web应用的自动化部署

👉这是一个或许对你有用的社群

🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料:

  • 《项目实战(视频)》:从书中学,往事上“练”

  • 《互联网高频面试题》:面朝简历学习,春暖花开

  • 《架构 x 系统设计》:摧枯拉朽,掌控面试高频场景题

  • 《精进 Java 学习指南》:系统学习,互联网主流技术栈

  • 《必读 Java 源码专栏》:知其然,知其所以然

👉这是一个或许对你有用的开源项目

国产Star破10w的开源项目,前端包括管理后台、微信小程序,后端支持单体、微服务架构

RBAC权限、数据权限、SaaS多租户、商城、支付、工作流、大屏报表、ERP、CRMAI大模型、IoT物联网等功能:

  • 多模块:https://gitee.com/zhijiantianya/ruoyi-vue-pro

  • 微服务:https://gitee.com/zhijiantianya/yudao-cloud

  • 视频教程:https://doc.iocoder.cn

【国内首批】支持 JDK17/21+SpringBoot3、JDK8/11+Spring Boot2双版本

来源:juejin.cn/post/7439403354056359947

  • 引子

  • 认识Docker与Kubernetes

    • Docker

    • Kubernetes

  • 实操

    • 1.开发Web应用

    • 2.创建Kubernetes集群

    • 3.创建阿里云容器镜像服务(ACR)

    • 4.配置GitHub仓库Secrets

    • 5.创建GitHub Actions工作流

    • 6.创建Kubernetes集群配置:

    • 7.访问以及版本管理

  • 小结


引子

在许多小团队中,开发人员不仅要编写应用代码,还需要负责将应用部署到生产环境。对于没有专职运维人员的团队,每次手动部署都不仅费时费力,还容易出错。因此,采用CI/CD(持续集成/持续部署) 来实现自动化部署,成为了解决这一问题的最佳方式。

本文将演示如何使用GitHub Actions和阿里云Kubernetes(ACK)来实现Java Web 应用的自动化部署。我们的目标是,开发人员无需将精力耗费在运维任务上,而是通过现成的云服务来简化部署过程。

需要说明的是,本文的核心目标是降低部署的运维成本,因此选择了多个云服务来演示整个流程,但在实际应用中,大家可以根据团队的情况进行调整。

例如,如果团队有足够的精力,也可以自行部署CI/CD工具,如Jenkins、GitLab CI,而Kubernetes 提供商的选择也非常多,甚至可以自行搭建Kubernetes集群。

本文的重点不在于具体工具的选择,而在于对整个自动化部署流程的掌握。一旦理解了基本流程,切换到其他工具或平台时,上手速度会非常快,因为它们的流程都大差不差的。

基于 Spring Boot + MyBatis Plus + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/ruoyi-vue-pro

  • 视频教程:https://doc.iocoder.cn/video/

认识Docker与Kubernetes

在正式开始操作前,如果是第一次接触的同学,可以先阅读下第二章节,来对Docker与Kubernetes建立起一个认识:

Docker

如果把一个应用程序比作一件商品,那么Docker就像是为这件商品打包的“集装箱”。在没有Docker的年代,开发人员在本地运行的应用,往往在部署到服务器时会遇到各种问题,比如依赖库不一致、操作系统版本不同等。就像你将一件精心制作的商品从一个国家运到另一个国家,可能会因为不同的运输环境、气候条件等因素,导致商品在到达目的地时无法正常使用。

Docker就像是一个标准化的“集装箱”,它能把你的应用程序和它需要的所有依赖打包在一起,形成一个独立的“镜像”image。无论你是在开发环境、测试环境,还是生产环境,Docker镜像都能确保应用在每个环境中以相同的方式运行,就像集装箱能在全球范围内标准化运输一样。它解决了“我本地运行没问题,为什么服务器上就不行?” 这个历史难题。

用个例子说明一下:你要制作一份美味的蛋糕,并寄给朋友。没有Docker的话,你只能把蛋糕装进一个普通的纸箱,然后寄出去。结果朋友收到后发现,蛋糕因为运输颠簸、天气变化,变得面目全非。而使用Docker,就相当于你把蛋糕放进一个坚固的保温集装箱,确保在任何运输条件下,蛋糕能保持新鲜、完整。无论你把这个蛋糕寄到哪里,朋友收到的蛋糕都和你制作时一模一样。

Kubernetes

上文中提到Docker是打包应用的“集装箱”,那么Kubernetes就是管理这些集装箱的“码头系统”。在实际生产环境中,应用程序往往需要部署到多个服务器上(或者称为节点),还需要根据流量的变化,灵活调整应用实例的数量。手动管理这些工作量大且容易出错,就像手工管理码头上成百上千个集装箱一样,效率低下。

Kubernetes 的出现,让这一切变得自动化和可控。它提供了一个强大的管理平台,用来自动调度和管理运行中的 Docker容器。Kubernetes不仅能够帮你决定应用(容器)应该在哪台服务器上运行,还能根据流量自动扩容或者缩容,确保应用始终保持高可用性。

再举个例子:假设你经营一个全球连锁的快递公司,每天都有成千上万的集装箱到达各个港口。如果没有一个智能的管理系统,你需要手动决定每个集装箱应该放在哪个仓库、什么时候发货、运输中如何调度,甚至在货物需求增加时,你还得临时增加人手来处理这些集装箱。

而Kubernetes就是这个智能的“码头管理系统”。它会根据你的需求,自动分配集装箱到各个港口,确保货物按时到达。如果某个港口的集装箱积压了,它可以自动将多余的货物调度到别的港口,保证高效运转。当货物需求增加时,它甚至可以“雇佣”更多的卡车来处理这些集装箱——这就是Kubernetes的自动扩展功能。

整体的架构与关系可以用这张图表示:

  • Docker:将应用打包成标准化的容器,确保在不同环境下都能一致运行。

  • Kubernetes:管理和调度这些容器,自动分配资源、扩展应用,并保证高可用性。

基于 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 实现的后台管理系统 + 用户小程序,支持 RBAC 动态权限、多租户、数据权限、工作流、三方登录、支付、短信、商城等功能

  • 项目地址:https://github.com/YunaiV/yudao-cloud

  • 视频教程:https://doc.iocoder.cn/video/

实操

在上文中已经明确了我们本次所使用的服务,这里再详细说明下每个服务所起的作用:

  • GitHub Actions:GitHub 的 CI/CD 工具,帮助我们实现代码提交后的自动化流程。

  • 阿里云 Kubernetes(ACK):阿里云的托管 Kubernetes 服务。

  • 阿里云容器镜像服务(ACR):Docker 镜像仓库,用于存储和管理 Docker 镜像。

  • Spring Boot:作为示例的 Java Web 应用框架。

同时,再对我们整个操作流程画图说明一下,如下:

1.开发Web应用

本篇的重点不在于应用,所以我们用Spring Boot简单起个应用,写个hello World的接口可以访问到就行,主要代码如下:

@RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello World!"; } }

编写完成后,先在本地启动测试下,确保应用可以正常使用,如下:

然后把它推送到Github仓库即可。

2.创建Kubernetes集群

直接登录阿里云控制台,搜索ACK即可找到容器服务 Kubernetes,如下:

我们这里只是演示,越简单越好,就买ACK托管版就可以了,配置就选最便宜的,然后一路下一步就行,如下:

等待几分钟,集群创建成功,如下:

集群创建完成后,进入集群的详情页面,点击连接信息,下载kubeconfig文件,这个文件包含你的集群配置信息,后续会用到它来访问集群。这里提一下,我们要的是公网访问的配置文件,如下:

3.创建阿里云容器镜像服务(ACR)

我们需要一个存储Docker镜像的地方,阿里云容器镜像服务(ACR)就是用来存储和管理 Docker 镜像的。在控制台搜索容器镜像服务,如下:

这里创建个人实例即可,如下:

点击 创建命名空间,为镜像仓库创建一个命名空间,如下:

创建完命名空间后,再点击 创建镜像仓库,如下:

创建完成后,可以得到仓库的连接相关信息,如下:

这些凭证将用于GitHub Actions登录ACR,推送Docker 镜像。

4.配置GitHub仓库Secrets

接下来,我们需要将阿里云的相关凭证添加到GitHub仓库的Secrets中,这样GitHub Actions才能安全地访问阿里云的资源。

首先打开你的 GitHub 仓库,点击Settings,然后选择左侧的Secrets and variables下的Actions,再点击New repository secret,如下:

然后添加相关的Secrets,这里需要注意一下,因为后续的配置需要用到它们,所以这里的名称需要和后续的配置文件中保持一致,否则读取不到打包会报错的,如下:

  • ALIYUN_REGISTRY_USERNAME:阿里云容器镜像服务(ACR)的用户名。

  • ALIYUN_REGISTRY_PASSWORD:阿里云容器镜像服务(ACR)的密码。

  • ALIYUN_REGISTRY_URL:ACR 镜像仓库的登录地址。

  • ALIYUN_NAMESPACE:ACR 命名空间。

  • ALIYUN_REPO_NAME:ACR 镜像仓库名称。

  • ALIYUN_KUBECONFIG:将之前下载的 kubeconfig 文件内容复制粘贴到这里,用于后续 GitHub Actions 通过 kubectl 访问 Kubernetes 集群。

5.创建GitHub Actions工作流

接下来在项目的根目录中,创建一个文件.github/workflows/ci-cd.yml(Ps:文件名随意,目录必须一致),并添加以下内容:

name: CI/CD for Spring Boot Hello World on: push: branches: - master jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Set up JDK 17 uses: actions/setup-java@v2 with: distribution: 'temurin' java-version: '17' - name: Build with Maven run: mvn clean package - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Log in to ACR run: | docker login \ --username=${{ secrets.ALIYUN_REGISTRY_USERNAME }} \ ${{ secrets.ALIYUN_REGISTRY_URL }} \ --password=${{ secrets.ALIYUN_REGISTRY_PASSWORD }} - name: Build and Push Docker image run: | # 构建本地镜像 docker build -t springboot-hello-world:latest . # 打标签 docker tag springboot-hello-world:latest ${{ secrets.ALIYUN_REGISTRY_URL }}/${{ secrets.ALIYUN_NAMESPACE }}/${{ secrets.ALIYUN_REPO_NAME }}:latest # 推送镜像 docker push ${{ secrets.ALIYUN_REGISTRY_URL }}/${{ secrets.ALIYUN_NAMESPACE }}/${{ secrets.ALIYUN_REPO_NAME }}:latest deploy: needs: build runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v2 - name: Set up kubectl uses: azure/setup-kubectl@v3 with: version: 'latest' - name: Configure kubectl run: | mkdir -p $HOME/.kube echo "${{ secrets.ALIYUN_KUBECONFIG }}" > $HOME/.kube/config chmod 600 $HOME/.kube/config - name: Deploy to Kubernetes run: | kubectl set image deployment/springboot-hello-world springboot-hello-world=${{ secrets.ALIYUN_REGISTRY_URL }}/${{ secrets.ALIYUN_NAMESPACE }}/${{ secrets.ALIYUN_REPO_NAME }}:latest

项目打包需要我们编写Dockerfile,也很简单,根据实际情况简单配下就行,示例如下:

FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]

现在我们往Master分支上提交代码就会自动触发action来帮助我们打包镜像,如下:

在实际业务场景中,我们会存在测试、生产等多个环境的分支,都需要进行自动化构建,也是很简单,在上面的配置里加上其他分支即可。由于我们的应用非常简单,所以整个打包的时间也相对较短,打包成功后,如下:

6.创建Kubernetes集群配置:

最后还需要我们在项目里添加一下Kubernetes集群的相关配置,如下:

apiVersion: apps/v1 kind: Deployment metadata: name: springboot-hello-world spec: replicas: 1 selector: matchLabels: app: springboot-hello-world template: metadata: labels: app: springboot-hello-world spec: containers: - name: springboot-hello-world image: registry.cn-hangzhou.aliyuncs.com/my-app/springboot-hello-world:latest ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: springboot-hello-world-service spec: selector: app: springboot-hello-world ports: - protocol: TCP port: 80 targetPort: 8080 type: LoadBalancer

提交到仓库后,可以在Kubernetes集群的控制台里看到我们的服务实例了,如下:

7.访问以及版本管理

部署成功后,访问下公网ip,也可以正常访问我们的应用,如下:

按照我们现有的配置,我们后续每次向Master分支提交代码都会自动打包以及更新我们的服务,比如我们在接口的响应上加上123,代码如下:

@RestController public class HelloController { @GetMapping("/hello") public String hello() { return "Hello World! 123"; } }

等待打包成功后,再次访问,会看到已经更新了,如下:

如果我们发布的新版本应用有BUG,需要回滚,操作也是非常简单,进入到集群详情-历史版本里就可以看到我们的版本记录,如下:

想要回滚到哪个版本直接点击回滚到该版本即可。

小结

相信大家看到这里对于整个流程也有了清晰的认识,可以根据自己的实际选择适合的来替换某个节点的服务或工具。另外,可能有人会说把代码发到Github上等于把业务泄露了。

我这里说下我的看法:本身针对小团队肯定越快越好,自然不用搭建的是最快的。另外,把仓库设为私有仓库,开发人员的权限简单配置下就足够用了。等你体量做大了,自然也不需要用它了。


欢迎加入我的知识星球,全面提升技术能力。

👉 加入方式,长按”或“扫描”下方二维码噢

星球的内容包括:项目实战、面试招聘、源码解析、学习路线。

文章有帮助的话,在看,转发吧。 谢谢支持哟 (*^__^*)
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/23 11:40:37

ACE-Step:开源AI音乐生成模型快速上手

ACE-Step:开源AI音乐生成模型快速上手 政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 希望政安晨的博客能够对您有所裨益,如有不足之处,欢迎在评论区提出指正! 你有没有想过,有一天只需输…

作者头像 李华
网站建设 2026/4/23 11:40:39

多模态向量检索技术深度解析:从理论突破到产业实践

多模态向量检索技术深度解析:从理论突破到产业实践 【免费下载链接】qdrant Qdrant - 针对下一代人工智能的高性能、大规模向量数据库。同时提供云端版本 项目地址: https://gitcode.com/GitHub_Trending/qd/qdrant 在人工智能技术快速发展的当下&#xff0c…

作者头像 李华
网站建设 2026/4/23 11:40:17

JVM面试篇总结

一、JVM基础概念 1.1 JVM定义与作用 定义:Java虚拟机(Java Virtual Machine)本质上是一个运行在计算机上的程序,负责运行Java字节码文件跨平台特性:支持"Write Once, Run Anywhere"理念,将Java源代码编译成字节码后&…

作者头像 李华
网站建设 2026/4/23 11:40:19

YOLO11-AIFI重型设备检测与识别--建筑工地十类设备自动定位_1

20230701_HeavyEquipment 数据集是一个专为计算机视觉应用设计的建筑工地重型设备检测数据集,该数据集采用 CC BY 4.0 许可证,由 qunshankj 平台用户贡献并提供。数据集包含 3962 张建筑工地场景图像,其中部分图像已采用 YOLOv8 格式进行标注…

作者头像 李华
网站建设 2026/4/23 11:40:18

农业大棚材质识别与分类全流程:从数据采集到模型部署的实战指南

1. 农业大棚材质识别与分类全流程:从数据采集到模型部署的实战指南 在现代农业发展中,农业大棚的材质识别与分类对于提高农业生产效率、优化资源配置具有重要意义。本文将详细介绍从数据采集到模型部署的完整流程,帮助读者构建一个实用的农业…

作者头像 李华
网站建设 2026/4/23 11:40:35

开题报告卡在“研究意义”三天没动?你可能缺的不是灵感,而是一个“学术搭桥人 宏智树AI

上周五,我在自习室偶遇一位大四学妹,她对着空白的Word文档发呆,光标在“一、选题背景与研究意义”后面闪烁了整整两个小时——不是没想法,而是不知道怎么把“我想研究短视频对大学生注意力的影响”变成一段导师认可的学术表述。 …

作者头像 李华