前言
本文详细介绍了如何通过Docker容器化技术构建自定义Jenkins镜像,解决传统部署方式中的环境一致性问题。我们将从镜像构建原理出发,逐步实现包含Node.js、JDK、Maven等工具链的一体化CI/CD环境,并探讨镜像优化、数据持久化和跨环境迁移的最佳实践。
创建镜像的方式
在DevOps实践中,Jenkins作为持续集成的核心工具,其环境一致性直接影响构建稳定性。传统部署方式存在以下痛点:
- 依赖冲突:不同项目对JDK、Maven版本要求各异
- 配置漂移:手动修改导致环境逐渐偏离初始状态
- 迁移复杂:服务器更换需重新配置完整环境
通过Docker构建自定义Jenkins镜像,可实现:
- 环境固化:一次构建,多环境一致运行
- 工具集成:预置项目所需的全部依赖工具
- 快速复制:通过镜像分发实现秒级环境部署
常用的Docker镜像的创建方式主要有以下三种:
- 基于容器提交创建(docker commit)
步骤:
- 启动基础容器并修改
bash
$ docker run -it --name temp-container ubuntu:22.04 /bin/bash
# 在容器内执行操作(如安装软件)
$ apt-get update && apt-get install -y nginx
exit
- 提交为新镜像
bash
$ docker commit -m "安装nginx" -a "作者" temp-container my-nginx:v1
这种方式主要通过将运行中的容器状态保存为新镜像的方式创建镜像。通过这种方式优点就是可以快速的创建一个镜像,缺点也很明显,就是难以追踪变更记录,不便于版本管理。
- 基于 Dockerfile 构建
基础Dockerfile示例:
bash
FROM ubuntu:22.04 # 基础镜像
LABEL maintainer="user@example.com"
RUN apt-get update && apt-get install -y nginx # 安装软件
COPY index.html /usr/share/nginx/html/ # 复制文件
EXPOSE 80 # 声明端口
CMD ["nginx", "-g", "daemon off;"] # 启动命令
构建命令:
bash
$ docker build -t my-nginx:v2 . # .表示当前目录Dockerfile
这种方式是通过文本指令(Dockerfile)自动化构建过程。这种方式的优点是方便版本管理,镜像分层构建,优化缓存,适合CI/CD流水线集成。
- 基于本地模板导入(docker import)
步骤:
- 获取模版文件
bash
$ wget http://download.openvz.org/template/precreated/ubuntu-22.04-x86_64.tar.gz
- 导入为镜像
bash
$ docker import ubuntu-22.04-x86_64.tar.gz my-ubuntu:v1
这种方式通过导入 tar 格式的文件系统快照快速生成镜像,优点是导入速度快、兼容性强,但缺乏 Docker 元数据和分层优化,适用于系统迁移和离线部署场景。
构建自定义容器镜像
通过对比以上三种创建镜像的方式的优缺点,我选择了通过 Dockerfile 的方式来构建自定义容器镜像。为了简化构建的复杂度,我选择了jenkins官方基础镜像作为基础,构建属于自己的自定义容器镜像。
Jenkins 官方基础镜像为精简体积,仅包含 Jenkins 本身及运行所需的核心应用程序。而构建前端程序依赖的 Node.js、pnpm,后端 Java 编译所需的 JDK 和 Maven,则需要自行安装。此外,还需配置一些工具应用(如 vim)和环境设置,例如替换为阿里云软件源以加速国内下载,配置 npm 淘宝镜像源以提升前端依赖安装速度等。
按照上述思路,我们开始构建名为 my-jenkins 的自定义容器镜像。
首先创建 jenkins-workspace 目录,在该目录下创建 Dockerfile 文件,并提前下载好 Jenkins 打包 Java 程序所需的 jdk1.8.0_202 和 apache-maven-3.9.9。
bash
.
├── apache-maven-3.9.9
├── Dockerfile
└── jdk1.8.0_202
接下来编写 Dockerfile 文件:
bash
FROM jenkins/jenkins # 指定基础镜像为 Jenkins 官方镜像,提供 Jenkins 运行环境
USER root # 切换至 root 用户,获取管理员权限以执行系统配置操作
RUN sed -i "s|http://deb.debian.org/debian|https://mirrors.aliyun.com/debian|g" /etc/apt/sources.list.d/debian.sources && \
sed -i "s|http://security.debian.org/debian-security|https://mirrors.aliyun.com/debian-security|g" /etc/apt/sources.list.d/debian.sources && \
apt update && \ # 替换 Debian 软件源为阿里云镜像,加速国内环境下的包下载,并更新软件包索引
# 安装Node.js 18.x和vim编辑器
curl -fsSL https://deb.nodesource.com/setup_18.x | bash - && \
apt install -y nodejs vim && \
# 配置npm淘宝镜像源
npm config set registry https://registry.npmmirror.com/ && \
# 全局安装pnpm
npm install -g pnpm && \
# 清理apt缓存,减小镜像体积
apt clean && \
rm -rf /var/lib/apt/lists/*
COPY jdk1.8.0_202 /usr/jdk1.8.0_202/ # 复制本地 JDK 1.8 到镜像,提供 Java 编译环境
COPY apache-maven-3.9.9 /usr/apache-maven-3.9.9/ # 复制本地 Maven 3.9.9 到镜像,提供 Java 项目构建工具
USER jenkins # 切换回 jenkins 用户,遵循最小权限原则,提高容器安全性
Dockerfile常用命令:
命令 | 功能描述 |
---|---|
FROM |
指定基础镜像(如jenkins/jenkins ) |
USER |
切换执行用户(root /jenkins ) |
RUN |
执行 Shell 命令(软件源替换 / 依赖安装 / 缓存清理) |
COPY |
复制本地文件到镜像(JDK/Maven 目录) |
ENV |
设置环境变量 |
EXPOSE |
声明容器端口 |
WORKDIR |
设置工作目录 |
CMD |
指定容器启动命令 |
Dockerfile 编写完成后,执行如下命令生成镜像。其中-f
参数指定 Dockerfile 文件路径,-t
参数用于设置镜像名称和标签(name:tag
)。
bash
$ docker build -f Dockerfile -t my-jenkins:1.1 .
当终端显示如下信息时,表明 my-jenkins 镜像制作成功。

也可以通过docker images命令查看本地镜像。
perl
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
my-jenkins 1.1 0188e3838f24 2 minutes ago 1.45GB
运行容器
在 Jenkins 容器内部安装软件时,软件会自动安装到/var/jenkins_home/tools/
目录。为避免容器启动时数据丢失,需在宿主机中创建数据目录,将 Jenkins 的数据目录挂载到宿主机目录。在 jenkins-workspace 目录下创建 jenkins-data 目录,并设置权限(容器中 jenkins 用户的 uid 为 1000)。
bash
$ mkdir -p ./jenkins-data
$ chown -R 1000:1000 ./jenkins-data # 设置权限
启动 Jenkins 容器时,通过-v ./jenkins-data:/var/jenkins_home
参数,将宿主机的jenkins-data
目录映射到容器的/var/jenkins_home
目录。
bash
docker run --privileged -d -p 8080:8080 -p 50000:50000 \
-v ./jenkins-data:/var/jenkins_home \
-v /etc/localtime:/etc/localtime \
-v /usr/bin/docker:/usr/bin/docker \
-v /var/run/docker.sock://var/run/docker.sock \
-u root \
--restart=always \
--name=my-jenkins my-jenkins:1.1
执行成功后,通过 docker ps 命令查看容器运行状态:
bash
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a53b18d880c6 sac-jenkins:1.1 "/usr/bin/tini -- /u..." 6 seconds ago Up 4 seconds 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp, 0.0.0.0:50000->50000/tcp, [::]:50000->50000/tcp my-jenkins
系统安装成功后,通过浏览器访问 http:/ip:port/进入初始页。

根据提示,密码存储在 /var/jenkins_home/secrets/initialAdminPassword 文件中。登录容器后,找到密码并输入,点击继续。
bash
$ docker exec -it a53b18d880c6 /bin/bash # 登录容器
创建第一个管理员用户:

jenkins配置
至此,整个 Jenkins 已可正常运行。前端程序打包所需的 Nodejs、Pnpm 及 Npm 淘宝镜像地址配置,在 my-jenkins 镜像中均已预置,因此前端构建不会出现问题。但对于 Java 程序打包,还需配置 Maven 和 Jdk。
这些配置可在 Jenkins 的工具配置管理界面统一完成。

首先介绍 Maven 的配置方法。
Maven 运行依赖 setting.xml 配置文件,下载后需修改其中的 Maven 镜像地址以提升依赖下载速度,有时还需根据需要调整依赖下载路径。
我们可在全局工具配置中指定 setting.xml 的读取路径。

此处将 Maven 路径配置为 /var/jenkins_home/maven/repository/setting.xml。如前所述,容器路径 /var/jenkins_home 会映射到宿主机的 jenkins-data 目录,因此需在宿主机的 /jenkins-data/maven/repository/ 目录下配置好 setting.xml 文件。这样做的好处是便于随时修改 Maven 配置文件,而非将其固化在容器中。
以下是 setting.xml 的配置内容:
xml
<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">
<localRepository>/var/jenkins_home/maven/mavenRepo</localRepository>
<mirrors>
<mirror>
<id>nexus-aliyun</id>
<mirrorOf>central</mirrorOf>
<name>Nexus aliyun</name>
<url>http://maven.aliyun.com/nexus/content/groups/public</ur1>
</mirror>
</mirrors>
</settings>
localRepository 配置项指定将 Maven 依赖下载至 /var/jenkins_home/maven/mavenRepo 路径,该路径会映射到宿主机的 /jenkins-data/maven/mavenRepo 目录。此举可实现依赖包的复用,避免容器重启时重复下载。
接下来需指定 Maven 的运行目录:

其次是 Jdk 的配置。Jenkins 自身运行依赖特定版本的 Jdk,该版本通常与打包 Java 工程所用的 Jdk 版本不同。因此,为确保 Java 程序顺利打包,需在 Jenkins 中设置打包程序使用的 Jdk 安装路径。

镜像的打包和加载
经过上述步骤创建的镜像,我们希望能供更多人使用。通常可将其发布到 Docker Hub 或其他镜像仓库供下载,对于私密镜像,则可打包为压缩包进行存档和分发。
通过 docker save 命令将镜像导出为 my-jenkins.tar.gz 文件:
bash
$ docker save -o my-jenkins.tar my-jenkins:1.1
使用时,通过 docker load 命令导入镜像,结合 jenkins-data 数据目录,即可快速搭建 Jenkins 运行环境。
bash
$ docker load -i my-jenkins.tar.gz
总结
通过 Docker 构建自定义 Jenkins 镜像,我们实现了 CI/CD 环境的标准化与可移植性,构建了包含完整工具链的一体化镜像、实现了数据持久化与环境快速复制、掌握了镜像优化与跨环境迁移的技巧。
更多精彩文章,欢迎关注我的公众号:前端架构师笔记