Dockerfile COPY指令如何复制build/libs下最新Spring Boot Jar包
问题解决方法
Docker原生COPY指令的通配符仅支持路径匹配,不具备按版本、修改时间自动筛选文件的能力,无需每次执行gradle clean assemble清理旧产物,通过以下两种方案即可实现仅复制最新Jar包的需求:
方案1:构建时传入精准Jar路径(最小改动)
无需修改原有Dockerfile,仅调整docker build执行命令即可。
原有Dockerfile保持不变:
FROM openjdk:8-jdk-alpine ARG JAR_FILE=build/libs/*.jar COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar"]
执行镜像构建时,先通过系统命令筛选出build/libs目录下最新修改的Jar包,将精准路径作为构建参数传入:
- Linux/macOS 环境:
docker build --build-arg JAR_FILE=$(ls -t build/libs/*.jar | head -n1) -t app-image .
- Windows PowerShell 环境:
docker build --build-arg JAR_FILE=(Get-ChildItem build/libs/*.jar | Sort-Object LastWriteTime -Descending | Select-Object -First 1).FullName -t app-image .
命令中ls -t会按文件修改时间倒序排列所有Jar包,取排序后的第一个文件就是最新构建的版本,不会匹配到多个旧文件触发COPY报错。
方案2:多阶段构建内置筛选逻辑(无需调整构建命令)
如果不想每次构建时额外加参数,可以通过Docker多阶段构建,把Jar包筛选逻辑内置在Dockerfile中,调整后的配置如下:
# 临时阶段:完成Jar包筛选 FROM alpine:3.20 AS tmp-builder WORKDIR /tmp RUN mkdir /target COPY build/libs/*.jar ./ # 按修改时间取最新Jar,复制为固定名称的app.jar RUN ls -t *.jar | head -n1 | xargs -I {} cp {} /target/app.jar # 最终运行镜像阶段 FROM openjdk:8-jdk-alpine COPY --from=tmp-builder /target/app.jar /app.jar ENTRYPOINT ["java","-jar","/app.jar"]
该方案会先把所有Jar包拷贝到轻量的临时构建阶段,在阶段内通过shell命令筛选出最新的Jar包,最终仅把筛选好的单个Jar包拷贝到运行镜像中,全程不需要提前清理构建目录,也不需要修改构建命令。
扩展规则:如果需要排除SNAPSHOT快照版本、仅选取正式发布版,只需要在筛选命令中增加过滤逻辑即可,比如将
ls -t *.jar替换为ls -t *.jar | grep -v SNAPSHOT,即可自动过滤快照版本,选取最新的正式版Jar。
内容的提问来源于stack exchange,提问作者Janning Vygen
相关产品推荐
相关产品推荐

