在 Spring Boot 应用开发中,将代码从本地推到远程仓库只是第一步,后续的构建、测试、部署如果全靠手动执行,不仅耗时而且容易遗漏步骤。CircleCI 作为一款基于云的持续集成与持续交付平台,可以与 GitHub、Bitbucket 等代码托管服务深度集成,当检测到代码变更时自动运行流水线。本文演示如何为一个标准的 Spring Boot 项目接入 CircleCI,完成从提交代码到部署上线的完整闭环。这里假设项目使用 Maven 构建,JDK 版本为 17,部署目标是一台 Linux 服务器,并采用 Docker 容器运行应用。

一、准备 Spring Boot 项目与 CircleCI 基础配置
任何 CI/CD 流水线的起点都是一个可构建、可测试的项目。Spring Boot 项目通常基于 Maven 或 Gradle,本文以 Maven 为例。确认 pom.xml 中配置了 spring-boot-maven-plugin,该插件负责将应用打成可执行 jar。若计划用 Docker 部署,还需要在项目根目录放置 Dockerfile,内容稍后给出。为了让 CircleCI 识别流水线,必须在仓库根目录建立 .circleci 目录,并在其中创建 config.yml 文件。CircleCI 会在代码推送到默认分支时读取该文件并执行定义好的任务。
CircleCI 的配置文件使用 YAML 语法,核心结构包括 version、jobs、workflows。version 固定为 2.1,jobs 定义独立的执行单元,每个 job 可以指定运行环境(如 docker 镜像)、执行步骤(steps),steps 中可以运行 shell 命令或使用内置的 CircleCI orb。workflows 用于编排多个 job 的执行顺序、依赖关系和触发条件。下面是一个最小化的配置,它只完成构建和测试,不涉及部署。
version: 2.1
jobs:
build:
docker:
- image: cimg/openjdk:17.0
steps:
- checkout
- run:
name: Build with Maven
command: ./mvnw clean package -DskipTests
- run:
name: Run tests
command: ./mvnw test
workflows:
build_and_test:
jobs:
- build
在上面配置中,cimg/openjdk:17.0 是 CircleCI 提供的 Java 17 镜像,checkout 步骤将代码从仓库拉取到构建容器。./mvnw 是 Maven Wrapper 脚本,它保证构建环境与本地使用的 Maven 版本一致,避免因服务器缺少 Maven 导致失败。如果项目没有 Maven Wrapper,也可以直接用 mvn 命令,但需要确保镜像中已包含 Maven。实际生产中建议始终使用 Wrapper,它能减少环境差异带来的不可预测性。测试步骤单独拆分,便于在日志中定位失败原因。
二、构建 Docker 镜像并推送到镜像仓库
单纯构建 jar 并不等于完成交付,很多团队选择用 Docker 容器部署 Spring Boot 应用,因为容器能统一运行环境、方便水平扩展。在 CI/CD 中,构建完 jar 文件后,紧接着就可以基于 Dockerfile 构建镜像并推送到镜像仓库,例如 Docker Hub 或私有 Harbor。Dockerfile 通常采用多阶段构建,先在 Maven 镜像中打包,再在 JRE 镜像中运行,以减小镜像体积。下面给出一个常见的 Dockerfile。
# 第一阶段:构建 FROM maven:3.9-eclipse-temurin-17 AS build WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn clean package -DskipTests # 第二阶段:运行 FROM eclipse-temurin:17-jre-alpine WORKDIR /app COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
对应地,需要在 CircleCI 配置中添加 Docker 构建与推送步骤。这里不能直接使用默认的 Java 镜像,因为它没有 Docker CLI。推荐使用 CircleCI 的 docker orb,或者选择带 Docker 客户端的基础镜像。更简单的方式是使用 CircleCI 官方提供的 setup_remote_docker 配合 docker 镜像。下面展示使用 cimg/base 镜像并启用 Docker 的配置。先登录 Docker Hub,需要将用户名和密码配置到 CircleCI 项目的环境变量中,例如 DOCKERHUB_USERNAME 和 DOCKERHUB_PASSWORD。然后执行 docker build 和 docker push。为了加速构建,可以在步骤前添加 restore_cache 和 save_cache 缓存 Maven 依赖。
version: 2.1
jobs:
build_and_publish:
docker:
- image: cimg/base:stable
steps:
- checkout
- setup_remote_docker:
version: 20.10.14
- restore_cache:
keys:
- maven-cache-{{ checksum "pom.xml" }}
- run:
name: Build jar with Maven
command: ./mvnw clean package -DskipTests
- save_cache:
key: maven-cache-{{ checksum "pom.xml" }}
paths:
- ~/.m2
- run:
name: Build Docker image
command: |
docker build -t yourusername/springboot-demo:latest .
- run:
name: Push Docker image
command: |
echo "$DOCKERHUB_PASSWORD" | docker login -u "$DOCKERHUB_USERNAME" --password-stdin
docker push yourusername/springboot-demo:latest
workflows:
pipeline:
jobs:
- build_and_publish
上面配置中,setup_remote_docker 会创建一个独立的 Docker 守护进程供构建容器使用,docker build 命令会在这个远程守护进程上执行。缓存部分通过 checksum pom.xml 判断依赖是否变化,如果 pom.xml 未修改,则直接使用缓存,大大缩短构建时间。推送镜像前必须完成 docker login,密码通过 echo 管道传入,避免明文出现在配置文件中。实际项目中,建议为每个提交生成唯一标签,例如使用 CIRCLE_SHA1 环境变量作为镜像 tag,以便回滚和追踪。
三、自动部署到服务器并加入审批流程
镜像推送成功后,还需要让服务器拉取最新镜像并重启容器。这一步通常通过 SSH 远程执行命令来完成。CircleCI 可以在构建阶段添加部署 job,使用 SSH 私钥连接服务器。首先在服务器上生成一对 SSH 密钥,公钥放在 authorized_keys,私钥通过 CircleCI 的环境变量或 SSH 密钥配置注入。然后在 job 中执行 ssh 命令,完成 docker pull 和 docker run。为了避免每次手动输入密码,建议使用 CircleCI 的 add_ssh_keys 步骤或者将私钥以环境变量形式写入。下面是一个部署 job 的片段。
deploy:
docker:
- image: cimg/base:stable
steps:
- add_ssh_keys:
fingerprints:
- "xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx:xx"
- run:
name: Deploy over SSH
command: |
ssh -o StrictHostKeyChecking=no deploy@your-server-ip "docker pull yourusername/springboot-demo:latest && docker stop springboot-demo || true && docker rm springboot-demo || true && docker run -d --name springboot-demo -p 8080:8080 yourusername/springboot-demo:latest"
将 deploy job 加入到 workflows 中,并设置 requires 依赖 build_and_publish,这样只有镜像推送成功才会执行部署。为了控制发布节奏,可以在部署前增加一个 approval 类型 job,由人工确认后才继续。这适用于测试环境和生产环境分开的场景。下面展示完整的 workflows 配置,包含构建、审批和部署三个阶段。
workflows:
build_and_deploy:
jobs:
- build_and_publish
- wait_for_approval:
type: approval
requires:
- build_and_publish
- deploy:
requires:
- wait_for_approval
SSH 部署虽然直接,但存在安全隐患,例如私钥泄露、服务器地址暴露等。更稳妥的做法是使用部署工具如 Ansible、Capistrano,或者将部署交给 Kubernetes、云平台的原生服务。对于小团队或个人项目,SSH 方案足够简单高效。无论采用哪种方式,敏感信息都应放在 CircleCI 的项目环境变量或上下文中,而不是写死在 config.yml。上下文(Context)允许在组织级别共享变量,还可以限制只有特定项目才能使用。另外,部署命令中的 || true 是为了避免容器不存在时 docker stop 返回非零导致整个步骤失败。生产环境部署建议加入健康检查、自动回滚和通知机制。
四、常见问题与优化建议
接入 CircleCI 后,最常见的痛点就是构建时间过长。除了缓存 Maven 或 Gradle 依赖,还可以拆分 job 并行运行测试,或者使用 CircleCI 的 test splitting 功能将测试用例分配到多个容器。Spring Boot 项目如果包含大量集成测试,建议将单元测试与集成测试分离,单元测试在快速镜像中运行,集成测试在专用 job 中运行。另外,构建 Docker 镜像时,将不变层放在前面(例如先拷贝 pom.xml 再拷贝源码)可以充分利用镜像层缓存。
配置文件中的 YAML 缩进错误是另一个高频问题。CircleCI 的 config.yml 对缩进非常敏感,建议使用支持 YAML 的编辑器,并在本地用 circleci config validate 命令校验。Maven Wrapper 脚本如果没有执行权限,会报 Permission denied,需要在提交前执行 chmod +x mvnw。此外,如果项目是多模块 Maven,需要指定 -pl 参数,否则打包可能失败。环境变量在 job 中不会自动继承,必须显式声明或通过 run 步骤 export。例如构建镜像时需要传入 SPRING_PROFILES_ACTIVE,可以在 Dockerfile 的 ENV 中设置,也可以在 docker run 时通过 -e 传入。
CircleCI 提供了丰富的 Orb 来复用配置,例如 circleci/maven、circleci/docker、circleci/aws-ecs 等。使用 Orb 可以减少重复配置,但也会增加学习成本。对于刚接触的团队,建议先使用原生命令理解每个步骤的作用,后续再逐步引入 Orb。通知方面,可以在 Slack、邮件或钉钉中配置 Webhook,当流水线失败时及时告知。最后,CI/CD 不是一次性配置完就结束,需要根据项目变化持续调整。定期回顾构建时间、失败率和部署成功率,才能让流水线真正服务于研发效率。
Spring BootCircleCICI/CD修改时间:2026-09-20 00:30:45