Search code examples
dockermavendockerfiledevopsdocker-maven-plugin

Unable to cache maven dependency in docker image


I am using the sh file which contains all the maven configuration, secret keys, maven command. when I run the container it downloads the dependency again and again everytime, it is unable to cache the dependency.

Here is how my Dockerfile looks like :

#MVN as build tool
FROM docker.hub.com/maven:3.5.3-jdk-8

#Settings.xml for downloading dependencies from nexus repository
ARG MVN_SETTINGS=settings.xml

#Maven project pom
ARG MVN_POM=pom.xml

#Defining the current working repository
WORKDIR /usr/src/app


#Coping the settings.xml into working directory
COPY ${MVN_SETTINGS} settings.xml

#Coping the pom.xml into working directory
COPY ${MVN_POM} pom.xml

#Download the package and make it cached in docker image
RUN mvn -B -f ./pom.xml -s settings.xml dependency:resolve-plugins dependency:resolve


#Coping the source code into working repository
COPY  src .

COPY  Test.sh .

#Execute permission
RUN chmod a+x Test.sh

#Entry point for docker container
CMD ./Test.sh

Here is the Test.sh file

#!bin/bash
mvn test -DtestSuite=src/test/resources/suites/Suite.xml

When I create the docker image and run the container it downloads the dependency, again and again, every time I run it.


Solution

  • What you want is not possible - at least using "regular" Docker and Dockerfile - see this question for an explanation.

    You can however achieve the desired effect using an experimental Dockefile syntax to enable caching for RUN statement:

    # syntax = docker/dockerfile:1.0-experimental
    FROM docker.hub.com/maven:3.5.3-jdk-8
    
    ARG MVN_SETTINGS=settings.xml
    ARG MVN_POM=pom.xml
    
    WORKDIR /usr/src/app
    
    COPY ${MVN_SETTINGS} settings.xml
    COPY ${MVN_POM} pom.xml
    RUN --mount=type=cache,target=/root/.m2 mvn -B -f ./pom.xml -s settings.xml dependency:resolve-plugins dependency:resolve
    
    COPY src .
    COPY Test.sh .
    RUN chmod a+x Test.sh
    CMD ./Test.sh
    

    The above Dockerfile will enable caching of /root/.m2 directory. The command will still run every time, but the dependencies will not be redownloaded. That said, this Dockerfile will not work with "regular" Docker. It requires BuildKit.

    I would also recommend using BuildX plugin and building the image with docker buildx build to allow for easy switching between build engines without setting and unsetting an environmental variable.