Docker+Jenkins 自定义镜像指南

前言

本文详细介绍了如何通过Docker容器化技术构建自定义Jenkins镜像,解决传统部署方式中的环境一致性问题。我们将从镜像构建原理出发,逐步实现包含Node.js、JDK、Maven等工具链的一体化CI/CD环境,并探讨镜像优化、数据持久化和跨环境迁移的最佳实践。

创建镜像的方式

在DevOps实践中,Jenkins作为持续集成的核心工具,其环境一致性直接影响构建稳定性。传统部署方式存在以下痛点:

  • 依赖冲突:不同项目对JDK、Maven版本要求各异
  • 配置漂移:手动修改导致环境逐渐偏离初始状态
  • 迁移复杂:服务器更换需重新配置完整环境

通过Docker构建自定义Jenkins镜像,可实现:

  • 环境固化:一次构建,多环境一致运行
  • 工具集成:预置项目所需的全部依赖工具
  • 快速复制:通过镜像分发实现秒级环境部署

常用的Docker镜像的创建方式主要有以下三种:

  1. 基于容器提交创建(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

这种方式主要通过将运行中的容器状态保存为新镜像的方式创建镜像。通过这种方式优点就是可以快速的创建一个镜像,缺点也很明显,就是难以追踪变更记录,不便于版本管理。

  1. 基于 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流水线集成。

  1. 基于本地模板导入(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 环境的标准化与可移植性,构建了包含完整工具链的一体化镜像、实现了数据持久化与环境快速复制、掌握了镜像优化与跨环境迁移的技巧。

更多精彩文章,欢迎关注我的公众号:前端架构师笔记

相关推荐
城管不管2 小时前
Docker核心---数据卷(堵门秘籍)
运维·docker·容器
荔枝爱编程4 小时前
如何在 Docker 容器中使用 Arthas 监控 Java 应用
java·后端·docker
HONG_YANG5 小时前
2025 热门的 Web 化容器部署工具对比:Portainer VS Websoft9
docker
Peter·Pan爱编程6 小时前
Docker在Linux中安装与使用教程
linux·docker·eureka
__lll_10 小时前
Docker 从入门到实战:容器、镜像与 Compose 全攻略
前端·docker
柏成11 小时前
写给前端仔仔的docker实战
前端·docker·面试
进击的阿尔法猿13 小时前
docker
运维·docker·容器
木易双人青20 小时前
01-Docker-简介、安装与使用
运维·docker·容器
AI大模型1 天前
基于 Docker 的 LLaMA-Factory 全流程部署指南
docker·llm·llama