在Ubuntu22.04上使用GitLab和Jenkins部署CI/CD實踐
詳細介紹在Ubuntu 22.04上使用GitLab和Jenkins部署CI/CD的完整過程。
環(huán)境準備
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
# 創(chuàng)建GitLab數據目錄
sudo mkdir -p /srv/gitlab/{config,data,logs}
# 創(chuàng)建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 -d2. 配置GitLab
# 獲取初始root密碼 sudo docker exec -it gitlab cat /etc/gitlab/initial_root_password # 登錄GitLab (http://your-server-ip) # 用戶名: root # 密碼: 從上述命令獲取
第二部分:Jenkins安裝與配置
1. 使用Docker安裝Jenkins
# 創(chuàng)建Jenkins數據目錄
sudo mkdir -p /srv/jenkins_home
# 設置目錄權限
sudo chown -R 1000:1000 /srv/jenkins_home
# 創(chuàng)建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第三部分:案例實戰(zhàn) - Spring Boot應用CI/CD
1. 準備示例項目
# 在GitLab創(chuàng)建新項目
# 項目名稱: spring-boot-demo
# 可見性: Private
# 本地準備Spring Boot項目
mkdir spring-boot-demo && cd spring-boot-demo
# 創(chuàng)建項目結構
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
# 創(chuàng)建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
# 創(chuàng)建測試文件
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
# 創(chuàng)建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
# 創(chuàng)建部署腳本
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
# 創(chuàng)建.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
EOF2. Jenkins配置
安裝必要插件
訪問 Jenkins: http://your-server-ip:8080
安裝插件:
- GitLab Plugin
- Pipeline
- Maven Integration
- Docker Pipeline
- Blue Ocean
創(chuàng)建Pipeline任務
新建Item → 選擇 Pipeline
配置:
- 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
創(chuàng)建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. 推送代碼觸發(fā)構建
# 初始化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. 監(jiān)控流程
# 查看Jenkins構建日志 docker logs -f jenkins # 查看應用運行狀態(tài) 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
# 創(chuàng)建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案例包含了從環(huán)境搭建到自動化部署的全過程,可以根據實際需求進行調整和擴展。
總結
以上為個人經驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
- Jenkins集成Gitlab實現自動化部署的全過程記錄
- 使用GitLab+Jenkins實現持續(xù)集成CI環(huán)境的示例代碼
- GitLab+Jenkins+Maven+Tomcat?實現自動集成、打包、部署
- docker+gitlab+jenkins從零搭建自動化部署
- jenkins+gitlab+nginx部署前端應用實現
- 基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持續(xù)集成交付環(huán)境的詳細教程
- 詳解Jenkins 實現Gitlab事件自動觸發(fā)Jenkins構建及釘釘消息推送
- Docker Gitlab+Jenkins+Harbor構建持久化平臺操作
- 詳解Docker+Jenkins+Gitlab+Django應用部署實踐
相關文章
LNMP下FTP服務器的安裝與使用方法(Pureftpd和Proftpd)
FTP是網站文件維護中使用比較多的,目前LNMP一鍵安裝包中有Pureftpd和Proftpd服務器安裝腳本2013-06-06
Apache使用.htaccess 屏蔽惡意 User Agent(防蜘蛛)
這篇文章主要介紹了Apache使用.htaccess 屏蔽惡意 User Agent(防蜘蛛),需要的朋友可以參考下2016-07-07
在 Apache 中創(chuàng)建單個文件的別名的操作方法
要創(chuàng)建 Apache 中的單個文件的別名,您可以在 Apache 配置文件中使用 Alias 指令,Alias 指令允許您將 URL 路徑映射到文件系統位置,該路徑可以是目錄或單個文件,本文介紹如何在 Apache 中創(chuàng)建單個文件的別名,感興趣的朋友一起看看吧2024-12-12
linux corosync+pacemaker+drbd+mysql配置安裝詳解
這篇文章主要介紹了corosync+pacemaker+drbd+mysql配置安裝詳解,需要的朋友可以參考下2016-05-05

