Docker 缓存 gradle 依赖项 [英] Docker cache gradle dependencies

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

问题描述

我正在尝试使用 docker 将我们的 Java Web 应用程序部署到 aws elastic beanstalk,其想法是能够在本地运行容器以进行开发和测试,并最终使用 git 将其推送到生产环境.

I'm trying to deploy our java web application to aws elastic beanstalk using docker, the idea is to be able to run the container locally for development and testing and eventually push it up to production using git.

我创建了一个安装了 tomcat8 和 java8 的基础镜像,执行 gradle 构建的镜像继承自这个基础镜像,加快了构建过程.

I've created a base image that has tomcat8 and java8 installed, the image that performs the gradle builds inherit from this base image, speeding up build process.

一切正常,除了使用 docker 构建的继承应用程序容器似乎没有缓存 gradle 依赖项之外,它每次都下载它,包括 gradlew.我们使用以下命令构建我们的 Web 应用程序:

All works well, except for the fact that the inheriting application container that gets built using docker doesn't seem to cache the gradle dependencies, it downloads it every time, including gradlew. We build our web application using the following command:

./gradlew war

有什么方法可以将文件缓存在 ~/.gradle 中,这会大大加快我的构建速度.

Is there some way that i can cache the files in ~/.gradle this would speed my build up dramatically.

这在 beanstalk 上并不是什么大问题,但对于尝试在本地构建和运行的开发人员来说是一个大问题,因为这确实需要很多时间,正如您想象的那样.

This isn't so much of an issue on beanstalk but is a big problem for devs trying to build and run locally as this does take a lot of time, as you can imagine.

基础镜像dockerfile:

The base image dockerfile:

FROM phusion/baseimage
EXPOSE 8080
RUN apt-get update
RUN add-apt-repository ppa:webupd8team/java
RUN apt-get update
RUN echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | sudo /usr/bin/debconf-set-selections
RUN apt-get -y install oracle-java8-installer
RUN java -version
ENV TOMCAT_VERSION 8.0.9
RUN wget --quiet --no-cookies http://archive.apache.org/dist/tomcat/tomcat-8/v${TOMCAT_VERSION}/bin/apache-tomcat-${TOMCAT_VERSION}.tar.gz -O /tmp/catalina.tar.gz
# Unpack
RUN tar xzf /tmp/catalina.tar.gz -C /opt
RUN mv /opt/apache-tomcat-${TOMCAT_VERSION} /opt/tomcat
RUN ln -s /opt/tomcat/logs /var/log/tomcat
RUN rm /tmp/catalina.tar.gz
# Remove unneeded apps
RUN rm -rf /opt/tomcat/webapps/examples
RUN rm -rf /opt/tomcat/webapps/docs
RUN rm -rf /opt/tomcat/webapps/ROOT
ENV CATALINA_HOME /opt/tomcat
ENV PATH $PATH:$CATALINA_HOME/bin
ENV CATALINA_OPTS $PARAM1
# Start Tomcat
CMD ["/opt/tomcat/bin/catalina.sh", "run"]

应用程序dockerfile:

The application dockerfile:

FROM <tag name here for base image>
RUN mkdir ~/.gradle
# run some extra stuff here to add things to gradle.properties file
# Add project Source
ADD . /var/app/myapp
# Compile and Deploy Application, this is what is downloading gradlew and all the maven dependencies every time, if only there was a way to take the changes it makes to ~/.gradle and persist it as a cache layer
RUN cd /var/app/myapp/ && ./gradlew war
RUN mv /var/app/myapp/build/libs/myapp.war /opt/tomcat/webapps/ROOT.war
# Start Tomcat
CMD ["/opt/tomcat/bin/catalina.sh", "run"]

推荐答案

我遇到了这个问题.您可能同意,最佳做法是在构建 docker 映像时单独下载依赖项作为单独的步骤.使用 gradle 变得有点棘手,因为没有直接支持下载依赖项.

I faced this issue. As you might agree, it is a best practice to download dependencies alone as a separate step while building the docker image. It becomes little tricky with gradle, since there is no direct support for downloading just dependencies.

选项 1:使用 docker-gradle Docker 镜像

Option 1 : Using docker-gradle Docker image

我们可以使用预先构建的 gradle docker 镜像来构建应用程序.这确保它不是本地系统构建,而是在干净的 docker 映像上完成的构建.

We can use pre-built gradle docker image to build the application. This ensures that it's not a local system build but a build done on a clean docker image.

docker volume create --name gradle-cache
docker run --rm -v gradle-cache:/home/gradle/.gradle -v "$PWD":/home/gradle/project -w /home/gradle/project gradle:4.7.0-jdk8-alpine gradle build
ls -ltrh ./build/libs

  • gradle 缓存在此处作为卷加载.因此,后续构建将重用下载的依赖项.
  • 此后,我们可以使用 Dockerfile 来获取此工件并生成应用程序特定的映像以运行应用程序.
  • 这样,就不需要构建器映像.应用构建流程和应用运行流程分离.
  • 由于挂载了 gradle-cache 卷,我们可以在不同的 gradle 项目中重用下载的依赖项.
  • 选项 2:多阶段构建

    ----- Dockerfile -----

    ----- Dockerfile -----

    FROM openjdk:8 AS TEMP_BUILD_IMAGE
    ENV APP_HOME=/usr/app/
    WORKDIR $APP_HOME
    COPY build.gradle settings.gradle gradlew $APP_HOME
    COPY gradle $APP_HOME/gradle
    RUN ./gradlew build || return 0 
    COPY . .
    RUN ./gradlew build
    
    FROM openjdk:8
    ENV ARTIFACT_NAME=your-application.jar
    ENV APP_HOME=/usr/app/
    WORKDIR $APP_HOME
    COPY --from=TEMP_BUILD_IMAGE $APP_HOME/build/libs/$ARTIFACT_NAME .
    EXPOSE 8080
    CMD ["java","-jar",$ARTIFACT_NAME]
    

    在上面的Dockerfile中

    In the above Dockerfile

    • 首先我们尝试单独复制项目的gradle文件,比如build.gradle、gradlew 等,
    • 然后我们复制gradle目录本身
    • 然后我们尝试运行构建.此时,没有其他源代码文件存在于目录中.所以构建会失败.但在此之前,它将下载依赖项.
    • 由于我们预计构建失败,我尝试了一种简单的技术来返回 0 并允许docker 继续执行
    • 这将加快后续构建流程,因为所有依赖项都已下载并且 docker 缓存了这一层.相比之下,Volume 挂载 gradle 缓存目录仍然是最好的方法.
    • 上面的例子还展示了多阶段docker镜像构建,这避免了多个 docker 构建文件.
    • First we try to copy the project's gradle files alone, like build.gradle, gradlew etc.,
    • Then we copy the gradle directory itself
    • And then we try to run the build. At this point, there is no other source code files exists in the directory. So build will fail. But before that it will download the dependencies. 
    • Since we expect the build to fail, I have tried a simple technique to return 0 and allow the docker to continue execution
    • this will speed up the subsequent build flows, since all the dependencies are downloaded and docker cached this layer. Comparatively, Volume mounting the gradle cache directory is still the best approach.
    • The above example also showcases multi-stage docker image building, which avoid multiple docker build files.

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆