Docker how to recompile jar file with maven - java

I am new to docker, and I am trying to setup docker for spring boot project.
Here is my Dockerfile
FROM maven:3.6.3-jdk-11-slim AS build
WORKDIR usr/src/springboot
COPY . ./
RUN mvn install
RUN mvn clean package
#
# Package stage
#
FROM openjdk:11-jre-slim
ARG JAR_NAME="springboot-0.0.1-SNAPSHOT"
WORKDIR /usr/src/springboot
EXPOSE 8080
COPY --from=build /usr/src/springboot/target/${JAR_NAME}.jar ./springboot.jar
CMD ["java","-jar", "./springboot.jar"]
Which works completely fine and I can access hello world from localhost:8080
But my confusion is how to make any changes in java file reflect in the docker container? how do I recompile the .jar file.
I tried something like docker exec -it strange_shaw "mvn clean package"
But it throws error exec: "mvn clean package": executable file not found in $PATH: unknown

when you are using double FROM instruction inside your Dockerfile , Docker will keep only the latest FROM and use the previous FROM to build the next one.
So it is simple to find this error because FROM maven:3.6.3-jdk-11-slim AS build only used to build the next step FROM openjdk:11-jre-slim and will be removed from the final image(this strategy used to minimize the docker image size).
I hope that give you a clear idea about Dockerfile with multiple stage.

Build your jar outside after your Dockerfile will be like that:
FROM openjdk:11-jre-slim
ARG JAR_NAME="springboot-0.0.1-SNAPSHOT"
WORKDIR /usr/src/springboot
EXPOSE 8080
COPY /usr/src/springboot/target/${JAR_NAME}.jar ./springboot.jar
CMD ["java","-jar", "./springboot.jar"]

The issue was that maven was not installed within the container. So I changed my Dockerfile to
FROM openjdk:11
ARG JAR_NAME="springboot-0.0.1-SNAPSHOT"
WORKDIR /usr/src/springboot
EXPOSE 8080
#COPY --from=build /usr/src/springboot/target/${JAR_NAME}.jar ./springboot.jar
#CMD ["java","-jar", "./springboot.jar"]
RUN apt-get update; apt-get install curl -y
ARG MAVEN_VERSION=3.6.3
# 2- Define a constant with the working directory
ARG USER_HOME_DIR="/root"
# 4- Define the URL where maven can be downloaded from
ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries
# 5- Create the directories, download maven, validate the download, install it, remove downloaded file and set links
RUN mkdir -p /usr/share/maven /usr/share/maven/ref \
&& echo "Downloading maven" \
&& curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \
\
&& echo "Unziping maven" \
&& tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \
\
&& echo "Cleaning and setting links" \
&& rm -f /tmp/apache-maven.tar.gz \
&& ln -s /usr/share/maven/bin/mvn /usr/bin/mvn
# 6- Define environmental variables required by Maven, like Maven_Home directory and where the maven repo is located
ENV MAVEN_HOME /usr/share/maven
ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2"
This will install maven inside the container and set $PATH
docker run -it -v "$(pwd)":/usr/src/springboot -p 8080:8080 spring-boot-app
Run above command to start container and map your project folder to container folder and local port to container port. So both are in sync if you do any changes in project.
docker exec -it <container_name> mvn verify
Above command will create the .jar file. Restart the container.
docker exec -it <container_name> java -jar target/<file_name>.jar
Will execute the jar file in port 8080 and will be accessible in your localhost:8080

Related

Tweak Any Errors with Docker Build for Maven-3.6.3 and Java SDK 8 Application

New to the java community, and would appreciate all of the help that I can get with my Dockerfile and Docker Compose setup.
These are the requirements of my project.
Use Maven 3.6.3 and Java 8 SDK,
create a workdir named /app
create a non root user with root permissions (max -777)
install basic linux tools and utilities
change to the root folder as a root user and cd into .m2/settings.xml and edit it with the code below.
Additionally, I need to copy over the pom.xml, the /target, the /src, and settings.xml and the app dir itself as illustrated in my attempt below.
And then run and execute this entire application as a non-root user with root permissions to create, delete, and update files and dirs in the root dir and throughout /app for the build with mvn.
# Custom image from Maven on DockerHub
# Language: dockerfile
FROM maven:3.6.3-amazoncorretto-8
# Set the working dir
WORKDIR /app
# Create a non root user
ARG USERNAME=jefferson
ARG USER_UID=1000
ARG USER_GID=$USER_UID
# Add linux dependenciesq
RUN yum install wget -y
RUN yum install shadow-utils -y
# Create the user
RUN groupadd --gid $USER_GID $USERNAME \
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
&& yum install sudo -y \
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
&& chmod 777 /etc/sudoers.d/$USERNAME \
&& sudo groupadd docker \
&& sudo usermod -aG docker $USERNAME \
&& newgrp docker
# Change to the root folder and edit the settings.xml for Maven
WORKDIR /root/.m2
RUN rm -rf settings.xml
RUN echo '<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0" \
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" \
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 \
http://maven.apache.org/xsd/settings-1.0.0.xsd"> \
</settings>' >> settings.xml
WORKDIR /app
COPY . ./
USER $USERNAME
# Run the application
CMD ["mvn", "clean", "verify", "-Pcargo.run", "-X"]
version: '1.0'
services:
app:
build: .
command: sh -c "mvn clean verify && mvn -Pcargo.run -X"
ports:
- 3100:3100
working_dir: /app
volumes:
# give absolute path of the workdir app working_dir
- .:/app
# give the absolute bath of src starting at app
- ./src:/app/src
# give the absolute path of target
- ./target:/app/target
# give the absolute path of the maven repo
- ~/.m2:/root/.m2
# give thepom.xml
- ./pom.xml:/app/pom.xml
That being said the docker compose up command should both build and run the container on port 3100. Can somebody give me a push in the right direction?

Unable to create docker container with docker command

i am building multi module springboot application and i want to setup docker environmenta, but unable to build container, can someone please help me to solve this issue.
My Docker file is mentioned below.
FROM openjdk:8-jdk
RUN apt-get update && apt-get install -y unzip
MAINTAINER zaihamm
COPY . .
WORKDIR /app/orderme
RUN curl -L https://services.gradle.org/distributions/gradle-7.1-bin.zip -o gradle-
7.1-bin.zip
RUN unzip gradle-7.1-bin.zip
ENV GRADLE_HOME=/app/orderme/gradle/gradle-7.1
ENV PATH=$PATH:$GRADLE_HOME/bin
RUN gradle --version
RUN ./gradlew :admin-service:build -x test
ENTRYPOINT ["java", "-jar","/admin-service/build/libs/admin-service.jar"]
when i run docker build -t orderme ./ its giving error
Unzip do not create extra "gradle" directory - line 8 should look like:
ENV GRADLE_HOME=/app/orderme/gradle-7.1

How to install java in container while writing it in Dockerfile?

I am naive in software development. I want to run a jar file from Dkron Scheduler using cron job. I am running dkron in docker(using docker-compose up). I am passing "command": "java --version" to see if I can run java from Dkron. As docker do not have java installed I changed the dockerfile.hub file to this:
FROM alpine
LABEL maintainer="Victor Castell <victor#victorcastell.com>"
RUN set -x \
&& buildDeps='bash ca-certificates openssl tzdata' \
&& apk add --update $buildDeps \
&& apk add openjava8 #add this line to install java
&& rm -rf /var/cache/apk/* \
&& mkdir -p /opt/local/dkron
ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk #add this line to install java
ENV PATH $PATH:$JAVA_HOME/bin #add this line to install java
EXPOSE 8080 8946
ENV SHELL /bin/bash
WORKDIR /opt/local/dkron
COPY dkron .
COPY dkron-* ./
ENTRYPOINT ["/opt/local/dkron/dkron"]
CMD ["--help"]
When I again do docker-compose up it do not give any error, still on passing "command": "java --version" by json through UI, dkron shows error - exec : "java" : executable file not found in $PATH.
What can I do to resolve it?
Thanks in advance.
I was able to create JVM in docker container using dkron as the base image, (publically available) and build another image on top of it.
Here is dockerfile I created for running java application
FROM dkron/dkron
WORKDIR /root/hello-world
COPY hello.java /root/hello-world
RUN apk add openjdk8
ENV JAVA_HOME /usr/lib/jvm/java-1.8-openjdk
ENV PATH $JAVA_HOME/bin:$PATH
RUN javac hello.java
Then I build image. Let id be xxx
Then I ran the image and build dkron server as
docker run -p 8080:8080 xxx agent --server --bootstrap-expect=1 --node-name=node1
Try this file
FROM alpine
LABEL maintainer="Victor Castell <victor#victorcastell.com>"
RUN set -x \
&& buildDeps='bash ca-certificates openssl tzdata' \
&& apk add --update $buildDeps \
&& apk add openjdk8 \
&& rm -rf /var/cache/apk/* \
&& mkdir -p /opt/local/dkron
ENV JAVA_HOME=/usr/lib/jvm/java-1.8-openjdk
ENV PATH="$JAVA_HOME/bin:${PATH}"
EXPOSE 8080 8946
ENV SHELL /bin/bash
WORKDIR /opt/local/dkron
COPY dkron .
COPY dkron-* ./
ENTRYPOINT ["/opt/local/dkron/dkron"]
CMD ["--help"]
alpine package doesn't have openjava8 packages.
Edit: Update ENV variables

Include local Maven m2 repo in Dockerfile during mvn package stage?

How can I include the local machine ~/.m2/repository in the mvn dependency:resolve stage of docker build? There is no -v option for docker build. Is this possible with just docker build to be compatible with our existing build pipeline (only a solitary Dockerfile is allowed)? This answer didn't help.
Current Dockerfile:
FROM maven:3.6.2-jdk-11 AS maven
WORKDIR /tmp/
# Set the local repository to /tmp/.m2/repository
RUN echo \
"<settings xmlns='http://maven.apache.org/SETTINGS/1.0.0\' \
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' \
xsi:schemaLocation='http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd'> \
<localRepository>/tmp/.m2/repository</localRepository> \
<interactiveMode>true</interactiveMode> \
<usePluginRegistry>false</usePluginRegistry> \
<offline>false</offline> \
</settings>" \
> /usr/share/maven/conf/settings.xml;
# TODO: How to perform -v ~/.m2/:/tmp/.m2/ but only using `docker build`?
COPY pom.xml /tmp/
RUN mvn dependency:resolve
RUN mvn dependency:resolve-plugins
COPY src /tmp/src/
RUN mvn package
FROM openjdk:11-jre-slim
EXPOSE 8080
RUN apt update
RUN apt -y install curl
WORKDIR /usr/app
ENV TARGET="<target name>.jar"
COPY --from=maven "/tmp/target/$TARGET" .
CMD ["java", "-jar", "$TARGET"]
And of course this doesn't work:
Update: I'm able to mount a folder pointing to the local .m2 repo and copy the whole folder into the docker image. However, now I cannot make mvn use that local repo.
Then
COPY pom.xml /tmp/
RUN mvn -o -s /usr/share/maven/conf/settings.xml dependency:resolve -X
results in the error:
Cannot access central (https://repo.maven.apache.org/maven2) in offline mode and the artifact com.myapp:somename:pom:1.0.4 has not been downloaded from it before.
An idea, that you can do is caching the maven dependencies in the docker. You can make use of mvn dependency-offline (https://maven.apache.org/plugins/maven-dependency-plugin/), doing the dependency-offline maven resolve the dependencies needed in preparation for going offline and reuse them as long as the pom.xml still be the same

Docker – Compile maven project inside docker container & run it from there

I have a project running Vue & Spring Boot that I need to create a docker-compose.yml file to run mvn clean install to generate the .jar, and then build a "new" image from another Dockerfile with that said .jar inside the docker container.
This is the Dockerfile that needs to be run once the mvn clean install is completed:
FROM java:8
ENV WKHTML_VERSION 0.12.4
# Builds the wkhtmltopdf download URL based on version numbers above
ENV DOWNLOAD_URL "https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTML_VERSION}/wkhtmltox-${WKHTML_VERSION}_linux-generic-amd64.tar.xz"
RUN apt-get update && \
apt-get install -y --no-install-recommends wget && \
wget $DOWNLOAD_URL && \
tar vxf wkhtmltox-${WKHTML_VERSION}_linux-generic-amd64.tar.xz && \
cp wkhtmltox/bin/wk* /usr/local/bin/ && \
cp wkhtmltox/lib/* /usr/local/lib/ && \
rm wkhtmltox-${WKHTML_VERSION}_linux-generic-amd64.tar.xz
# #see https://spring.io/guides/gs/spring-boot-docker/
COPY server/target/redo-server-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"]
So the build steps need to be something like this:
Install node + maven / pull those images
Install postgresql & pull that image
Run mvn clean install & generate .jar
Build new image from abovementioned Dockerfile and run it
I am new to docker-compose so I am having troubles setting this up in the correct execution order.
The reason I need to do this is due to a problem with the production pipeline not having node or npm, which is needed to run the full maven application (Vue.js and Spring Boot app), which is why it needs to be compiled from inside the Docker container
It would be greatly appreciated if anyone could point me in the right direction, let alone – is this possible to do?
Solved by writing a multi-step build as my Dockerfile. I am installing node as a dependency in the client's pom.xml file.
# Install maven and copy project for compilation
FROM maven:latest as builder
COPY pom.xml /usr/local/pom.xml
COPY server /usr/local/server
COPY client /usr/local/client
WORKDIR /usr/local/
RUN mvn clean install
FROM openjdk:8
ENV WKHTML_VERSION 0.12.4
# Builds the wkhtmltopdf download URL based on version numbers above
ENV DOWNLOAD_URL "https://github.com/wkhtmltopdf/wkhtmltopdf/releases/download/${WKHTML_VERSION}/wkhtmltox-${WKHTML_VERSION}_linux-generic-amd64.tar.xz"
RUN apt-get update && \
apt-get install -y --no-install-recommends wget && \
wget $DOWNLOAD_URL && \
tar vxf wkhtmltox-${WKHTML_VERSION}_linux-generic-amd64.tar.xz && \
cp wkhtmltox/bin/wk* /usr/local/bin/ && \
cp wkhtmltox/lib/* /usr/local/lib/ && \
rm wkhtmltox-${WKHTML_VERSION}_linux-generic-amd64.tar.xz
COPY --from=builder /usr/local/redo/server/target/server-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java", "-Djava.security.egd=file:/dev/./urandom","-jar","app.jar"]

Categories

Resources