Docker缓存Gradle依赖性 [英] Docker cache gradle dependencies

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

问题描述

我正在尝试使用docker将Java Web应用程序部署到aws弹性beantalk,其想法是能够在本地运行容器以进行开发和测试,并最终使用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.

对于beantalk来说,这并不是什么大问题,但是对于试图在本地构建和运行的开发人员来说,这是一个大问题,因为这确实需要花费很多时间.

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项目中重复使用下载的依赖项.
    • gradle cache is loaded here as a volume. So subsequent builds will reuse the downloaded dependencies.
    • After this, we could have a Dockerfile to take this artifact and generate application specific image to run the application.
    • This way, the builder image is not required. Application build flow and Application run flow is separated out.
    • Since the gradle-cache volume is mounted, we could reuse the downloaded dependencies across different gradle projects.
    • 选项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将该层缓存.相比之下,批量安装gradle缓存目录仍然是最好的方法.
      • 以上示例还展示了多阶段docker映像构建,避免了多个docker build文件.
      • 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天全站免登陆