How to reduce my java/gradle docker image size?

With Docker 17.05+ you can use multi-stage builds.

"With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image."

So your Dockerfile could look like this:

#
# first stage (build)
#
FROM openjdk:8 as build

ADD . /usr/share/app-name-tmp

WORKDIR /usr/share/app-name-tmp

RUN ./gradlew build && \
    mv ./build/libs/app-name*.jar /usr/share/app-name/app-name.jar

#
# second stage. use alpine to reduce the image size
#
FROM openjdk:8-jre-alpine

WORKDIR /usr/share/app-name

COPY --from=build /usr/share/app-name/app-name.jar .

EXPOSE 8080

RUN chmod +x ./docker-entry.sh

ENTRYPOINT [ "./docker-entry.sh" ]

This way you only keep the jar and all the unnecessary files are not included in the final image.


I am really confused about your image size. I have typical Spring Boot applications offering a REST service including an embedded servlet container in less than 200MB! It looks like your project dependencies can and should be optimised.

Docker Image

The openjdk:8 (243MB compressed) can be replaced by one with a reduced Alpine unix image like openjdk:8-jdk-alpine (52MB) as a base image but if you don't need compiler capabilities (e.g. don't use JSPs) you may also go for openjdk:8-jre-alpine (42MB) which includes the runtime only, have a look into Docker Hub. I use that for Spring Boot based REST services working great.

Java Dependencies

The Java dependencies needed for compile and runtime have to be included but you may have unused dependencies included:

  • check your dependencies, are the current compile/runtime dependencies really used or maybe can be removed or moved to test, see Gradle Java Plugin
  • some dependencies have a lot of transitive dependencies (display using gradle dependencies), check out for unnecessary ones and exclude them if unused, see Gradle Dependency Management. Be sure to do integration tests before applying finally, some transitive dependencies are not well documented but may be essential!