概要描述
在容器镜像中新增或替换 JAR 包、shell 脚本时,建议始终通过 Dockerfile 生成新镜像,不要直接修改运行中的容器,也不要使用 docker commit 保存临时修改。
本文说明如何使用 Dockerfile 规范地向现有镜像添加或替换 JAR 包,并提供 Yarn 镜像换包示例及常见最佳实践。
详细说明
一、适用范围
本文适用于以下场景:
- 在现有 Docker 镜像中新增 JAR/SHELL 包;
- 使用同名 JAR/SHELL 覆盖镜像中的旧文件;
- 使用新版本 JAR/SHELL 替换旧版本文件;
二、构建前检查
1. 确认基础镜像
查看基础镜像的 ID、标签和仓库信息:
docker images |grep :
三、准备构建目录
为每次换包创建独立目录,并将 Dockerfile 与补丁文件纳入版本管理或变更记录:
image-patch/
├── Dockerfile
└── patches/
└──
└──
四、编写 Dockerfile
1. 推荐模板
支持较新 Dockerfile 前端的构建环境,可以直接在 COPY 时指定属主和权限:
FROM @
LABEL io.transwarp.yarn.image.description="Add "
COPY patches/ /
2. 使用 COPY,不要滥用 ADD
对于构建上下文中的本地 JAR 文件,应使用 COPY。ADD 还具有远程资源和本地 tar 自动解包等额外行为,不适合仅复制普通 JAR 的场景。
3. 同名替换无需先删除
如果新旧 JAR 的目标路径和文件名完全相同,COPY 会在新镜像层中覆盖该路径,不需要额外执行:
RUN rm -f /
需要注意,覆盖或删除只会改变新镜像的可见文件系统,不会从基础镜像历史层中移除原文件字节。因此,增加一条 RUN rm 不能减小基础层大小。
4. 不同文件名替换时必须处理旧版本
如果新旧 JAR 文件名不同,并且二者同时存在会导致类冲突,应显式删除旧版本,再复制新文件:
FROM @
RUN rm -f /
COPY patches/ /
此时应优先保证运行时只有正确版本,不要为了少一个 layer 而保留冲突 JAR。删除动作、旧文件名和回滚基线都必须记录清楚。
5. 使用 LABEL 记录变更
使用 LABEL 记录基础镜像、补丁名称、校验值、变更单号和构建时间。不要使用已经弃用的 MAINTAINER 指令,也不要在 Dockerfile 中写入个人邮箱、内部群聊或其他不适合对外公开的信息。
历史变更应由版本控制和镜像元数据保存,不建议长期在 Dockerfile 中累积被注释掉的旧命令。回滚时应使用历史镜像 digest,而不是手工取消注释旧步骤后重新构建。
五、构建新镜像
在构建目录中执行,注意这里最后有一个 . 是代表基于当前目录构建:
docker build -t : .
正常情况下,构建日志应显示:
FROM使用预期的基础镜像 digest;- 构建上下文仅包含 Dockerfile 和本次补丁;
COPY成功写入目标路径;- 最终生成并标记新的镜像 ID。
六、验证新镜像
1. 检查镜像历史
docker image history :
对于只新增一个 JAR 的换包,新增加的文件层通常应只有一个。LABEL 等元数据层不增加文件内容大小。
七、推送镜像
推送前确认 <NEW_TAG> 在仓库中尚不存在,并确认组织允许向该仓库上传补丁内容。不要通过覆盖现有标签来“替换旧版本”。
如果构建时使用的是本地仓库名,可以先创建目标仓库标签:
docker tag : /:
经确认后推送:
docker push /:
推送成功后记录仓库返回的 digest。部署清单优先引用该 digest:
/@
推送成功不代表已经部署。更新 Kubernetes Deployment,应另行确认变更窗口、灰度范围和回滚方案。
八、回滚方法
1. 尚未部署
如果新镜像尚未部署,停止后续推送或发布即可。原镜像不需要修改。
2. 已经部署
将工作负载的镜像引用恢复为变更前记录的旧 digest,并按原部署流程发布。回滚后需要检查:
- Pod 或容器全部恢复为旧镜像 digest;
- 服务健康检查通过;
- 原有作业和核心功能正常;
- 没有新镜像与旧镜像混跑造成的兼容问题。
不要删除旧镜像或重用旧标签,直到补丁观察期结束并满足组织的镜像保留策略。
九、quark-8.37.3-final 镜像换包示例
以下示例将 inceptor-torc-3.1.1.jar 加入 quark 运行时 classpath。执行前必须根据目标版本确认真实路径;quark 的类库目录为 /usr/lib/inceptor/lib/。
构建目录:
quark-image-patch/
├── Dockerfile
└── patches/
└── inceptor-torc-3.1.1.jar
Dockerfile:
FROM gts-131081:5000/transwarp/quark:quark-8.37.3-final
LABEL io.transwarp.quark.image.description="Add inceptor-torc-3.1.1.jar" \
io.transwarp.quark.patch.artifact="inceptor-torc-3.1.1.jar"
COPY patches/inceptor-torc-3.1.1.jar /usr/lib/inceptor/lib/inceptor-torc-3.1.1.jar
构建并验证:
docker build -t gts-131081:5000/transwarp/quark:quark-8.37.3-final .
推送到仓库:
docker push gts-131081:5000/transwarp/quark:quark-8.37.3-final
最后重启 quark 生效。