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. 架构清晰:两台主机分工明确,兼顾性能和稳定性
相关推荐
仙柒41513 小时前
Docker 网络
运维·docker·容器
木雷坞13 小时前
vLLM 服务启动慢排查:NAS 模型目录、Docker 镜像和 GPU Runtime
docker·容器·vllm
撸码老九13 小时前
GitHub Actions + 阿里云 ACR + Docker 自动化 CI/CD 部署到云服务器
ci/cd
红球yyds13 小时前
CICD 持续集成与持续交付
ci/cd
古怪今人13 小时前
WSL和Hyper-V Ubuntu安装docker Docker安装Reids、MySQL、PostgreSQL和RabbitMQ
运维·docker·容器
周易宅13 小时前
Docker MySQL 8.0.45 性能优化配置文档
mysql·docker·性能优化
ん贤13 小时前
Kubernetes 核心资源对象与应用编排基础
云原生·容器·kubernetes
LZZ and MYY13 小时前
将Virtual PLCnext 部署在PVE的LXC容器
云原生·容器·kubernetes
仙柒4151 天前
Docker存储原理
运维·docker·容器
快乐的哈士奇1 天前
LangFuse 自托管实战:选型理由、Docker 部署与常用配置全解析
运维·人工智能·docker·容器