Docker构建镜像时如何先在构建上下文执行Gradle构建再仅复制JAR文件
问题本质说明
你期望的写法无法运行的核心原因是:Dockerfile的RUN指令是在镜像构建的临时容器内部执行的,执行该指令时容器内还没有任何项目文件,自然无法找到gradlew脚本执行构建,也不可能直接调用宿主机的构建上下文执行构建命令。
以下是两种可行的实现方案:
方案1:Docker多阶段构建(最推荐)
这是Docker官方推荐的分离构建和运行上下文的标准方案,全程在Docker构建流程内完成,不需要本地预装Gradle环境,最终运行镜像仅包含JRE和可执行Jar,无任何源码、构建工具等冗余文件。
完整Dockerfile写法如下:
# 第一阶段:构建阶段,仅负责完成Jar包编译 FROM gradle:8-jdk8-alpine AS builder # 拷贝项目源码到构建容器内 COPY ./ /build WORKDIR /build # 执行构建,可根据需求调整是否跳过测试 RUN ./gradlew clean build -x test # 第二阶段:运行阶段,仅保留运行所需的最小环境 FROM azul/zulu-openjdk-alpine:8 WORKDIR /app # 仅从构建阶段拷贝生成的Jar包,完全不引入源码等冗余文件 COPY --from=builder /build/build/libs/oms-core-app-*-SNAPSHOT.jar ./ # 启动命令优化,避免多余的sh进程 ENTRYPOINT ["java", "-jar", "oms-core-app-*-SNAPSHOT.jar"]
该方案优势:
- 构建环境一致,不会出现本地环境和镜像环境差异导致的构建失败问题
- 最终镜像体积极小,无任何冗余文件
- 不需要修改本地构建流程,直接执行
docker build即可完成全流程
方案2:本地预构建+Docker忽略配置
如果希望直接在宿主机完成构建,再把Jar复制到镜像内,可以通过以下步骤实现:
- 先在项目根目录执行本地构建命令:
./gradlew clean build - 项目根目录新增
.dockerignore文件,过滤所有冗余文件,仅保留构建好的Jar包:
# .dockerignore 内容 * !oms-core-app-*-SNAPSHOT.jar
- 简化后的Dockerfile写法:
FROM azul/zulu-openjdk-alpine:8 WORKDIR /app COPY ./oms-core-app-*-SNAPSHOT.jar ./ ENTRYPOINT ["java", "-jar", "oms-core-app-*-SNAPSHOT.jar"]
该方案优势是构建速度更快,不需要在容器内重复下载Gradle依赖,适合本地开发频繁构建镜像的场景。
内容的提问来源于stack exchange,提问作者Harry Manoharan
相关产品推荐
相关产品推荐

