如何在Docker构建时将生成的制品文件名设置为镜像名称
实现方法
Docker本身不支持在Dockerfile内部直接定义最终构建出的镜像名称,镜像的名称和标签必须在执行docker build命令时通过-t参数传入。要实现镜像名和构建产出的Jar包名一致,核心逻辑是先拿到Maven构建生成的Jar包名称,再将其作为参数传入构建命令打标签,以下是两种可直接落地的方案:
方案1:全版本兼容方案(所有Docker版本可用)
不需要依赖新版本Docker特性,通过临时构建容器提取Jar名即可,步骤如下:
- 先修正原有Dockerfile的问题(原ENTRYPOINT参数缺少逗号分隔会触发运行错误),去掉硬编码的版本号,消除版本不一致的隐患:
FROM maven:3-jdk-8-alpine AS build ADD . /my-app WORKDIR /my-app # 版本号可通过构建参数传入,默认值可自行调整 ARG NEW_VERSION=1.0.1 RUN mvn versions:set -DnewVersion="${NEW_VERSION}" RUN mvn compile RUN mvn package FROM openjdk:8-jdk-alpine # 从构建阶段直接拷贝Jar包,不需要硬编码文件名 COPY --from=build /my-app/target/*.jar /app.jar # 修正原ENTRYPOINT的参数格式错误 ENTRYPOINT ["java", "-cp", "/app.jar", "com.mycompany.app.App"]
- 执行以下构建命令,自动提取Jar名作为镜像名:
# 第一步:仅执行多阶段构建的build阶段,生成临时构建镜像 docker build --target build -t temp-mvn-build . # 第二步:从临时构建镜像中提取生成的Jar包名称,自动排除sources、javadoc等附属包 IMAGE_NAME=$(docker run --rm temp-mvn-build sh -c 'ls target/*.jar | grep -E "(sources|javadoc)" -v | head -n1 | xargs basename | sed "s/\.jar$//"') # 第三步:删除临时构建镜像 docker rmi temp-mvn-build # 第四步:构建最终镜像,用提取到的Jar名作为镜像名称 docker build -t ${IMAGE_NAME} .
执行完成后,本地生成的镜像名称会和Maven产出的Jar包名完全一致,例如my-app-1.0.1。
方案2:BuildKit 高效方案(Docker 18.09及以上版本支持)
如果你的Docker版本支持BuildKit,可以省去临时镜像的步骤,直接导出构建阶段的产物提取Jar名:
# 开启BuildKit export DOCKER_BUILDKIT=1 # 新建临时目录存放构建阶段产出 mkdir -p ./temp-build-output # 仅执行build阶段,将target目录输出到本地临时目录 docker build --target build --output type=local,dest=./temp-build-output . # 提取Jar包名称作为镜像名 IMAGE_NAME=$(ls ./temp-build-output/target/*.jar | grep -E "(sources|javadoc)" -v | head -n1 | xargs basename | sed "s/\.jar$//") # 清理临时目录 rm -rf ./temp-build-output # 构建最终镜像 docker build -t ${IMAGE_NAME} .
注意:不要尝试在Dockerfile内部通过ENV、LABEL等指令修改镜像标签,Docker构建的运行上下文隔离决定了内部指令无法干预外部
docker build命令的标签参数,所有镜像命名必须在执行构建命令时指定。
内容的提问来源于stack exchange,提问作者Eladik
相关产品推荐
相关产品推荐

