news 2026/8/15 17:17:25

1Panel容器化部署实战:Jenkins流水线自动化构建与发布Java应用

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
1Panel容器化部署实战:Jenkins流水线自动化构建与发布Java应用

1. 为什么我们需要这条自动化流水线?

如果你和我一样,带过几个中小型团队,或者自己维护过几个Java应用,肯定对下面这个场景不陌生:每次代码更新,都要手动登录服务器,git pull拉取最新代码,然后mvn clean package打包,接着用scp或者FTP把那个几十上百兆的jar包传到服务器,最后再ps -ef | grep java找到进程,kill掉,再用nohup java -jar ... &启动。一套流程下来,十分钟过去了,还容易手滑出错。更别提多环境(开发、测试、生产)部署时,那简直就是一场灾难。

我之前就踩过这样的坑。有一次半夜上线,因为太困,打包命令少打了个参数,导致一个非关键功能异常,又得回滚重来,折腾到天亮。从那次以后,我就下定决心,一定要把构建发布这两个最耗时、最容易出错的环节自动化。

这就是我们今天要聊的核心:用1Panel的容器化环境,加上Jenkins的流水线,打造一条从代码提交到应用上线的“高速公路”。这条“路”建好后,你只需要点一下“构建”按钮,或者更酷一点,让Git提交自动触发,剩下的打包、构建Docker镜像、推送到仓库、重启容器服务,全部由机器自动完成。你可以喝着咖啡,看着日志一条条刷过去,应用就平滑更新了。听起来是不是很美好?

1Panel在这里扮演了什么角色呢?它提供了一个非常清爽、直观的容器管理界面。我们不用再记一堆复杂的docker run参数,也不用去维护繁琐的docker-compose.yml文件(当然,它也支持)。对于Java应用,1Panel内置的“运行时环境”功能,可以一键创建包含指定JDK版本的容器,直接运行我们的jar包,省去了自己制作Docker镜像的步骤,特别适合快速起步。而Jenkins,则是这条流水线上不知疲倦的“装配工人”,负责调度所有任务。

所以,这篇文章就是一份实打实的“铺路”指南。我会假设你已经有了一个可以运行的1Panel环境和一个Jenkins服务(安装教程网上很多,这里不赘述),然后手把手带你打通这最后一公里,实现真正的一键发布。无论你是运维工程师、后端开发,还是团队的技术负责人,这套方案都能显著提升你们的交付效率和部署体验。

2. 搭建舞台:配置Jenkins与1Panel服务器的通信桥梁

自动化部署的第一步,是让Jenkins这个“指挥中心”能够安全、顺利地指挥远端的1Panel服务器(也就是你的应用最终运行的地方)。它们之间最常见的通信方式就是SSH。这就像给Jenkins配了一把能打开服务器大门的专属钥匙。

2.1 安装Jenkins的“万能钥匙”:Publish Over SSH插件

首先,我们需要在Jenkins里安装一个核心插件:Publish Over SSH。这个插件允许Jenkins通过SSH协议向远程服务器传输文件,并执行命令。

  1. 登录你的Jenkins管理后台。
  2. 点击左侧菜单的“系统管理”(Manage Jenkins)。
  3. 选择“插件管理”(Manage Plugins)。
  4. 切换到“可选插件”(Available plugins) 标签页。
  5. 在右上角的搜索框里输入“Publish Over SSH”
  6. 找到插件后,勾选它,然后点击页面下方的“直接安装”(Install without restart) 或“立即下载并在重启后安装”。通常直接安装即可,安装完成后根据提示重启Jenkins。

这个插件就是Jenkins的手臂,让它能把打包好的产物“扔”到目标服务器上。

2.2 在Jenkins中配置1Panel服务器的连接信息

插件装好了,我们得告诉Jenkins服务器的地址和开门的“钥匙”在哪。

  1. 重启Jenkins后,再次进入“系统管理”->“系统配置”(Configure System)。
  2. 页面往下拉,找到“Publish over SSH”区域。如果没找到,可能是插件没加载成功,可以尝试完全重启Jenkins服务。
  3. 这里是配置的关键,我画个表格把每个参数说清楚:
配置项填写内容说明我的实战示例与注意事项
Passphrase如果你的SSH私钥设置了密码,就填在这里。通常为了自动化,我们使用无密码的私钥。留空
Path to keyJenkins服务器上,SSH私钥文件的绝对路径。这是认证方式一/var/lib/jenkins/.ssh/id_rsa(Jenkins用户的默认密钥路径)
Key直接将私钥文件的内容粘贴到这里。这是认证方式二,比指定路径更常用、更便携。id_rsa文件的内容(以-----BEGIN RSA PRIVATE KEY-----开头)全部复制粘贴进来。
SSH Servers点击“新增”(Add),来添加我们的1Panel服务器。

点击新增后,会展开服务器详细配置:

子配置项填写内容说明我的实战示例与注意事项
Name给你这台服务器起个名字,方便在项目里选择。1Panel-Production
Hostname1Panel服务器的IP地址或域名。192.168.1.100
Username用于SSH登录的Linux用户名。强烈建议专门创建一个用于部署的用户,如deployerdeployer
Remote Directory远程服务器的基准目录。后续传输文件时,指定的路径都是基于这个目录的。/home/deployer/opt

这里有个巨坑,我踩过好几次!关于认证,最稳妥的做法是:

  • 在1Panel服务器上,用deployer用户生成SSH密钥对:ssh-keygen -t rsa(一直回车,不设密码)。
  • 将生成的公钥(~/.ssh/id_rsa.pub)内容,添加到deployer用户自己的~/.ssh/authorized_keys文件中(cat id_rsa.pub >> authorized_keys)。
  • 将私钥(id_rsa)的内容复制出来,粘贴到Jenkins配置的“Key”栏位里。

这样配置,就避免了Jenkins服务器上密钥路径的权限问题。配置完成后,一定要点击底部的“Test Configuration”按钮。如果看到绿色的“Success”提示,恭喜你,桥梁已经架通了!如果失败,请检查防火墙SSH端口(默认22)是否开放,以及用户名、密钥是否正确。

3. 传统方式的自动化:Jenkins直接部署Jar包

在进入炫酷的容器化部署之前,我们先来看看如何用Jenkins实现传统Jar包部署的自动化。这个过程是理解自动化流水线的基础,而且对于一些暂时无法容器化的老项目,依然非常有用。

3.1 创建你的第一个自动化构建任务

我们假设你有一个Spring Boot项目,代码仓库在GitLab或Gitee上。

  1. 在Jenkins首页点击“新建任务”(New Item)。
  2. 输入任务名称,例如my-springboot-app,选择“自由风格项目”(Freestyle project),然后点击确定。
  3. “源码管理”(Source Code Management) 部分,选择Git,填入你的仓库URL和凭证(用户名密码或SSH密钥)。在“分支”栏可以指定要构建的分支,如*/main*/master
  4. “构建触发器”(Build Triggers) 部分,你可以设置定时构建(如H/30 * * * *表示每30分钟一次),或者更高级的“GitHub hook trigger for GITScm polling”来实现代码一提交就自动构建。这里我们先跳过,手动触发。
  5. “构建环境”(Build Environment) 暂时不需要特殊设置。
  6. 最关键的一步:“构建”(Build)。点击“增加构建步骤”,选择“执行shell”(Execute shell)。这里我们写入Maven打包命令。
    # 如果你的Jenkins服务器安装了Maven mvn clean package -DskipTests # 或者使用全路径 # /opt/maven/bin/mvn clean package -DskipTests
    这个命令会在项目根目录下的target文件夹里生成一个jar包,名字通常类似myapp-0.0.1-SNAPSHOT.jar

3.2 将构建产物推送到1Panel服务器并启动

打包只是第一步,接下来要把这个jar包送到服务器上并运行起来。

  1. 在项目配置页面,找到“构建后操作”(Post-build Actions) 区域(有些版本叫“后期构建步骤”)。
  2. 点击“增加构建后操作步骤”,选择“Send files or execute commands over SSH”。没错,就是我们刚才配置的那个插件!
  3. 在出现的配置中:
    • Name: 选择你之前配置好的服务器,例如1Panel-Production
    • Source files: 这里填写相对于Jenkins工作空间jar包路径。例如:target/*.jar*是通配符,会匹配所有jar包。
    • Remove prefix: 填写target/。这个操作的意思是,传输文件时,去掉target/这个前缀。这样,target/myapp.jar传到服务器上,就变成了myapp.jar,而不是放在target文件夹里。
    • Remote directory: 这里可以再指定一个子目录,它会附加在系统配置里设置的“Remote Directory”之后。例如,这里填写app/,那么文件最终会被传到/home/deployer/app/目录下。
    • Exec command: 传输完成后,在远程服务器上执行的命令。这里就是传统部署的核心
      # 切换到应用目录 cd /home/deployer/app # 停止之前可能运行的旧进程(简单粗暴版,根据实际情况调整) pkill -f 'myapp.*.jar' || true # 后台启动新的jar包 nohup java -jar myapp-0.0.1-SNAPSHOT.jar > app.log 2>&1 & # 检查进程是否启动 sleep 5 ps -ef | grep java | grep myapp
    我来解释一下最后那个启动命令:nohup保证终端退出后进程不挂断;> app.log 2>&1把标准输出和错误输出都重定向到app.log文件,方便查看日志;最后的&是放入后台执行。

点击保存,然后立即点击“立即构建”(Build Now)。如果一切顺利,你会在构建历史里看到蓝色圆球,点进去看控制台输出,会显示文件传输和远程命令执行的详细日志。至此,一个最基本的自动化部署流程就完成了。但这只是开始,这种方式有诸多问题:环境依赖(服务器要有对的JDK版本)、端口冲突、多个应用隔离性差、升级回滚麻烦。接下来,就是容器化登场解决这些问题的时候了。

4. 拥抱容器化:使用1Panel运行时环境部署Java应用

容器化就像给每个应用分配了一个独立的、标准化的“集装箱”。这个集装箱里包含了应用运行所需的一切:代码、运行时环境(JDK)、系统工具、库文件。1Panel的“运行时环境”功能,极大地简化了为Java应用创建这个“集装箱”的过程。

4.1 在1Panel中创建Java运行时环境容器

我们不再需要手动编写Dockerfile,定义基础镜像、复制Jar包、设置启动命令。1Panel提供了图形化的方式。

  1. 登录你的1Panel后台。
  2. 在左侧菜单进入“容器”->“运行时环境”
  3. 点击右上角的“创建环境”按钮。
  4. 你会看到一个非常直观的表单:
    • 环境名称:给你的容器起个名字,比如myapp-java17
    • 镜像:选择你需要的Java基础镜像。1Panel预置了常用的选项,如openjdk:17-jdk-slim(推荐,体积小)、openjdk:8openjdk:11等。这完美解决了不同项目需要不同JDK版本的问题。
    • 端口映射:这是容器内外通信的桥梁。比如你的Spring Boot应用在容器内监听8080端口,你可以将它映射到宿主机的18080端口。格式为宿主机端口:容器端口,例如18080:8080
    • 目录映射(挂载):这是持久化数据的关键。容器内的数据是易失的,重启就没了。我们需要把jar包、日志文件等映射到宿主机的目录。例如:
      • 源路径(容器内):/app(我们打算把jar包放这里)
      • 目标路径(宿主机):/home/deployer/app(Jenkins会把jar包传到这里)
      • 同样,可以把日志目录也映射出来,比如/app/logs->/home/deployer/app/logs
    • 启动命令:容器启动后执行的命令。对于我们运行Jar包,这里填:java -jar /app/myapp-0.0.1-SNAPSHOT.jar。注意,路径是容器内的路径/app

配置完成后,点击“确认”。1Panel会自动拉取镜像并创建容器。但此时先不要启动,因为/app目录里还没有我们的jar包呢。

4.2 调整Jenkins任务,适配容器化部署

现在,我们需要改造之前的Jenkins任务,让它把jar包传到1Panel容器映射的宿主机目录,然后重启容器。

  1. 回到Jenkins中你的项目配置,找到“构建后操作”里那个SSH传输步骤。
  2. 修改“Source files”“Remove prefix”,确保能准确匹配到打包后的jar包。比如你的项目打包后名字固定,可以写target/myapp-*.jar
  3. 修改“Remote directory”,让它指向1Panel容器映射的宿主机目录,例如app/(对应/home/deployer/app)。
  4. 最关键的一步:修改“Exec command”。我们不再需要复杂的nohup启动命令,因为应用现在由Docker容器来运行。我们只需要做一件事:重启对应的Docker容器
    # 重启1Panel中名为“myapp-java17”的容器 docker restart myapp-java17
    是的,就这么简单!当新的jar包被传输到宿主机的映射目录后,容器内的/app目录内容也随之更新。此时重启容器,容器会重新执行我们预设的启动命令java -jar /app/myapp-0.0.1-SNAPSHOT.jar,自然就运行了新版本的代码。

这里有一个必须解决的权限问题:Jenkins通过SSH登录到1Panel服务器的deployer用户,默认是没有权限执行docker命令的。你会看到permission denied错误。

解决方法就是给deployer用户加入docker用户组:

# 在1Panel服务器上执行 sudo usermod -aG docker deployer

执行后,需要让deployer用户重新登录,或者更简单粗暴一点,在Jenkins的Exec command里使用sudo(需要配置deployer用户的sudo免密码权限):

sudo docker restart myapp-java17

配置sudo免密码,可以编辑/etc/sudoers文件(使用visudo命令),添加一行:deployer ALL=(ALL) NOPASSWD: /usr/bin/docker restart myapp-java17。这样更安全,只赋予了重启特定容器的权限。

保存Jenkins配置,再次执行构建。你会发现,控制台输出在文件传输完成后,会执行docker restart命令,你的应用就在容器中完成了一次无缝重启。这种方式实现了应用与宿主机环境的完全解耦,升级、回滚(替换jar包并重启容器)变得极其简单。

5. 进阶与优化:打造更健壮的流水线

基本的流水线跑通了,但我们在实际生产中肯定会遇到更多问题。下面分享几个我踩过坑后总结的进阶优化点,让你的流水线从“能用”变得“好用且可靠”。

5.1 镜像管理与版本控制

直接替换/app目录下的jar包虽然方便,但失去了Docker镜像版本管理的优势。更专业的做法是,在Jenkins中构建应用镜像

  1. 在你的项目根目录创建一个Dockerfile
    FROM openjdk:17-jdk-slim WORKDIR /app # 将Maven打包好的jar包复制到镜像中,使用通配符避免写死版本号 COPY target/*.jar app.jar EXPOSE 8080 ENTRYPOINT ["java", "-jar", "app.jar"]
  2. 修改Jenkins的“构建”步骤,在Shell中增加构建和推送镜像的命令:
    # 1. 打包应用 mvn clean package -DskipTests # 2. 构建Docker镜像,带上版本标签(例如使用构建号) docker build -t my-registry.com/myapp:${BUILD_NUMBER} . # 3. 推送镜像到私有仓库 docker push my-registry.com/myapp:${BUILD_NUMBER} # 4. 在1Panel服务器上拉取新镜像并更新容器(通过SSH执行) # 这部分命令可以移到“Exec command”中,但逻辑更复杂
  3. 在1Panel服务器上,Exec command需要改为:
    # 拉取最新镜像 docker pull my-registry.com/myapp:${BUILD_NUMBER} # 停止并删除旧容器 docker stop myapp-container && docker rm myapp-container # 用新镜像启动新容器,重新映射端口和目录 docker run -d --name myapp-container -p 18080:8080 -v /home/deployer/logs:/app/logs my-registry.com/myapp:${BUILD_NUMBER}
    这种方式实现了完整的镜像版本化,回滚时只需指定旧的镜像标签即可,管理起来更加清晰。

5.2 处理容器时区与日志

如果你发现容器内应用日志的时间是UTC,与本地时间对不上,可以在1Panel创建环境时,在“启动命令”中指定时区环境变量:

java -jar -Duser.timezone=Asia/Shanghai /app/myapp-*.jar

或者,更Docker化的方式是在1Panel创建环境的“高级设置”中,添加环境变量:TZ=Asia/Shanghai。关于日志,强烈建议通过目录映射(-v)将容器内的日志目录挂载到宿主机,这样即使容器被删除,日志文件也还在。在1Panel的“目录映射”设置里添加即可,例如/app/logs->/home/deployer/app/logs

5.3 健康检查与回滚策略

一个健壮的部署流程必须包含健康检查。我们可以在Exec command里,在重启容器后,增加一个检查应用是否真正启动成功的逻辑。

docker restart myapp-java17 # 等待10秒,让应用启动 sleep 10 # 检查容器内应用的HTTP端口是否可访问,或者检查日志关键词 if curl -f http://localhost:18080/actuator/health > /dev/null 2>&1; then echo "应用启动成功!" else echo "应用启动失败,尝试回滚..." # 这里可以加入回滚逻辑,例如重启上一个版本的容器,或者从备份恢复jar包 docker restart myapp-java17-backup exit 1 # 构建标记为失败 fi

对于简单的Jar包替换方式,回滚可以是将备份的旧版jar包复制回来并重启容器。对于镜像方式,回滚就是使用上一个版本的镜像重新运行容器。将这些逻辑脚本化,集成到Jenkins的Pipeline脚本中,就能构建出一条具备自愈能力的强大流水线。

最后,别忘了安全。用于部署的deployer用户权限要严格控制,仅赋予其必要的目录读写和docker restart(或特定命令)的sudo权限。Jenkins的凭证管理系统也要用好,避免敏感信息泄露。这套组合拳打下来,你的团队就能享受到容器化与自动化带来的高效与宁静了。至少,半夜被叫起来手动部署的事情,不会再发生了。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/15 17:14:38

PowerShell文件切割避坑指南:为什么你的20GB文件总是切割失败?

PowerShell大文件切割实战:从原理到避坑全解析 当20GB文件在PowerShell中"罢工"时 深夜的办公室里,咖啡杯早已见底,而你盯着PowerShell窗口里那个顽固的24GB日志文件已经三个小时了。每次执行分割脚本,不是内存溢出就是…

作者头像 李华
网站建设 2026/7/14 16:03:06

AI训练师备考指南:10个最容易错的NLP和数据清洗题解析

AI训练师备考指南:10个最容易错的NLP和数据清洗题解析 自然语言处理和数据清洗是AI训练师认证考试中的两大核心模块,也是考生最容易失分的领域。本文将深入解析10个高频易错题,帮助考生掌握关键概念和解题技巧。 1. 自然语言处理基础概念辨析…

作者头像 李华
网站建设 2026/7/14 16:03:03

Phi-3-mini-128k-instruct多场景落地:跨境电商独立站FAQ自动生成与更新

Phi-3-mini-128k-instruct多场景落地:跨境电商独立站FAQ自动生成与更新 1. 引言:跨境电商卖家的新烦恼 如果你在运营一个跨境电商独立站,每天最头疼的事情是什么?是选品、物流,还是营销?很多卖家会告诉你…

作者头像 李华
网站建设 2026/7/14 16:03:03

告别环境配置烦恼:PyTorch 2.5镜像一键部署深度学习开发环境

告别环境配置烦恼:PyTorch 2.5镜像一键部署深度学习开发环境 你是否也曾被深度学习环境配置折磨得焦头烂额?CUDA版本不匹配、PyTorch安装失败、依赖库冲突……这些“环境玄学”问题,不知浪费了多少宝贵的研究和开发时间。 今天,…

作者头像 李华