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

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)?

Related

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.

Unable to run './mvnw clean install' when building docker image based on "openjdk:8-jdk-alpine" for Spring Boot app

I would like to build a Spring Boot app using the maven wrapper provided by spring.io.starter inside a docker container.
My Dockerfile is:
FROM openjdk:8-jdk-alpine
# install bash --> commented because I just need /bin/sh which is already provided by the base image
#RUN apk add --no-cache bash
ENV APP_DIR /app
ENV APP app.jar
WORKDIR ${APP_DIR}
COPY . ${APP_DIR}
# ===> HERE THE PROBLEM
RUN /bin/sh -c "./mvnw clean install"
ENTRYPOINT ["java","-jar","chicowa-app.jar"]
EXPOSE 8080
I have this error:
/bin/sh: ./mvnw: not found
After making some researches I still don't find a solution.
My docker version
Docker version 18.06.1-ce, build e68fc7a on Windows10 pro
Thanks a lot for your help.
EDIT
A solution would be to install maven directly with a RUN apk add --no-cache maven but I would like to minimize as possible the image' size.
We were experimenting this issue only on Windows 10 and were able to solve this issue on just applying dos2unix
dos2unix mvnw
I have the same issue when build Dockerfile in Window 10.
This because mvnw file contains CRLF (\r\n) at the end of line. I open it with Notepad++ and use Find \r\n and Replace with \n (with Extended (\n, \r, ...) checked). You can use dos2unix tool to convert as #Juanan said above.
After that, the build run with no problem.
Unless you are running the script in the exact location that the file mvnw is located, it won’t work.
If your PATH is set correct, and Maven was installed in a suitable location, simply removing the “./“ in front of the command will suffice.
RUN /bin/sh -c “mvnw clean install”
If mvnw is NOT in your PATH, you can specify the full path in your script (but recognize that Maven is likely to call other things that would want the same PATH changes).
if you have already maven configured then you may run the following:-
mvn clean install
It will build the docker image seamlessly.
If you are using windows git may change the line ending of the mvnw file to CRLF. If you open the file with any text editor and save it to LF it will probably work.
use
RUN chmod +x mvnw
before using
./mvnw clean install
it'll make your mvnw file executable
The problem can also be fixed without bothered with line endings or path variables even on Windows10.
Just include Maven to your Dockerfile and run the maven commands via this:
Here is an example Dockerfile:
FROM maven:3.8.1-openjdk-17-slim AS builder # <-- Include Maven
WORKDIR /app
COPY pom.xml ./
COPY src ./src
RUN mvn clean install
# Second stage: Minimal runtime environment
FROM eclipse-temurin:17-jre-jammy
WORKDIR /app
# copy jar from the first stage
COPY --from=builder /app/target/*.jar /app/app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
After using this approach, I solved this problem. Hope this helps...
This is working solution as I don't find anywhere this solution:
mvnw -version
error:
java.security.InvalidAlgorithmParameterException: the trustAnchors parameter must be
non-empty
Root Cause:
maven public certificate is missing in java trust store
Solutions:
download - repo.maven.apache.org leaf certificate from https://repo.maven.apache.org and save it as repo_maven.cer file in base64 format
Install the repo_maven.cer into to cacerts (truststore)
keytool -import -keystore "...\openjdk-8u41\jre\lib\security\cacerts" -file "repo_maven.cer" -alias maven
Output:
mvnw -version
Apache Maven 3.8.1 (05c21c65bdfed0f71a2f2ada8b84da59348c4c5d)

Docker copy doesn't seem to work with stopped container and wildcard

I'm building a maven project inside a docker container:
docker run build-image "mvn clean package -f ./pom.xml"
The source and workdir in the Dockerfile for "build-image" are located at /src/ (having two subfolders with each containing one submodule with pom.xml, parent pom at /src/pom.xml)
When the build is finished, the container exits. Then, I want to extract the build artifacts:
docker cp <container-id>:/src/module1/target/*.war ./
I get an error:
Error response from daemon: Could not find the file /src/<module1>/target/*.war in container silly_nobel
When I specify the file without using the wildcard:
docker cp <container-id>:/src/<module1>/target/<module1>##0.1.0-SNAPSHOT.war ./
it succeeds..
Is this intended behaviour or a bug? I googled a bit but could not find a similar post with that problem. docker version is 18.02.0-ce, build fc4de44
Best regards
docker cp does not support wildcards at the moment (github discussion)
But you can get what you want by using multi stage builds. In multi stage builds you can use COPY which allows wildcards.
This is a short example:
FROM alpine as builder
RUN touch foo.txt
RUN touch bar.txt
FROM alpine
COPY --from=builder /*.txt ./
Build an run image:
$ docker build -t foobar .
$ docker run foobar ls
bar.txt
bin
dev
etc
foo.txt
...

I am trying to perform mvn install from Dockerfile but it is not working says mvn not found

I am trying to perform "mvn install" to create war file from Dockerfile. Bellow is the Dockerfile
FROM scratch
FROM ubuntu:16.04
RUN mkdir /opt/java8
RUN mkdir /opt/tomcat8
RUN mkdir /opt/maven3
ENV JAVA_HOME /opt/java8
ENV CATALINA_HOME /opt/tomcat8
ENV PATH $PATH:$JAVA_HOME/bin:$CATALINA_HOME/bin:$M2_HOME/bin
ADD jdk1.8.0_112 /opt/java8
ADD apache-tomcat-8.0.38 /opt/tomcat8
WORKDIR /home/veni/git/M_UserTP
RUN mvn install
WORKDIR /home/veni/git/M_UserTP/target
RUN mv M_UserTP.war
/home/veni/Documents/dhaval_bhoot/docker_images/tomcat1
ADD M_UserTP.war /opt/tomcat8/webapps
EXPOSE 8080
CMD ["catalina.sh", "run"]
I also added the path of bin directory of maven in PATH environment variable.
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/home/veni/Documents/apache-maven-3.3.9/bin/
This path I set from root user in my machine, I also added same path in PATH variable as normal user already.
So now I exit from root user and come back by sudo su to be root user and check PATH variable, it has not path of maven
So when I make docker build of image I get the bellow error
/bin/sh: 1: mvn: not found
The command '/bin/sh -c mvn install' returned a non-zero code: 127
Given that you want to run your application in a Tomcat 8 Docker container:
Your maven project should be laid out like:
M_UserTP
+ Dockerfile
+ pom.xml
+ src
+ target
This is a standard maven layout plus your Dockerfile.
Ensure that your pom.xml contains the following finalName defined in it:
<build>
<finalName>${project.artifactId}</finalName>
...
</build>
Your Dockerfile can be really simple:
FROM tomcat:8.0
COPY target/M_UserTP.war $CATALINA_HOME/webapps/
(Note how the finalName is used by the Dockerfile)
To build it, execute:
mvn clean install && docker build . -t Bhoot/M_UserTP
You can use what ever -t tag that you want.
It will take some time the first time that you do this while the standard Tomcat 8 image is downloaded.
Now you can run it:
docker run --detach --publish 8080:8080 Bhoot/M_UserTP
You don't really want to build your WAR file in the docker image. This will suck all the maven repository components used by maven to build your application into the image. This space is not recoverable as images will only ever grow - they never shrink again.
Have you considered using a maven:onbuild image in conjunction with a multi-stage build for this?
An example of such a usage (with a Spring Boot application) is available here: https://github.com/anokun7/docker-springframework/blob/master/Dockerfile
Your container have its own filesystem.
So the mvn binary available on your system, is not available on a base ubuntu image.
You should install it first in your container (with a RUN apt-get install..)
You will then be able to use it in the next RUN
Try getting inside your container (after commenting out maven layer and everything below) and type which mvn. This will display the absolute path of the maven binary. Then use that absolute path inside your Dockerfile instead of just mvn.
Example:
mvn -> /opt/maven/bin/mvn

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