Docker的CICD持续集成

CICD(持续集成/持续部署)是提升研发效率、保障代码质量的核心实践。本文将基于Docker容器化技术,通过两台物理机/虚拟机搭建完整的CICD流水线,实现若依(RuoYi-Vue)前后端分离项目的自动化构建、测试与部署。全程步骤详细、解析透彻,适合DevOps入门者和企业级项目实践参考。

一、整体架构与环境规划

1.1 核心技术栈

  • 容器化:Docker 20.10.18
  • 代码管理:GitLab 10.7.5
  • 持续集成:Jenkins 2.480
  • 数据库:MySQL 8.0.39
  • 缓存:Redis 7.4.1
  • 项目:RuoYi-Vue(Spring Boot+Vue前后端分离)
  • 反向代理:Nginx 1.26.2

1.2 两台主机角色分配

主机IP 配置要求 部署服务清单 核心作用
192.168.10.13 2C 8G Jenkins、MySQL、Redis、Nginx、Spring Boot后端 构建节点+应用运行环境
192.168.10.80 1C 4G GitLab、Docker 代码仓库+版本控制中心

1.3 核心流程说明

  1. 开发者提交代码到GitLab仓库
  2. GitLab通过WebHook触发Jenkins构建
  3. Jenkins拉取代码,执行自动化构建(编译、打包)
  4. 构建产物生成Docker镜像,推送至本地镜像仓库
  5. Jenkins部署镜像到目标主机,自动启动服务
  6. 部署结果实时通知(本文以日志反馈为例)

二、前置条件:两台主机统一安装Docker

所有服务均基于Docker部署,需先在两台主机完成Docker环境初始化,步骤完全一致。

2.1 安装Docker依赖包

bash 复制代码
# 安装yum工具集和存储依赖
yum install -y yum-utils device-mapper-persistent-data lvm2

2.2 配置阿里云Docker镜像源

默认官方镜像源下载速度较慢,替换为阿里云镜像源提升效率:

bash 复制代码
yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

2.3 安装指定版本Docker并设置开机自启

bash 复制代码
# 安装Docker-CE 20.10.18(稳定版)
yum install -y docker-ce-20.10.18 docker-ce-cli-20.10.18 containerd.io

# 启动Docker服务
systemctl start docker.service

# 设置开机自动启动
systemctl enable docker.service

2.4 配置华为镜像加速器(关键优化)

进一步提升Docker镜像下载速度,配置华为云加速器:

bash 复制代码
# 创建Docker配置目录
mkdir -p /etc/docker

# 写入加速器配置
tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://0a40cefd360026b40f39c00627fa6f20.mirror.swr.myhuaweicloud.com"]
}
EOF

# 重启Docker使配置生效
systemctl daemon-reload
systemctl restart docker

2.5 验证Docker安装成功

bash 复制代码
docker --version  # 输出Docker版本信息即成功

三、主机192.168.10.80:部署GitLab代码仓库

GitLab用于存储项目源代码、管理分支和触发CICD流水线,是整个流程的代码入口。

3.1 下载GitLab镜像

bash 复制代码
docker pull beginor/gitlab-ce  # 社区版镜像,轻量且满足需求

3.2 创建数据卷挂载目录(核心步骤)

为避免容器删除导致配置、数据和日志丢失,需将GitLab关键目录挂载到宿主机:

bash 复制代码
# 创建挂载目录
mkdir -p /data/gitlab/etc /data/gitlab/log /data/gitlab/data

# 授予目录最高权限(避免容器访问权限不足)
chmod 777 /data/gitlab/etc /data/gitlab/log /data/gitlab/data

3.3 启动GitLab容器

bash 复制代码
docker run -itd \
--name=gitlab \
--restart=always \  # 容器异常自动重启
--privileged=true \  # 授予容器特权,避免文件权限问题
-p 8443:443 \  # HTTPS端口映射
-p 80:80 \     # HTTP端口映射
-p 222:22 \    # SSH端口映射(避免与宿主机22端口冲突)
-v /data/gitlab/etc:/etc/gitlab \  # 配置文件挂载
-v /data/gitlab/log:/var/log/gitlab \  # 日志挂载
-v /data/gitlab/data:/var/opt/gitlab \  # 数据挂载
beginor/gitlab-ce

3.4 配置GitLab访问地址与SSH端口

容器启动后,需修改配置文件指定访问地址,否则无法正常访问:

bash 复制代码
# 1. 修改外部访问地址(GitLab Web界面地址)
sed -i "/external_url 'GENERATED_EXTERNAL_URL'/a external_url\t'http://192.168.10.80' " /data/gitlab/etc/gitlab.rb

# 2. 修改SSH连接主机(与Web地址一致)
sed -i "/gitlab_ssh_host/a gitlab_rails['gitlab_ssh_host']= '192.168.10.80' " /data/gitlab/etc/gitlab.rb

# 3. 修改SSH连接端口(与容器映射的222端口一致)
sed -i "/gitlab_shell_ssh_port/a gitlab_rails['gitlab_shell_ssh_port'] = 222" /data/gitlab/etc/gitlab.rb

# 重启GitLab使配置生效
docker restart gitlab

3.5 初始化GitLab管理员账号

  1. 访问GitLab Web界面:浏览器输入 http://192.168.10.80(首次启动需等待3-5分钟)
  2. 初始化root密码:首次登录会提示设置密码(本文设置为 1qaz@WSX
  3. 登录:使用用户名 root + 新设密码登录

3.6 配置SSH密钥(免密拉取代码)

为了让Jenkins和本地开发机免密拉取GitLab代码,需配置SSH密钥:

bash 复制代码
# 在GitLab宿主机或开发机生成SSH密钥(以GitLab宿主机为例)
ssh-keygen  # 一路回车,无需设置密码

# 查看公钥内容
cat ~/.ssh/id_rsa.pub

将输出的公钥复制到GitLab Web界面:

  • 登录GitLab → 右上角头像 → Settings → SSH Keys
  • 粘贴公钥,设置标题(如"Jenkins访问密钥"),点击Add Key

3.7 上传若依项目到GitLab

3.7.1 下载若依源码
bash 复制代码
# 本地开发机(Windows需安装Git Bash,Linux需安装git)
git clone https://gitee.com/y_project/RuoYi-Vue.git
3.7.2 在GitLab创建项目
  1. 登录GitLab → New Project → 项目名称 ruoyi-server(后端)、ruoyi-ui(前端)
  2. 可见等级选择"私有"(仅团队成员可访问)
  3. 点击"Create project"
3.7.3 推送代码到GitLab
bash 复制代码
# 进入若依项目根目录
cd RuoYi-Vue

# 初始化本地Git仓库
git init

# 关联GitLab后端项目远程仓库
git remote add origin ssh://git@192.168.10.80:222/root/ruoyi-server.git

如果已经存在则:
git remote set-url origin ssh://git@192.168.10.80:222/root/ruoyi-server.git

# 添加所有文件到暂存区
git add .

# 提交代码
git commit -m "Initial commit: 若依后端项目初始化"

# 推送到GitLab master分支
git push -u origin master


## 四、主机192.168.10.13:部署Jenkins持续集成工具
Jenkins是CICD流水线的核心,负责拉取代码、构建打包、部署发布等自动化操作。由于若依项目需要JDK、Maven、Node.js环境,需对Jenkins镜像二次打包。

### 4.1 准备Jenkins二次打包资源
#### 4.1.1 创建工作目录
```bash
mkdir -p /data/jenkins
cd /data/jenkins
4.1.2 下载依赖包(JDK、Maven、Node.js)

将以下包上传到 /data/jenkins 目录(可通过wget或本地传输):

  • JDK:jdk-8u421-linux-x64.tar.gz(若依后端需JDK8)
  • Maven:apache-maven-3.9.9-bin.tar.gz(构建Java项目)
  • Node.js:node-v11.0.0-linux-x64.tar.gz(构建Vue前端)
4.1.3 配置Maven settings.xml

3.8.x以上Maven默认不支持HTTP仓库,需自定义配置文件:

bash 复制代码
tee settings.xml <<-'EOF'
<?xml version="1.0" encoding="UTF-8"?>
<settings xmlns="http://maven.apache.org/SETTINGS/1.2.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.2.0 https://maven.apache.org/xsd/settings-1.2.0.xsd">
</settings>
EOF

4.2 编写Dockerfile二次打包Jenkins

dockerfile 复制代码
# 基础镜像:Jenkins 2.480 + JDK21(后续手动配置JDK8)
FROM jenkins/jenkins:2.480-jdk21

# 暴露Jenkins默认端口
EXPOSE 8080

# 复制并自动解压JDK、Maven、Node.js到容器
ADD apache-maven-3.9.9-bin.tar.gz /usr/local
ADD jdk-8u421-linux-x64.tar.gz /usr/local
ADD node-v11.0.0-linux-x64.tar.gz /usr/local

# 覆盖Maven配置文件
ADD settings.xml /usr/local/apache-maven-3.9.9/conf/

# 配置环境变量(时区、Maven、Node.js)
ENV TZ=Asia/Shanghai
ENV M2_HOME=/usr/local/apache-maven-3.9.9
ENV NODE_HOME=/usr/local/node-v11.0.0-linux-x64
ENV PATH=$M2_HOME/bin:$NODE_HOME/bin:$PATH

4.3 构建自定义Jenkins镜像

bash 复制代码
# 创建Jenkins数据目录并授权
mkdir jenkins_home
chmod +777 jenkins_home

# 构建镜像(镜像名jenkins)
docker build -t jenkins .

# 授予Docker sock权限(Jenkins需调用宿主机Docker命令)
chmod +777 /var/run/docker.sock

4.4 启动Jenkins容器

bash 复制代码
docker run -d \
--name=jenkins \
-p 8080:8080 \  # Jenkins Web端口
-v /data/jenkins/jenkins_home:/var/jenkins_home \  # 数据挂载
-v /etc/localtime:/etc/localtime \  # 同步宿主机时区
-v /run/docker.sock:/run/docker.sock \  # 挂载Docker sock
-v /usr/bin/docker:/usr/bin/docker \  # 挂载Docker命令
jenkins

4.5 初始化Jenkins

4.5.1 获取初始管理员密码
bash 复制代码
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword

输出类似 a07829a8375a47f7b6e516ca2f0bad1f 的密码,用于首次登录。

4.5.2 登录并安装插件
  1. 访问Jenkins Web界面:http://192.168.10.13:8080
  2. 输入初始密码 → 选择"安装推荐插件"(包含Git、Pipeline等核心插件)
  3. 安装完成后,创建管理员账号(本文设置用户名 admin,密码 123456
  4. 配置Jenkins URL:默认 http://192.168.10.13:8080,直接保存
4.5.3 配置JDK环境(关键步骤)

Jenkins二次打包时未配置JDK环境变量,需手动配置:

  1. 进入Jenkins → 系统管理 → 全局工具配置 → JDK
  2. 点击"新增JDK",取消"自动安装"
  3. 名称填写 jdk8(后续Jenkinsfile需引用)
  4. JAVA_HOME填写 /usr/local/jdk1.8.0_421(容器内JDK实际路径)
  5. 点击"保存"
4.5.4 安装GitLab插件

为了让Jenkins接收GitLab的WebHook触发,需安装GitLab插件:

  1. 系统管理 → 插件管理 → 可选插件
  2. 搜索"GitLab" → 勾选安装 → 重启Jenkins

五、主机192.168.10.13:部署MySQL与Redis

若依项目依赖MySQL数据库和Redis缓存,需在应用主机部署这两个服务。

5.1 部署MySQL 8.0.39

bash 复制代码
docker run -d \
--name=mysql \
-p 3306:3306 \  # 数据库端口映射
-e MYSQL_ROOT_PASSWORD=123456 \  #  root密码
--restart=always \
mysql:8.0.39
5.1.1 创建若依数据库并导入数据
bash 复制代码
# 进入MySQL容器
docker exec -it mysql bash

# 登录MySQL
mysql -u root -p123456

# 创建数据库(若依默认数据库名ry-vue)
create database ry-vue;

# 使用数据库
use ry-vue;

# 导入若依SQL文件(需先将ry_20250522.sql和quartz.sql上传到容器/opt目录)
source /opt/ry_20250522.sql;
source /opt/quartz.sql;

# 验证导入成功(查看表结构)
show tables;

5.2 部署Redis 7.4.1

bash 复制代码
docker run -d \
--name=redis \
-p 6379:6379 \  # 缓存端口映射
--restart=always \
redis:7.4.1

5.3 验证服务可用性

bash 复制代码
# 查看容器运行状态(均为Up状态即正常)
docker ps | grep -E "mysql|redis"

六、Jenkins实现CICD自动化部署(前后端)

6.1 后端部署(ruoyi-server)

6.1.1 修改若依后端配置文件

需修改数据库和Redis连接信息,指向主机192.168.10.13的服务:

  1. 本地开发机打开 ruoyi-admin/src/main/resources/application-druid.yml

  2. 修改MySQL配置:

    yaml 复制代码
    spring:
      datasource:
        url: jdbc:mysql://192.168.10.13:3306/ry-vue?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
        username: root
        password: 123456
  3. 修改Redis配置:

    yaml 复制代码
    spring:
      redis:
        host: 192.168.10.13
        port: 6379
        password:  # 默认为空,若有密码需填写
  4. 提交配置修改到GitLab:

    bash 复制代码
    git add .
    git commit -m "修改数据库和Redis连接配置"
    git push origin master
6.1.2 新增后端构建部署文件

在若依项目根目录新增3个文件,用于Jenkins构建和Docker部署:

1. Dockerfile(构建后端镜像)
dockerfile 复制代码
# 基础镜像:JDK8(若依后端依赖JDK8)
FROM openjdk:8u342

# 配置时区
ENV TZ=Asia/Shanghai

# 复制打包后的jar包到容器
ADD ruoyi-admin/target/ruoyi-admin.jar app.jar

# 容器启动命令
ENTRYPOINT ["java", "-jar", "app.jar"]
2. .dockerignore(优化构建速度)

屏蔽不必要的文件,减少镜像体积和构建时间:

复制代码
.git
ruoyi-admin/src
ruoyi-admin/target/classes
ruoyi-admin/target/generated-sources
ruoyi-common
ruoyi-framework
ruoyi-generator
ruoyi-quartz
ruoyi-system
ruoyi-ui
sql
3. Jenkinsfile(流水线脚本)

定义CICD构建和部署流程:

groovy 复制代码
pipeline {
    agent any  // 任意Jenkins节点执行
    tools {
        jdk 'jdk8'  // 引用之前配置的JDK环境
    }
    environment {
        APP_NAME = 'ruoyi-server'  // 项目名称
        APP_PORT = 9800  // 后端服务端口
    }
    stages {
        // 构建阶段:编译打包
        stage('build') {
            steps {
                script {
                    sh 'mvn clean package -DskipTests=true'  // Maven打包,跳过测试
                }
            }
        }
        // 部署阶段:构建镜像并启动容器
        stage('deploy') {
            steps {
                script {
                    // 停止并删除旧容器和镜像
                    sh 'docker stop $APP_NAME || true'
                    sh 'docker rm $APP_NAME || true'
                    sh 'docker rmi $APP_NAME || true'
                    // 构建新镜像
                    sh 'docker build -t $APP_NAME .'
                    // 启动新容器
                    sh "docker run -d --name $APP_NAME -p 0.0.0.0:$APP_PORT:$APP_PORT --restart=always $APP_NAME --server.port=$APP_PORT"
                }
            }
        }
    }
}
6.1.3 提交构建文件到GitLab
bash 复制代码
git add .dockerignore Dockerfile Jenkinsfile
git commit -m "新增Jenkins构建和Docker部署文件"
git push origin master
6.1.4 Jenkins创建后端流水线任务
  1. Jenkins → 新建Item → 任务名称 ruoyi-server → 选择"流水线" → 确定
  2. 配置流水线:
    • 选择"Pipeline script from SCM"(从GitLab拉取Jenkinsfile)
    • SCM选择"Git"
    • 仓库URL:ssh://git@192.168.10.80:222/root/ruoyi-server.git(GitLab项目SSH地址)
    • Credentials:添加Jenkins的SSH密钥(与GitLab配置的一致)
    • 分支:*/master
    • 脚本路径:Jenkinsfile(项目根目录下的Jenkinsfile路径)
  3. 配置GitLab WebHook触发:
    • 勾选"Build when a change is pushed to GitLab"
    • 点击"Generate"生成Secret token(后续GitLab配置需用到)
    • 保存配置
6.1.5 GitLab配置WebHook
  1. 登录GitLab → 进入ruoyi-server项目 → Settings → Integrations
  2. URL填写:http://192.168.10.13:8080/project/ruoyi-server(Jenkins项目地址)
  3. Secret token填写Jenkins生成的令牌
  4. 触发器选择"Push events"(代码推送时触发构建)
  5. 点击"Add webhook" → 测试连接(显示200即成功)

6.2 前端部署(ruoyi-ui)

6.2.1 新增前端构建部署文件

进入 ruoyi-ui 目录,新增4个文件:

1. nginx.conf(前端反向代理配置)
nginx 复制代码
server {
    listen 9801;  // 前端访问端口
    charset utf-8;

    # 前端静态资源访问
    location / {
        root /usr/share/nginx/html;
        try_files $uri $uri/ /index.html;  // 解决Vue路由刷新404问题
    }

    # 后端接口代理(转发/prod-api请求到后端服务)
    location /prod-api {
        rewrite ^/prod-api/(.*)$ /$1 break;
        proxy_pass http://192.168.10.13:9800;  // 后端服务地址
    }
}
2. Dockerfile(构建前端镜像)
dockerfile 复制代码
# 基础镜像:Nginx 1.26.2
FROM nginx:1.26.2

# 解决中文乱码
ENV LC_ALL=C.UTF-8

# 删除默认Nginx配置
RUN rm -rf /etc/nginx/conf.d/default.conf

# 复制自定义Nginx配置
ADD nginx.conf /etc/nginx/conf.d

# 复制前端打包后的dist目录到Nginx静态资源目录
COPY dist/ /usr/share/nginx/html/
3. .dockerignore(优化构建)
复制代码
node_modules
src
4. Jenkinsfile(前端流水线脚本)
groovy 复制代码
pipeline {
    agent any
    environment {
        APP_NAME = 'ruoyi-ui'  // 前端项目名称
        APP_PORT = 9801  // 前端访问端口
    }
    stages {
        // 构建阶段:安装依赖并打包
        stage('build') {
            steps {
                script {
                    sh 'npm install'  // 安装Node依赖
                    sh 'npm run build:prod'  // 打包生产环境版本
                }
            }
        }
        // 部署阶段:构建镜像并启动容器
        stage('deploy') {
            steps {
                script {
                    sh 'docker stop $APP_NAME || true'
                    sh 'docker rm $APP_NAME || true'
                    sh 'docker rmi $APP_NAME || true'
                    sh 'docker build -t $APP_NAME .'
                    sh "docker run -d --name $APP_NAME -p 0.0.0.0:$APP_PORT:$APP_PORT --restart=always $APP_NAME"
                }
            }
        }
    }
}
6.2.2 提交文件到GitLab并配置Jenkins
  1. 提交前端构建文件到GitLab(步骤同后端)
  2. Jenkins新建 ruoyi-ui 流水线任务(配置同后端,仓库URL改为前端项目地址)
  3. GitLab配置前端项目WebHook(步骤同后端)

七、测试CICD流水线

7.1 手动触发构建

  1. 进入Jenkins → 选择 ruoyi-server → 点击"立即构建"
  2. 查看构建日志:点击构建记录 → Console Output,显示"Finished: SUCCESS"即构建成功
  3. 同理触发 ruoyi-ui 构建

7.2 自动触发构建(验证WebHook)

  1. 本地开发机修改若依项目代码(如修改前端页面标题)

  2. 提交并推送代码到GitLab:

    bash 复制代码
    git add .
    git commit -m "测试WebHook自动构建"
    git push origin master
  3. 观察Jenkins:自动触发对应项目构建,无需手动操作

7.3 访问若依项目

  • 前端访问:http://192.168.10.13:9801(输入用户名 admin,密码 admin123
  • 后端接口:http://192.168.10.13:9800/prod-api/system/index(返回JSON即正常)

八、常见问题排查

  1. Jenkins无法拉取GitLab代码 :检查SSH密钥是否配置正确,Jenkins容器内是否生成 known_hosts 文件(可通过 ssh-keyscan -p 222 192.168.10.80 >> ~/.ssh/known_hosts 生成)
  2. Maven打包失败:检查Maven配置文件是否正确,依赖是否能正常下载
  3. Docker构建镜像失败:检查Dockerfile路径是否正确,.dockerignore文件是否屏蔽必要文件
  4. 前端访问后端接口404 :检查Nginx配置中的 proxy_pass 是否指向正确的后端地址

九、总结

本文基于两台主机搭建了完整的Docker+CICD流水线,实现了若依项目的自动化构建、测试和部署。核心优势在于:

  1. 容器化部署:所有服务隔离运行,环境一致性强,迁移方便
  2. 自动化流水线:代码提交后自动触发构建部署,减少人工操作
  3. 架构清晰:两台主机分工明确,兼顾性能和稳定性
相关推荐
oMcLin1 天前
在RHEL 8系统上如何实现基于Docker的微服务架构,并进行自动化部署?
docker·微服务·架构
人工小情绪1 天前
docker常用命令
docker·容器
叫致寒吧1 天前
CICD持续集成Ruo-Yi项目
ci/cd
胖好白1 天前
【咸鱼RK3399】打造NAS(Debian+Docker+CasaOS)
linux·docker·debian
少云清1 天前
【接口测试】2_持续集成 _Git与Gitee
git·ci/cd·gitee
开开心心就好1 天前
右键菜单管理工具,添加程序自定义名称位置
linux·运维·服务器·ci/cd·docker·pdf·1024程序员节
Red丶哞1 天前
Docker 部署 File Browser 文件管理系统
运维·docker·容器
Red丶哞1 天前
使用Docker部署RustFS分布式对象存储服务
linux·docker·云原生
l1t1 天前
使用docker安装sql server linux版
linux·sql·docker·容器·sqlserver