Multi-Stage Spring Boot Dockerization Using Maven - spring-boot

Trying to get the multi-stage Spring Boot application Dockerfile that works.
The idea is to:
Build and package the project using mvn package command
Run the built .jar file
After some research, I found this article. It provides complete Dockerfile, but it does not work for me.
I modified the initial Dockerfile, and now it looks like this:
FROM maven:3.6.2-jdk-8-slim AS MAVEN_BUILD
COPY pom.xml /build/
COPY src /build/src/
WORKDIR /build/
RUN mvn -Dmaven.test.skip=true package -Ptest # This line does not work properly
FROM openjdk:8-jre
WORKDIR /app
COPY --from=MAVEN_BUILD /build/target/platform-0.0.1.jar /app/
ENTRYPOINT ["java", "-jar", "platform-0.0.1.jar"]
I created a docker-compose.yml that tries to build this Dockerfile:
[...]
api:
build:
context: .
dockerfile: Dockerfile
depends_on:
- mysql-db
ports:
- "8080:8085"
[...]
After running the docker-compose up --build -d command, I always get this error:
Am I missing something?
Running the mvn -Dmaven.test.skip=true package -Ptest command in the actual project folder works normally...

The problem was with my docker client installation. It somehow did not setup necessary permissions after installation. On other machines, this Dockerfile works fine.
Well, this was a lesson for some future times.

Related

H2 CSVRead gives FileNotFoundException

I have a Spring Boot application that uses JPA with H2. data.sql has the following content:
INSERT INTO artists
SELECT *
FROM CSVREAD('/usr/local/data/artists.csv’);
and that path works locally (though changed to a local directory). However when dockerized with the following image:
# Build stage
FROM maven:3.8.6-amazoncorretto-17 AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package -DskipTests
# Package state
FROM amazoncorretto:17-alpine
COPY --from=build /home/app/target/webusengus-0.0.1-SNAPSHOT.jar /usr/local/lib/webusengus.jar
COPY --from=build /home/app/src/main/resources/artists.csv /usr/local/data/artists.csv
EXPOSE 8080
ENTRYPOINT ["java","-jar","/usr/local/lib/webusengus.jar”]
on startup a java.nio.file.NoSuchFileException: /usr/local/data/artists.csv is thrown, but when exploring the image through docker export the file is in /usr/local/data/artists.csv
Given that docker is a superuser, I also don’t see how this could relate to file access?

My spring boot application was running fine but when I dockerized it I got File not Found error

I don't know what I'm getting this error when I dockerized my spring-boot application
this is my Dockerfile
enter image description here
First, I wonder is your application working on your IDE?
Second, I think you make sure to build and package.
It is not sure to exists a jar file in your target folder.
You always have to build and check by yourself.
Make the build process automatic.
How about using this Dockerfile?
FROM maven:3.8.6-openjdk-18-slim as MAVEN_BUILD
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn package -Dmaven.test.skip=true
FROM openjdk:18-alpine
WORKDIR /app
ARG JAR_FILE=*.jar
COPY --from=MAVEN_BUILD /build/target/${JAR_FILE} ./app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]
If maven or openjdk version not matched, check this site.
https://hub.docker.com/_/maven
https://hub.docker.com/_/openjdk
In your Spring Boot application, from what I can see your BookingController is missing. Make sure you have the file present and build your image accordingly.
For your Dockerfile, try to change add to ADD, as it seems your target files are not been copied into the image built.

How to natively build a servlet based Quarkus application using a web.xml as the deployment descriptor?

I'm setting up a simple servlet application using Quarkus. Where should I place the web.xml file and how should I deploy the application using the native build feature of Quarkus?
I have tried placing web.xml in project-name/src/main/resources/WEB-INF folder and natively built it using GraalVM docker image, but the built is not working. Dockerfile I used for the build is as of below.
Stage 1 : build with maven builder image with native capabilities
FROM quay.io/quarkus/centos-quarkus-maven:19.1.1 AS build
COPY src /usr/src/app/src
COPY pom.xml /usr/src/app
USER root
RUN chown -R quarkus /usr/src/app
USER quarkus
RUN mvn -f /usr/src/app/pom.xml -Pnative clean package
Stage 2 : create the docker final image
FROM registry.access.redhat.com/ubi8/ubi-minimal
WORKDIR /work/
COPY --from=build /usr/src/app/target/*-runner /work/application
RUN chmod 775 /work
EXPOSE 8080
CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
I expected the output to be "Welcome", but the actual output is "Not Found".
You can place web.xml file in the project-name/src/main/resources/META-INF directory to get it working.

Dockerfile that is used for building spring-cloud-dataflow-server image

I have downloaded the Spring cloud Dataflow server code from GitHub at https://github.com/spring-cloud/spring-cloud-dataflow. I am trying to understand how the docker image is build for this server. But I am unable to find dockerfile in this codebase.
Reference documentation section "Adding a Custom JDBC Driver" calls for modifying Pom.xml and rebuild with very little information. I need to use a custom jar and rebuild the image.
Already looked into this post https://github.com/spring-cloud/spring-cloud-dataflow/issues/2489 but I am trying to understand how the orginal image for Spring Dataflow server is built.
The Maven configuration to build the Spring Cloud Data Flow server is here
To build the docker image, you can run the following from your cloned repo (assuming you are on the latest):
./mvnw clean install -DskipTests
./mvnw docker:build -pl spring-cloud-dataflow-server
Thanks Gopinathan. I have used the below dockerfile instead of changing the POM.xml and rebuilding the docker image.
FROM mcr.microsoft.com/java/jdk:8u212-zulu-alpine as build
RUN apk add --update \
curl \
&& rm -rf /var/cache/apk/*
WORKDIR /workspace/app
RUN mkdir target
RUN curl -sS -o /workspace/app/target/spring-cloud-dataflow-server-2.1.2.RELEASE.jar https://repo.spring.io/release/org/springframework/cloud/spring-cloud-dataflow-server/2.1.2.RELEASE/spring-cloud-dataflow-server-2.1.2.RELEASE.jar
RUN curl -sS -o /workspace/app/target/mysql-connector-java-8.0.16.jar https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.16/mysql-connector-java-8.0.16.jar
RUN mkdir -p target/dependency && (cd target/dependency; jar -xf ../spring-cloud-dataflow-server-2.1.2.RELEASE.jar)
RUN cp /workspace/app/target/mysql-connector-java-8.0.16.jar /workspace/app/target/dependency/BOOT-INF/lib/
FROM mcr.microsoft.com/java/jdk:8u212-zulu-alpine
VOLUME /tmp
ARG DEPENDENCY=/workspace/app/target/dependency
COPY --from=build ${DEPENDENCY}/BOOT-INF/lib /app/lib
COPY --from=build ${DEPENDENCY}/META-INF /app/META-INF
COPY --from=build ${DEPENDENCY}/BOOT-INF/classes /app
RUN echo "$(ls -lR /app)"
ENTRYPOINT ["java","-cp","app:app/lib/*","org.springframework.cloud.dataflow.server.single.DataFlowServerApplication"]
dockerfile-from-image would help to reverse engineer from docker image.
Upvoted Ilyaperumal Gopinathan's answer, the best way is to build the project. The fabric8 maven docker plugin requires docker to be installed locally however - surely a lot of work to get to the 4 lines below.
This is the image produced by the 2.7.1 build -
FROM springcloud/baseimage:1.0.0
ENV LANG=C.UTF-8
COPY maven /
VOLUME ["/tmp"]
ENTRYPOINT ["java","-jar","/maven/spring-cloud-dataflow-server.jar"]
The spring cloud base image seems to be simply an Ubuntu base with Java 8 installed (https://github.com/spring-cloud/baseimage)?

Do not download all Maven dependencies on a Docker build

I'm trying to create a Dockerfile to then build a Maven project.
I wonder how to fix the Dockerfile and what command to then execute.
I would like to know how to run the build so that it does NOT download all the Maven dependencies every time it builds when the source code, sitting in the src/ directory, has NOT changed.
Here is my Dockerfile file:
FROM maven:3.3.9-jdk-8
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN cd /usr/src/app
ADD pom.xml /usr/src/app
RUN mvn dependency:resolve
ADD src /usr/src/app
RUN mvn package
ENTRYPOINT ["mvn"]
CMD ["package"]
Should I run the docker run --rm -it toolbox command or the docker build -t toolbox . command ?
Both of these above commands run fine, except that they both download all the Maven dependencies even if the source code has not been touched.
That's how Docker works. Every time you do docker run, it creates a new container which does not have any access to the files in the old container. So, it download all dependencies it requires. You can circumvent this by declaring an external volume. Looking at the Dockerfile of Maven, it declares a volume /root/.m2. So, you can use a directory in your host machine and attach it to this volume by -v option. Your Docker command would be,
`docker run -v <directory-in-your-host>:/root/.m2 <other-options-and-commands>
Every time you run a new docker run, Maven will look into your local directory before downloading the dependency.
However, my question is why don't you build your app first and use the resulting jar to create the docker images unless you have any specific reasons. You can create your own Dockerfile using java base image or simply use one of the docker-maven-plugin like spotify available out there. That makes your life a lot easier.

Resources