本文介绍了Docker中缓慢的gradle构建缓存gradle构建的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在做一个大学项目,我们需要一次运行多个Spring Boot应用程序。

I am doing university project where we need to run multiple Spring Boot applications at once.

我已经使用gradle docker image配置了多阶段构建,然后运行

I had already configured multi-stage build with gradle docker image and then run app in openjdk:jre image.

这是我的Dockerfile:

Here is my Dockerfile:

FROM gradle:5.3.0-jdk11-slim as builder
USER root
WORKDIR /usr/src/java-code
COPY . /usr/src/java-code/

RUN gradle bootJar

FROM openjdk:11-jre-slim
EXPOSE 8080
WORKDIR /usr/src/java-app
COPY --from=builder /usr/src/java-code/build/libs/*.jar ./app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

我正在使用docker-compose构建并运行所有程序。 docker-compose的一部分:

I am building and running everything with docker-compose. Part of docker-compose:

 website_server:
    build: website-server
    image: website-server:latest
    container_name: "website-server"
    ports:
      - "81:8080"

当然,第一个构建需要很长时间。 Docker正在提取所有依赖项。我对此表示同意。

Of course first build take ages. Docker is pulling all it's dependencies. And I am okay with that.

目前一切正常,但是代码中的每一个微小变化都会导致一个应用的构建时间约为1分钟。

Everything is working ok for now but every little change in code causes around 1 min build time for one app.

部分构建日志: docker-compose up --build

Step 1/10 : FROM gradle:5.3.0-jdk11-slim as builder
 ---> 668e92a5b906
Step 2/10 : USER root
 ---> Using cache
 ---> dac9a962d8b6
Step 3/10 : WORKDIR /usr/src/java-code
 ---> Using cache
 ---> e3f4528347f1
Step 4/10 : COPY . /usr/src/java-code/
 ---> Using cache
 ---> 52b136a280a2
Step 5/10 : RUN gradle bootJar
 ---> Running in 88a5ac812ac8

Welcome to Gradle 5.3!

Here are the highlights of this release:
 - Feature variants AKA "optional dependencies"
 - Type-safe accessors in Kotlin precompiled script plugins
 - Gradle Module Metadata 1.0

For more details see https://docs.gradle.org/5.3/release-notes.html

Starting a Gradle Daemon (subsequent builds will be faster)
> Task :compileJava
> Task :processResources
> Task :classes
> Task :bootJar

BUILD SUCCESSFUL in 48s
3 actionable tasks: 3 executed
Removing intermediate container 88a5ac812ac8
 ---> 4f9beba838ed
Step 6/10 : FROM openjdk:11-jre-slim
 ---> 0e452dba629c
Step 7/10 : EXPOSE 8080
 ---> Using cache
 ---> d5519e55d690
Step 8/10 : WORKDIR /usr/src/java-app
 ---> Using cache
 ---> 196f1321db2c
Step 9/10 : COPY --from=builder /usr/src/java-code/build/libs/*.jar ./app.jar
 ---> d101eefa2487
Step 10/10 : ENTRYPOINT ["java", "-jar", "app.jar"]
 ---> Running in ad02f0497c8f
Removing intermediate container ad02f0497c8f
 ---> 0c63eeef8c8e
Successfully built 0c63eeef8c8e
Successfully tagged website-server:latest

每次启动Gradle守护程序后冻结(后续构建会更快)

我正在考虑使用缓存添加卷gradle依赖关系,但我不知道这是否是问题的核心。

I was thinking about adding volume with cached gradle dependencies but I don't know if that is core of the problem. Also i could't find good examples for that.

有什么方法可以加快构建速度吗?

Is there any way to speed up the build?

推荐答案

构建会花费很多时间,因为每次构建Docker映像时,Gradle都会下载所有插件和依赖项。

Build takes a lot of time because Gradle every time the Docker image is built downloads all the plugins and dependencies.

有无法在映像构建时挂载卷。但是可以引入一个新的阶段,该阶段将下载所有依赖项并将其缓存为Docker映像层。

There is no way to mount a volume at the image build time. But it is possible to introduce new stage that will download all dependencies and will be cached as Docker image layer.

FROM gradle:5.6.4-jdk11 as cache
RUN mkdir -p /home/gradle/cache_home
ENV GRADLE_USER_HOME /home/gradle/cache_home
COPY build.gradle /home/gradle/java-code/
WORKDIR /home/gradle/java-code
RUN gradle clean build -i --stacktrace

FROM gradle:5.6.4-jdk11 as builder
COPY --from=cache /home/gradle/cache_home /home/gradle/.gradle
COPY . /usr/src/java-code/
WORKDIR /usr/src/java-code
RUN gradle bootJar -i --stacktrace

FROM openjdk:11-jre-slim
EXPOSE 8080
USER root
WORKDIR /usr/src/java-app
COPY --from=builder /usr/src/java-code/build/libs/*.jar ./app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

Gradle插件和依赖项缓存位于 $ GRADLE_USER_HOME / caches 中。 GRADLE_USER_HOME 必须设置为不同于 /home/gradle/.gradle 的其他值。父级Gradle Docker映像中的 /home/gradle/.gradle 被定义为卷,并在每个映像层之后被擦除。

Gradle plugin and dependency cache is located in $GRADLE_USER_HOME/caches. GRADLE_USER_HOME must be set to something different than /home/gradle/.gradle. /home/gradle/.gradle in parent Gradle Docker image is defined as volume and is erased after each image layer.

在示例代码 GRADLE_USER_HOME 中设置为 / home / gradle / cache_home

builder 阶段复制Gradle缓存以避免再次下载依赖项: COPY --from = cache / home / gradle / cache_home /home/gradle/.gradle

In the builder stage Gradle cache is copied to avoid downloading the dependencies again: COPY --from=cache /home/gradle/cache_home /home/gradle/.gradle.

阶段缓存仅当更改 build.gradle 时才会重建。
更改Java类时,将重用具有所有依赖关系的缓存图像层。

The stage cache will be rebuilt only when build.gradle is changed.When Java classes are changes, cached image layer with all dependencies is reused.

此修改可以减少构建时间,但是可以使用以下更干净的方式构建Docker图像Java应用程序是Google的。
有一个允许为Java应用程序构建容器映像,而无需手动创建Dockerfile。
使用应用程序构建映像并运行容器类似于:

This modifications can reduce the build time but more clean way of building Docker images with Java applications is Jib by Google.There is a Jib Gradle plugin that allows to build container images for Java applications without manually creating Dockerfile.Building image with application and running the container is similar to:

gradle clean build jib
docker-compose up

这篇关于Docker中缓慢的gradle构建缓存gradle构建的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-03 20:48
查看更多