当前位置: 代码网 > it编程>编程语言>其他编程 > 在Ubuntu22.04上使用GitLab和Jenkins部署CI/CD实践

在Ubuntu22.04上使用GitLab和Jenkins部署CI/CD实践

2026年01月26日 其他编程 我要评论
详细介绍在ubuntu 22.04上使用gitlab和jenkins部署ci/cd的完整过程。环境准备1. 系统初始化# 更新系统sudo apt update && sudo apt

详细介绍在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配置

安装必要插件

访问 jenkins: http://your-server-ip:8080

安装插件:

  • gitlab plugin
  • pipeline
  • maven integration
  • docker pipeline
  • blue ocean

创建pipeline任务

新建item → 选择 pipeline

配置:

创建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配置

在gitlab项目中

  • settings → webhooks
  • url: http://jenkins-server:8080/project/spring-boot-demo
  • secret token: (生成并复制)

在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案例包含了从环境搭建到自动化部署的全过程,可以根据实际需求进行调整和扩展。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持代码网。

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2026  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com