Web 项目 CICD 的简单实现

一 、前期准备

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 实现

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(触发器)

需要安装插件 Gitlab

image.png

点开高级 - 选择 Filter branches by name

image.png

勾选 Filter branches by name - 填写分支 - 生成 Secret token

image.png

(3)流水线配置
image.png
image.png
(4)配置凭据
image.png
(5)其它设置

1、直接在服务器上安装 jenkins

# 从 jenkins 服务器 192.168.31.112 添加的任务发布到 Nginx 服务器 192.168.31.110
# 需要把公钥拷贝到 192.168.31.110
# 如果执行 docker 操作,还需要给 jenkins 用户添加 docker 执行权限

# 在 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 用户身份执行 shell,然后执行 docker ps,可以查看 jenkins 是否有权限执行 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" 或其他用户名
# 如果不存在,需先创建用户并指定 UID:
sudo useradd -u 1000 -m jenkins
# 将 UID 1000 的用户加入 docker 组
sudo usermod -aG docker $(id -nu 1000)

# 查看 jenkins 是否有执行 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 密钥,发布到其它服务器的时候可以用 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 容器的默认网页根目录(/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 {
                // 从代码仓库拉取代码(假设代码已经提交到 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 凭证系统管理 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 管理凭据
                    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  # 设置环境变量
    restart: always  # 容器意外停止时自动重启

6、CICD

web 项目上传到 Gitlab 仓库之后,会触发 Jenkins 执行 web 项目下 Jenkinsfile 中定义的任务 ,然后浏览器访问 http://192.168.31.110:8081,即可查看页面

Jenkins 执行成功或者失败,可以在这里查看日志

image.png

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容