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.
CodePudding user response:
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:
- Use layers to avoid rebuilding code not changed.
- 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.
- Use a JRE as base instead of JDK if your code can live with that. Many projects don’t need JDK to run.