news 2026/10/7 15:54:48

在Ubuntu 22.04上使用GitLab和Jenkins部署CI/CD的完整过程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
在Ubuntu 22.04上使用GitLab和Jenkins部署CI/CD的完整过程

详细介绍在Ubuntu 22.04上使用GitLab和Jenkins部署CI/CD的完整过程。

环境准备

1. 系统初始化

# 更新系统 sudo apt update && sudo apt upgrade -y # 安装必要工具 sudo apt install -y curl wget git vim

2. 安装Docker(推荐方式)

# 安装Docker sudo apt install -y docker.io docker-compose sudo systemctl enable docker sudo systemctl start docker # 将当前用户添加到docker组 sudo usermod -aG docker $USER

第一部分:GitLab安装与配置

1. 使用Docker安装GitLab

# 创建GitLab数据目录 sudo mkdir -p /srv/gitlab/{config,data,logs} # 创建docker-compose.yml cat > docker-compose-gitlab.yml << 'EOF' version: '3.6' services: gitlab: image: gitlab/gitlab-ce:latest container_name: gitlab restart: always hostname: 'gitlab.example.com' # 修改为您的域名或IP environment: GITLAB_OMNIBUS_CONFIG: | external_url 'http://192.168.1.100' # 修改为您的IP或域名 gitlab_rails['gitlab_shell_ssh_port'] = 2222 gitlab_rails['smtp_enable'] = false gitlab_rails['time_zone'] = 'Asia/Shanghai' ports: - "80:80" - "443:443" - "2222:22" volumes: - /srv/gitlab/config:/etc/gitlab - /srv/gitlab/logs:/var/log/gitlab - /srv/gitlab/data:/var/opt/gitlab networks: - gitlab-network shm_size: '256m' networks: gitlab-network: driver: bridge EOF # 启动GitLab docker-compose -f docker-compose-gitlab.yml up -d

2. 配置GitLab

# 获取初始root密码 sudo docker exec -it gitlab cat /etc/gitlab/initial_root_password # 登录GitLab (http://your-server-ip) # 用户名: root # 密码: 从上述命令获取

第二部分:Jenkins安装与配置

1. 使用Docker安装Jenkins

# 创建Jenkins数据目录 sudo mkdir -p /srv/jenkins_home # 设置目录权限 sudo chown -R 1000:1000 /srv/jenkins_home # 创建docker-compose.yml cat > docker-compose-jenkins.yml << 'EOF' version: '3.7' services: jenkins: image: jenkins/jenkins:lts-jdk17 container_name: jenkins restart: always user: "1000:1000" # 使用非root用户 ports: - "8080:8080" - "50000:50000" volumes: - /srv/jenkins_home:/var/jenkins_home - /var/run/docker.sock:/var/run/docker.sock - /usr/bin/docker:/usr/bin/docker environment: - JAVA_OPTS=-Djenkins.install.runSetupWizard=false networks: - jenkins-network networks: jenkins-network: driver: bridge EOF # 启动Jenkins docker-compose -f docker-compose-jenkins.yml up -d # 查看初始管理员密码 sudo cat /srv/jenkins_home/secrets/initialAdminPassword

第三部分:案例实战 - Spring Boot应用CI/CD

1. 准备示例项目

# 在GitLab创建新项目 # 项目名称: spring-boot-demo # 可见性: Private # 本地准备Spring Boot项目 mkdir spring-boot-demo && cd spring-boot-demo # 创建项目结构 cat > pom.xml << 'EOF' <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spring-boot-demo</artifactId> <version>1.0.0</version> <packaging>jar</packaging> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.0</version> <relativePath/> </parent> <properties> <java.version>17</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project> EOF # 创建Java源码 mkdir -p src/main/java/com/example/demo cat > src/main/java/com/example/demo/DemoApplication.java << 'EOF' package com.example.demo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; @SpringBootApplication @RestController public class DemoApplication { @GetMapping("/") public String hello() { return "Hello from Spring Boot CI/CD Pipeline!"; } @GetMapping("/health") public String health() { return "Status: UP"; } public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); } } EOF # 创建测试文件 mkdir -p src/test/java/com/example/demo cat > src/test/java/com/example/demo/DemoApplicationTest.java << 'EOF' package com.example.demo; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; @SpringBootTest @AutoConfigureMockMvc class DemoApplicationTest { @Autowired private MockMvc mockMvc; @Test void testHelloEndpoint() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/")) .andExpect(status().isOk()) .andExpect(content().string("Hello from Spring Boot CI/CD Pipeline!")); } @Test void testHealthEndpoint() throws Exception { mockMvc.perform(MockMvcRequestBuilders.get("/health")) .andExpect(status().isOk()) .andExpect(content().string("Status: UP")); } } EOF # 创建Dockerfile cat > Dockerfile << 'EOF' FROM openjdk:17-jdk-slim AS builder WORKDIR /app COPY . . RUN ./mvnw clean package -DskipTests FROM openjdk:17-jre-slim WORKDIR /app COPY --from=builder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"] EOF # 创建部署脚本 cat > deploy.sh << 'EOF' #!/bin/bash # 部署脚本 set -e APP_NAME="spring-boot-demo" CONTAINER_NAME="spring-boot-app" VERSION=${BUILD_NUMBER:-latest} echo "开始部署版本: $VERSION" # 停止并删除旧容器 docker stop $CONTAINER_NAME || true docker rm $CONTAINER_NAME || true # 运行新容器 docker run -d \ --name $CONTAINER_NAME \ --restart always \ -p 8081:8080 \ -e SPRING_PROFILES_ACTIVE=prod \ $APP_NAME:$VERSION echo "部署完成!" docker ps | grep $CONTAINER_NAME EOF chmod +x deploy.sh # 创建.gitlab-ci.yml cat > .gitlab-ci.yml << 'EOF' stages: - build - test - package - deploy variables: MAVEN_OPTS: "-Dmaven.repo.local=.m2/repository" cache: paths: - .m2/repository/ - target/ build: stage: build image: maven:3.8.6-openjdk-17 script: - mvn clean compile artifacts: paths: - target/ test: stage: test image: maven:3.8.6-openjdk-17 script: - mvn test coverage: '/Total.*?([0-9]{1,3})%/' package: stage: package image: maven:3.8.6-openjdk-17 script: - mvn package -DskipTests artifacts: paths: - target/*.jar deploy: stage: deploy image: docker:latest services: - docker:dind variables: DOCKER_HOST: tcp://docker:2375 DOCKER_DRIVER: overlay2 script: - docker build -t spring-boot-demo:$CI_COMMIT_SHORT_SHA . - docker tag spring-boot-demo:$CI_COMMIT_SHORT_SHA spring-boot-demo:latest - docker run -d -p 8081:8080 --name spring-boot-app spring-boot-demo:latest only: - main environment: name: production url: http://your-server-ip:8081 EOF

2. Jenkins配置

安装必要插件
  1. 访问 Jenkins: http://your-server-ip:8080

  2. 安装插件:

    • GitLab Plugin

    • Pipeline

    • Maven Integration

    • Docker Pipeline

    • Blue Ocean

创建Pipeline任务
  1. 新建Item→ 选择Pipeline

  2. 配置:

    • Pipeline: Pipeline script from SCM

    • SCM: Git

    • Repository URL: http://gitlab-server/root/spring-boot-demo.git

    • Credentials: 添加GitLab凭据

    • Branch Specifier: */main

    • Script Path: Jenkinsfile

  3. 创建Jenkinsfile(在项目根目录)

groovy

pipeline { agent any tools { maven 'Maven-3.8' jdk 'JDK-17' } stages { stage('Checkout') { steps { git branch: 'main', url: 'http://gitlab-server/root/spring-boot-demo.git', credentialsId: 'gitlab-credentials' } } stage('Build') { steps { sh 'mvn clean compile' } } stage('Unit Test') { steps { sh 'mvn test' } post { always { junit 'target/surefire-reports/*.xml' } } } stage('Code Analysis') { steps { sh 'mvn checkstyle:checkstyle pmd:pmd' } } stage('Package') { steps { sh 'mvn package -DskipTests' } post { success { archiveArtifacts 'target/*.jar' } } } stage('Build Docker Image') { steps { script { docker.build("spring-boot-demo:${env.BUILD_ID}") } } } stage('Deploy to Test') { steps { sh ''' docker stop spring-boot-test || true docker rm spring-boot-test || true docker run -d --name spring-boot-test -p 8082:8080 spring-boot-demo:${BUILD_ID} ''' } } stage('Integration Test') { steps { sh ''' sleep 10 # 等待应用启动 curl -f http://localhost:8082/health || exit 1 ''' } } stage('Deploy to Production') { when { branch 'main' } steps { sh ''' docker tag spring-boot-demo:${BUILD_ID} spring-boot-demo:latest docker stop spring-boot-prod || true docker rm spring-boot-prod || true docker run -d --name spring-boot-prod -p 8081:8080 --restart always spring-boot-demo:latest ''' } } } post { success { emailext ( subject: "构建成功: ${env.JOB_NAME} - ${env.BUILD_NUMBER}", body: "项目构建成功,请访问: http://your-server-ip:8081", to: 'admin@example.com' ) } failure { emailext ( subject: "构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}", body: "项目构建失败,请检查日志", to: 'admin@example.com' ) } } }

3. GitLab Webhook配置

  1. 在GitLab项目中:

    • Settings → Webhooks

    • URL: http://jenkins-server:8080/project/spring-boot-demo

    • Secret Token: (生成并复制)

  2. 在Jenkins中:

    • 项目配置 → Build Triggers

    • 勾选 "Build when a change is pushed to GitLab"

    • 添加Secret Token (与GitLab中相同)

第四部分:CI/CD流程测试

1. 推送代码触发构建

# 初始化Git仓库 git init git add . git commit -m "Initial commit" git remote add origin http://gitlab-server/root/spring-boot-demo.git git push -u origin main

2. 监控流程

# 查看Jenkins构建日志 docker logs -f jenkins # 查看应用运行状态 docker ps # 测试应用 curl http://localhost:8081 curl http://localhost:8081/health

第五部分:高级配置

1. 配置Slack通知

# Jenkins安装Slack Notification插件 # Jenkinsfile中添加 post { success { slackSend( color: 'good', message: "构建成功: ${env.JOB_NAME} - ${env.BUILD_NUMBER}" ) } failure { slackSend( color: 'danger', message: "构建失败: ${env.JOB_NAME} - ${env.BUILD_NUMBER}" ) } }

2. 配置SonarQube代码质量检查

groovy

stage('SonarQube Analysis') { steps { withSonarQubeEnv('sonarqube-server') { sh 'mvn sonar:sonar' } } }

3. 使用Kubernetes部署

yaml

# 创建k8s部署文件 deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: spring-boot-app spec: replicas: 3 selector: matchLabels: app: spring-boot-app template: metadata: labels: app: spring-boot-app spec: containers: - name: spring-boot-app image: spring-boot-demo:latest ports: - containerPort: 8080

故障排除

常见问题解决

# 1. Jenkins无法连接GitLab # 检查网络连通性 docker network ls docker network connect gitlab-network jenkins # 2. Maven构建缓慢 # 配置阿里云镜像 mkdir -p ~/.m2 cat > ~/.m2/settings.xml << 'EOF' <settings> <mirrors> <mirror> <id>aliyun</id> <name>Aliyun Maven Mirror</name> <url>https://maven.aliyun.com/repository/public</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors> </settings> EOF # 3. Docker权限问题 sudo chmod 666 /var/run/docker.sock # 4. 查看日志 docker logs gitlab docker logs jenkins journalctl -u docker --follow

这个完整的CI/CD案例包含了从环境搭建到自动化部署的全过程,可以根据实际需求进行调整和扩展。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 23:58:34

苹果宣布专业图像编辑应用Pixelmator Pro即将登陆iPad

根据苹果关于即将推出的Apple Creator Studio的新闻稿&#xff0c;Pixelmator Pro将为iPad用户带来桌面级的设计体验。直观的触控操作让用户能够更轻松地在iPad上创建桌面级设计作品。全功能的图层侧边栏允许创作者使用图像、形状、文本甚至视频等多种独特元素来构建设计。智能…

作者头像 李华
网站建设 2026/10/5 1:48:54

告别文献 “乱炖”!宏智树 AI 手把手教你写出有灵魂的文献综述

作为深耕论文写作科普的教育博主&#xff0c;后台总能刷到这样的求助&#xff1a;“读了几十篇文献&#xff0c;写出来的综述像‘大杂烩’”“观点堆砌没逻辑&#xff0c;被导师批‘没找到研究缺口’”“参考文献格式错一堆&#xff0c;查重率还居高不下”。文献综述不是简单的…

作者头像 李华
网站建设 2026/10/7 5:28:00

0x3f第32天复习 (12;30-12:50)

子串基础前缀和思考前缀和的定义是什么和为k的子数组1min ac两数之和接雨水三数之和ac字母异位词分组ac最长连续序列ac移动零ac无重复字符的最长子串ac找到字符串中所有字母异位词ac滑动窗口最大值1min ac1min ac最小覆盖子串1min ac1min ac思考买卖股票的最佳时机1min ac1min …

作者头像 李华
网站建设 2026/10/5 4:53:58

大模型算法社招面试全攻略:技术要点+简历优化+代码题解析

本文作者分享了从国企跳槽至大模型算法领域社招的完整经历。详细介绍了职业规划考量、简历准备技巧&#xff0c;以及大模型相关技术面试要点&#xff0c;包括SFT、RAG、Agent等热门技术方向。同时提供了常见代码题考察情况和业务方向分析&#xff0c;为想进入大模型领域的求职者…

作者头像 李华
网站建设 2026/10/7 14:11:43

算法题 增减字符串匹配

942. 增减字符串匹配 问题描述 给定只含 "I"&#xff08;增加&#xff09;和 "D"&#xff08;减少&#xff09;的字符串 s&#xff0c;令 n s.length。 根据 s 构造一个排列 perm&#xff08;长度为 n 1&#xff09;&#xff0c;使得对于所有的 i&#x…

作者头像 李华
网站建设 2026/10/5 4:53:47

基于Django的蔬菜批发管理系统设计与实现

基于Django的蔬菜批发管理系统设计与实现 一、系统开发背景与意义 蔬菜批发行业作为农产品流通的关键环节&#xff0c;长期面临供应链效率低、损耗率高、交易流程繁琐等问题。传统模式下&#xff0c;供应商信息分散导致采购比价困难&#xff0c;库存依赖人工盘点易造成积压或缺…

作者头像 李华