skip to Main Content

I am planning to use gradle as build tool with docker for containerizing spring boot applications.

I currently have one question regarding best practices/pros/cons from:
a. from general perspective as a best practice.
b. from CI /CD perspective.

I have understood that I can do it in three ways:

1. Do gradle build by running command on your host machine + then dockerize your spring boot app

eg:

/.gradlew build

docker build -f dockerfile...

2. Do gradle build inside dockerfile itself.

for 2, I got inspiration from these guys at dockercon(https://www.docker.com/blog/intro-guide-to-dockerfile-best-practices/).

eg:

FROM gradle:4.7.0-jdk8-alpine AS build
COPY --chown=gradle:gradle . /home/gradle/src
WORKDIR /home/gradle/src
RUN gradle build --no-daemon 

FROM openjdk:8-jre-slim

EXPOSE 8080

RUN mkdir /app

COPY --from=build /home/gradle/src/build/libs/*.jar /app/spring-boot-application.jar

ENTRYPOINT ["java", "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCGroupMemoryLimitForHeap", "-Djava.security.egd=file:/dev/./urandom","-jar","/app/spring-boot-application.jar"]

There are other articles as well

https://codefresh.io/docs/docs/learn-by-example/java/gradle/

https://codefresh.io/docker-tutorial/java_docker_pipeline/

here I would also like to point that for option 2 that:
a. I plan to use mount option from docker instead of rebuilding image again and again to reflect local changes.

b. I plan to leverage multistage builds, so that we can just discard heavy gradle input and just focus on jar in final output.

3. Use buildpacks, jib or spring boot build image command.

any ideas? If anyone has experienced any pros cons in this area please share.

2

Answers


  1. Chosen as BEST ANSWER

    After a lot of thought and research I have switched to buildpacks.

    Also, I have included image build process in build with maven plugin.

    Buildpacks are mature way of building docker images with all best practices and security in mind.

    Dockerfile is good option if you have a really really custom requirement that does not fit in ideal scenarios and requires custom development.

    Example of buildpacks: https://paketo.io/docs/howto/java/

    For this java buildpack you can configure:

    1. you can configure your ssl certificates
    2. jvm options
    3. remote debugging options
    4. JVM vendor switching
    5. Custom command launch
    6. and list goes on...

    Also you do not need to worry for all best practices (https://docs.docker.com/develop/develop-images/dockerfile_best-practices/), buildpacks handle that for you.

    In case of dockerfile, you might forget to apply standard practices to your docker image(when we are dealing with lot of services/images).

    So its another piece of code to maintain and ensure you follow all practices correctly.

    Also you can include buildpack in your builds as well, eg: you can use spring boot gradle or maven plugin ref: https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#build-image

    Ref: https://tanzu.vmware.com/developer/blog/understanding-the-differences-between-dockerfile-and-cloud-native-buildpacks/

    ref: https://cloud.google.com/blog/topics/developers-practitioners/comparing-containerization-methods-buildpacks-jib-and-dockerfile


  2. After almost 7 years of building Docker images from Gradle, long before Docker became a commonplace thing, I’ve never done option 2. I’ve done options 1 and 3, primarily 3.

    The problem with #1 is that you lose the information from your Gradle project that can be used to build the image, like the location of the jar file and the project name (there are several others). You end up redefining them on the command line, and the result could be very different.

    The problem with #2 is the loss of developer productivity and conflating responsibilities. I can’t imagine building a Docker image every time I made a change to the code. Gradle is a build tool, Docker is a delivery mechanism, and they have different goals.

    There are many articles that you can find online for building Docker images that apply equally well to Spring applications. Most notably:

    1. Use layers to avoid rebuilding code not changed.
    2. Use a Gradle Docker plugin to integrate Docker build within Gradle. I’m not sure if the Spring Boot plugin has integrated Docker build task now, if so, use that.
    3. Use a JRE as base instead of JDK if your code can live with that. Many projects don’t need JDK to run.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search