FROM gradle:jdk8 as gradle
WORKDIR /app
COPY settings.gradle build.gradle ./
COPY module-core/build.gradle ./module-core/
COPY gradle ./gradle
RUN gradle build --no-daemon --info --stacktrace #make gradle download dependencies
COPY . .
RUN gradle :module-core:bootJar --no-daemon --info --stacktrace #should reuse the dependencies
As shown I copy the gradle configuration files without the source codes to make gradle download the dependencies, and I can make sure that gradle download a lot of dependencies through the log.
Then I copy the source codes and run the build again, I expect that gradle will use the cached depedencies , however I found it download them again.
Because the Gradle cache lives in the ~/.gradle on the host. When running in a Docker container that folder is going to be empty. You could mount that Gradle user home directory into the Docker container, but there are complications with that and it isn’t fully supported. However, there is preliminary work which will be available in Gradle 6.1 to make this possible.
When running in a Docker container that folder is going to be empty
At the first build time it is ok if the folder is empty, but after the first build. Docker should reuse the cached layer where the ~/.gradle should contain the jars.
This is only the case if you run multiple builds in the same container, or use persistent volumes between containers, otherwise, everything I spin up a new container that folder will be empty.
FROM node:10-alpine as node
WORKDIR /app
COPY package*.json ./
RUN npm install
ADD . .
RUN npm run build
The last line npm run build will reuse the node dependencies downloaded in the step npm install.
The only difference is that the node dependencies will be saved in the current directory while gradle dependencies will be put outside the current directory.
Ok, I think I understand what you are referring to now. You are indeed running multiple builds in the same container, and the later builds still download dependencies? Could you perhaps run those builds with --scan and share the build scan URLs?
It’s possible there are different semantics regarding user home directories when build a Docker image vs running a container.
One thing you might try is using an explicit Gradle user home directory by passing a location via -g. Try using the same location for both build invocations and see if that helps.
The image has VOLUME /home/gradle/.gradle. This was done because CI containers tend to be ephemoral and this gives you the option to mount them in a volume so it can be re-used between containers (and generally child images are meant to be a non-project specific image that is used for many projects, and thus avoids having dependencies for any particular project in the image).