Web 項目 CICD 的簡單實現(xiàn)

一 、前期準備

1、安裝 Gitlab
點擊查看安裝教程
2、安裝 Jenkins
點擊查看安裝教程
3、部署 Docker Harbor
點擊查看安裝教程
4、
程序 ip
Docker + Nginx 192.168.31.110
Gitlab 192.168.31.111
Jenkins 192.168.31.112
DockerHarbor 192.168.31.113

二、CICD 實現(xiàn)

1、配置 Gitlab

可以切換到中文:點擊頭像 - Preferences - Localization - Language - Save changes

(1) 新建 git 倉庫,地址: http://192.168.31.111/root/helloworld.git
(2)Admin - Setting - Network
image.png
(3)Outbound requests - 勾選 Allow requests to the local network from webhooks and integrations
image.png
(4)選擇項目 - Settings - Webhooks
image.png
(5)Add new webhook - URL 和 Secret token 都從 Jenkins Triggers 中獲取
image.png
{E1458EE8-9E84-4015-B0AD-8FADE422DC60}.png

2、配置 Jenkins

(1) 新建任務 - 輸入任務名稱 - 選擇流水線 - 確定
image.png
(2)點擊剛剛新建的任務 - 配置 - Triggers(觸發(fā)器)

需要安裝插件 Gitlab

image.png

點開高級 - 選擇 Filter branches by name

image.png

勾選 Filter branches by name - 填寫分支 - 生成 Secret token

image.png

(3)流水線配置
image.png
image.png
(4)配置憑據(jù)
image.png
(5)其它設置

1、直接在服務器上安裝 jenkins

# 從 jenkins 服務器 192.168.31.112 添加的任務發(fā)布到 Nginx 服務器 192.168.31.110
# 需要把公鑰拷貝到 192.168.31.110
# 如果執(zhí)行 docker 操作,還需要給 jenkins 用戶添加 docker 執(zhí)行權限

# 在 Jenkins 服務器上以 jenkins 用戶生成密鑰:
sudo -u jenkins ssh-keygen -t ed25519 -f /var/lib/jenkins/.ssh/id_ed25519
# 查看公鑰內容
sudo -u jenkins cat /var/lib/jenkins/.ssh/id_ed25519.pub
# 將公鑰拷貝到目標服務器
sudo -u jenkins ssh-copy-id -i /var/lib/jenkins/.ssh/id_ed25519.pub root@192.168.31.110

# 以 jenkins 用戶身份執(zhí)行 shell,然后執(zhí)行 docker ps,可以查看 jenkins 是否有權限執(zhí)行 docker ps
sudo -u jenkins bash
# 檢查 Jenkins 用戶所屬組
id jenkins
# 將 Jenkins 用戶添加到 docker 用戶組
sudo usermod -aG docker jenkins
# 重啟 Jenkins 服務
sudo systemctl restart jenkins
# 重啟  Docker 服務:
sudo systemctl restart docker

2、通過 docker 安裝 jenkins

# 獲取宿主機的 docker 組 GID
getent group docker | cut -d: -f3

# 在宿主機運行以下命令,確認 UID 1000 的用戶是否存在:
id -nu 1000  # 應返回 "jenkins" 或其他用戶名
# 如果不存在,需先創(chuàng)建用戶并指定 UID:
sudo useradd -u 1000 -m jenkins
# 將 UID 1000 的用戶加入 docker 組
sudo usermod -aG docker $(id -nu 1000)

# 查看 jenkins 是否有執(zhí)行 docker ps 的權限
[root@jenkins ~]# docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS              PORTS                                                                                          NAMES
9acb30a66cc7   jenkins/jenkins:lts   "/usr/bin/tini -- /u…"   About a minute ago   Up About a minute   0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp, 0.0.0.0:50000->50000/tcp, [::]:50000->50000/tcp   jenkins
[root@jenkins ~]# docker exec -it 9acb30a66cc7 bash
jenkins@9acb30a66cc7:/$ docker ps
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                                                                                          NAMES
9acb30a66cc7   jenkins/jenkins:lts   "/usr/bin/tini -- /u…"   2 minutes ago   Up 2 minutes   0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp, 0.0.0.0:50000->50000/tcp, [::]:50000->50000/tcp   jenkins

# 1. 在 Jenkins 容器內生成 SSH 密鑰,發(fā)布到其它服務器的時候可以用 ssh 連接
# 進入 Jenkins 容器
docker exec -it jenkins bash
# 生成 SSH 密鑰對
mkdir -p ~/.ssh
chmod 700 ~/.ssh
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -N ""  # 無密碼
# 2. 將公鑰復制到目標服務器
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@target-server

3、配置 DockerHarbor,新建項目

image.png

4、web 項目內容

web 項目一共三個文件,所有內容如下

(1)index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>WebView Test</title>
</head>
<body>
    <h1>Hello World!</h1>
</body>
</html>
(2)Dockerfile 文件
# 使用官方的 Nginx 鏡像作為基礎鏡像
FROM nginx:latest

# 將當前目錄下的所有文件復制到 Nginx 容器的默認網(wǎng)頁根目錄(/usr/share/nginx/html)
COPY . /usr/share/nginx/html

# 暴露 Nginx 服務的默認端口 80
EXPOSE 80
(3)Jenkinsfile 文件
pipeline {
    agent any

    environment {
        // 定義 Docker 相關變量
        DOCKER_REGISTRY = "cicd.ddzhixu.com:443"
        IMAGE_NAME = "helloworld/helloworld"
        TIMESTAMP = "${new Date().format('yyyyMMdd_HHmmss', TimeZone.getTimeZone('Asia/Shanghai'))}" // 默認 UTC 時間,更改為 CST 時間為:年月日-時分秒
        DEPLOY_SERVER = "root@192.168.31.110" // 目標服務器地址
        DEPLOY_DIR = "/root"      // 目標服務器上的部署目錄
    }

    stages {
        stage('Checkout') {
            steps {
                // 從代碼倉庫拉取代碼(假設代碼已經(jīng)提交到 Git 倉庫)
                git credentialsId: 'fa1644ee-7237-4388-8c95-11764b542803', url: 'http://192.168.31.111/root/helloworld.git', branch: 'main'
            }
        }

        stage('Build Docker Image') {
            steps {
                // 構建 Docker 鏡像,鏡像標簽格式為:倉庫地址/鏡像名:時間戳
                sh """
                    docker build -t ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP} .
                """
            }
        }
        stage('Login to Docker Harbor') {
            steps {
                // 使用 Jenkins 憑證系統(tǒng)管理 Docker Harbor 的用戶名和密碼
                withCredentials([usernamePassword(credentialsId: '64cad706-930f-457b-9756-f468ea96c570', usernameVariable: 'DOCKER_USER', passwordVariable: 'DOCKER_PASSWORD')]) {
                    sh '''
                        echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USER}" --password-stdin cicd.ddzhixu.com:443
                    '''
                }
            }
        }
        stage('Push Docker Image') {
            steps {
                // 將構建好的 Docker 鏡像推送到 Docker Harbor
                sh """
                    docker push ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP}
                """
            }
        }
        stage('Deploy to Server') {
            steps {
                script {
                    def IMAGE_TAG = "${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP}"
                    
                    // 使用 sshagent 管理憑據(jù)
                    sshagent(['ac999135-8dd0-434f-ade1-773921ac78d4']) {
                        // 更新目標服務器上的 helloworld.yaml 文件
                        sh """
                            ssh -v ${DEPLOY_SERVER} "
                                cd ${DEPLOY_DIR} &&
                                sed -i 's|image:.*|image: ${IMAGE_TAG}|' helloworld.yaml
                            "
                        """

                        // 在目標服務器上拉取最新鏡像并啟動服務
                        sh """
                            ssh ${DEPLOY_SERVER} "
                                cd ${DEPLOY_DIR} &&
                                ls -l && # 打印當前目錄文件列表,用于調試
                                docker compose -f helloworld.yaml pull &&
                                docker compose -f helloworld.yaml up -d
                            "
                        """
                    }
                }
            }
        }
    }

    post {
        success {
            echo "Pipeline completed successfully with image tag: ${DOCKER_REGISTRY}/${IMAGE_NAME}:${TIMESTAMP}"
        }
        failure {
            echo "Pipeline failed"
        }
    }
}

5、服務器 192.168.31.110

(1)/root 目錄下添加 helloworld.yaml 文件,內容如下
version: '3.8'  # 使用 Docker Compose 的版本

services:
  helloworld:  # 服務名稱
    image: cicd.harbor.com:443/helloworld/helloworld:20250419_122044
    container_name: helloworld  # 容器名稱
    ports:
      - "8081:80"  # 將容器的 80 端口映射到主機的 8081 端口
    environment:
      - NODE_ENV=production  # 設置環(huán)境變量
    restart: always  # 容器意外停止時自動重啟

6、CICD

web 項目上傳到 Gitlab 倉庫之后,會觸發(fā) Jenkins 執(zhí)行 web 項目下 Jenkinsfile 中定義的任務 ,然后瀏覽器訪問 http://192.168.31.110:8081,即可查看頁面

Jenkins 執(zhí)行成功或者失敗,可以在這里查看日志

image.png

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容