Docker unable to access jar file without docker-compose - java

as far as I know I only got this answer for my query, but unfortunately I do not have docker-compose.yml I am just trying with plain Dockerfile below is my dockerFile.
FROM openjdk:8-jre-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} ebiPorjectJava.jar
ENTRYPOINT ["java","-jar","/ebiProjectJava.jar"]
but build is getting successful, by below command.
docker build -t ebiproject .
but when I am trying to run the docker it says unable to access jar file
docker run -p 3000:3000 ebiproejct
but it says unable to access jar
I am running docker on windows and I have spring boot application to run
I updated with below one:
FROM openjdk:8-jre-alpine
VOLUME /tmp
ARG JAR_FILE
COPY ${JAR_FILE} /ebiProjectJava.jar
ENTRYPOINT ["java","-jar","/ebiProjectJava.jar"]
but now I am getting corrupted error:

ARG JAR_FILE
expects you to pass the path of the jar_file as docker run argument
Otherwise nothing will be copied to the place, thus java jar won't be able to run the jar.
Check this out: https://vsupalov.com/docker-env-vars/

In this situation you can go in your container with this command:
docker run --rm -it <container_name> <image_name> <command>
you can use bash, ash or sh as
and after entering the container, you can check, run, or any tests in that.

Related

Running Maven test in Docker container

I have a Spring boot application in a Docker container and when I run the command to execute tests I see that the app starts correctly but there is no test executed. Looks like the mvn test is completely ignored.
Below my docker commands:
docker build -t cygnetops/react-test -f Dockerfile.dev .
docker run cygnetops/react-test mvn test
Dockerfile.dev
FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
ADD /target/demoCI-CD-0.0.1-SNAPSHOT.jar app.jar
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
EXPOSE 5000
Entrypoints and commands are working together in a Docker container, if you specify an entrypoint, your command will be passed as an argument to the entrypoint, and if that entrypoint does nothing with the arguments passed to it, then the behaviour you are observing it totally normal.
The chapter "Understand how CMD and ENTRYPOINT interact" of the documentation provides a nice table explaining in depth how they interact.
In order to run you tests from that image, you could override the entrypoint when running you container:
docker run --entrypoint "" cygnetops/react-test mvn test
Note:
you will also have to install Maven, as it is not part of your base image
as you pointed, you will also need the POM and files of the Java project in order to run the tests, so you need to copy those sources in the image
So, add, in your Dockerfile, the lines:
COPY . .
RUN apk add --no-cache maven
If you want both to work, on the other hand, you will have to write your own entrypoint and make something from the command passed as arguments.
Here is an example:
entrypoint.sh, should be located at the same level as your Dockerfile:
#!/usr/bin/env sh
exec "$#" # execute what is passed as argument
java -Djava.security.egd=file:/dev/./urandom -jar /app.jar
Then, for your Dockerfile
FROM eclipse-temurin:17-jdk-alpine
VOLUME /tmp
RUN apk add --no-cache maven
COPY . .
COPY /target/demoCI-CD-0.0.1-SNAPSHOT.jar app.jar
COPY entrypoint.sh /usr/local/bin/
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 5000
Maybe a better solution is to create a docker file that runs a script instead of plain java. for example create a runner.sh file as follow:
#!/bin/bash
CMD="java -jar app.jar"
$CMD &
SERVICE_PID=$!
mvn test
wait "$SERVICE_PID"
and this will be your dockerfile
FROM maven:3.9.0-eclipse-temurin-11-alpine
COPY . .
RUN mvn install
COPY runner.sh /scripts/runner.sh
RUN ["chmod", "+x", "/scripts/runner.sh"]
ENTRYPOINT ["/scripts/runner.sh"]

Executing java command on ENTRYPOINT of Dockerfile doesn't recognize given ARG values

I have created a dockerfile to build and upload on DockerHub an image that will connect to a database and will create a table.
Dockerfile
FROM openjdk:11 as builder
EXPOSE 8080
WORKDIR application
ARG JAR_FILE=toDoAppWithLogin.jar
COPY $JAR_FILE application.jar
ARG SQL_PASSWORD
ARG SQL_USERNAME
ARG SQL_PORT
ARG SQL_SERVER
RUN java -Djarmode=layertools -jar application.jar extract
FROM openjdk:11
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/application/ ./
ENTRYPOINT ["java", "org.springframework.boot.loader.JarLauncher", "--my_sql.host=$SQL_SERVER", "--my_sql.port=$SQL_PORT", "--my_sql.username=$SQL_USERNAME", "--my_sql.password=$SQL_PASSWORD"]
I build the image by running the following command (it's build it successfully):
docker build -t nikspanos/cicd-pipeline:tag1 --build-arg SQL_USERNAME=user --build-arg SQL_PASSWORD=pass --build-arg SQL_PORT=0000 --build-arg SQL_SERVER=server .
Then I run the docker image to test it before I upload it on Docker registry
docker run nikspanos/cicd-pipeline:tag1
The first error I get:
java.sql.SQLNonTransientConnectionException: Cannot load connection class because of underlying exception: com.mysql.cj.exceptions.WrongArgumentException: Failed to parse the host:port pair '$SQL_SERVER:$SQL_PORT'.
I guess I don't pass the arguments correctly so they are not recognized. I have searched about it and many other answers include the ENV option but I would like to use the ARG only.
Aprreciate any suggestions on this matter.
You've got at least 3 things wrong here.
ARG values are scoped, and go out of scope when you start the next stage.
ARG values are for build time (building the image), for runtime (when you start the container from the image) you need to set an ENV.
Docker doesn't expand variables in RUN, CMD, or ENTRYPOINT. Instead you get the value injected as an environment variable. To expand the $var syntax to the value of the variable, you need a shell like /bin/sh. The json/exec syntax explicitly bypasses running your command with a shell.
The result looks like:
FROM openjdk:11 as builder
EXPOSE 8080
WORKDIR application
ARG JAR_FILE=toDoAppWithLogin.jar
COPY $JAR_FILE application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM openjdk:11
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/application/ ./
ARG SQL_PASSWORD
ARG SQL_USERNAME
ARG SQL_PORT
ARG SQL_SERVER
ENV SQL_PASSWORD=$SQL_PASSWORD
ENV SQL_USERNAME=$SQL_USERNAME
ENV SQL_PORT=$SQL_PORT
ENV SQL_SERVER=$SQL_SERVER
ENTRYPOINT java org.springframework.boot.loader.JarLauncher "--my_sql.host=$SQL_SERVER" "--my_sql.port=$SQL_PORT" "--my_sql.username=$SQL_USERNAME" "--my_sql.password=$SQL_PASSWORD"
I'd personally switch to running the entrypoint as a shell script so you can get back to the json syntax. That would allow other cli options to be passed in the CMD value. And that script could be
#!/bin/sh
exec java org.springframework.boot.loader.JarLauncher "--my_sql.host=$SQL_SERVER" "--my_sql.port=$SQL_PORT" "--my_sql.username=$SQL_USERNAME" "--my_sql.password=$SQL_PASSWORD" "$#"
Where the exec avoids leaving the /bin/sh as pid 1 which can mess with signals.
You then run into the next issue, you shouldn't be baking configuration settings like db hostnames, and especially passwords, into the image. Instead that becomes a runtime configuration when you run the container:
FROM openjdk:11 as builder
EXPOSE 8080
WORKDIR application
ARG JAR_FILE=toDoAppWithLogin.jar
COPY $JAR_FILE application.jar
RUN java -Djarmode=layertools -jar application.jar extract
FROM openjdk:11
WORKDIR application
COPY --from=builder application/dependencies/ ./
COPY --from=builder application/spring-boot-loader/ ./
COPY --from=builder application/application/ ./
COPY entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh" ]
Then you'd build it without any args and run it with the settings:
docker build -t nikspanos/cicd-pipeline:tag1 .
docker run -e SQL_USERNAME=user -e SQL_PASSWORD=pass -e SQL_PORT=0000 -e SQL_SERVER=server nikspanos/cicd-pipeline:tag1
I'd also recommend looking into secrets solutions for passing credentials since environment variables are easily exposed. Those would mount the credentials as a file or make them available from an external secrets server.

Exception when running Spring Boot app inside of Docker

I have a problem connecting to the config-server. I am not sure what am I doing wrong. I have configured server running in a docker container named "config-server" on port 8888.
http://config-server:8888. Will be trying the next url if available
2020-08-10 17:38:35.196 ERROR 11052 --- [ main] o.s.boot.SpringApplication : Application run failed
java.lang.IllegalStateException: Could not locate PropertySource and the fail fast property is set, failing
at org.springframework.cloud.config.client.ConfigServicePropertySourceLocator.locate(ConfigServicePropertySourceLocator.java:148) ~[spring-cloud-config-client-2.2.3.RELEASE.jar:2.2.3.RELEASE]
discovery-server bootstrap.yml
spring:
application:
name: discovery-server
cloud:
config:
uri: http://config-server:8888
fail-fast: true
retry:
max-attempts: 20
EDIT
config-server Dockerfile
FROM openjdk:11.0-jre
ADD ./target/config-server-0.0.1-SNAPSHOT.jar config-server-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java", "-jar", "/config-server-0.0.1-SNAPSHOT.jar"]
EXPOSE 8888
docker run -p 8888:8888 --name config-server 3deb982c96fe
Discavery-server is not running in docker. First I want to create its .jar file
Original question already answered in comments, answering the last point here for better formatting:
Jar file will be built in /target folder of your application everytime you run mvn clean install or gradle build. In order to run this in Docker you have to copy the jar file from your /target directory to the Docker container inner files, and then run it (java -jar nameOfYourJar.jar).
Name of your jar can be defined in maven/gradle settings but to keep your Dockerfile generic I suggest following Dockerfile:
FROM openjdk:11.0-jre
ARG JAR_FILE=/target/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","app.jar"]
with ARG JAR_FILE you save the path to any jar file (found in target) as JAR_FILE variable in docker and then you can copy it to your Docker inner files where it will be stored under the name app.jar.
ENTRYPOINT is the command that will be run on container start.
Place the Dockerfile next to the /target directory (so in root folder of your app) and run following command in terminal:
docker build -t springapp . && docker run --rm -d -p 8080:8080 springapp
Hope this clarifies everything.

Unable to access jarfile from docker run command for java maven project

Build docker images using docker file for maven project
When try running docker run getting error saying Unable to access jarfile.
Can some one assist on whats wrong with .
FROM openjdk:8-jre-alpine as release
RUN addgroup -g 1001 -S user1 && user1 -u 1001 -S user1 -G user1
WORKDIR /home/app
COPY --from=builder /home/app/service-1.0.0.jar .
RUN chown -R user1:user1 /home/app
USER user1
ENTRYPOINT ["java", "-jar" ,"/home/app/service-1.0.0.jar"]
but when i go for docker run with local config files as build mount
docker run -it --mount type=bind,source=D:/Java/service/docker/config,target=/home/app services
Unable to access jarfile /home/app/service-1.0.0.jar
Can someone assist on this or is something wrong i did??
I am not sure if you are looking for multistage docker build. If not, you need not use "COPY --from=builder" as it tires to copy the build artifact from your previous stage to this new stage. If it is a single stage docker build, you might just use the copy as follows -
COPY /home/app/service-1.0.0.jar .
Able to resolve the same, Issue was due to mound of config files not happened properly.
instead of docker run -it --mount type=bind,source=D:/Java/service/docker/config,target=/home/app services changes it to docker run -it --mount type=bind,source=D:/Java/service/docker/config/app.config,target=/home/app services which made service to load and work

gu No such file or directory

I'm building a docker image out of a micronaut application.
But whenever I run the docker build command
docker build -f Dockerfile -t micronaut .
I get this error
/bin/sh: /bin/gu: No such file or directory
Here's the content of my docker file anyway:
FROM oracle/graalvm-ce:20.0.0-java11 as graalvm
RUN $GRAALVM_HOME/bin/gu install native-image
COPY . /home/app/micronautguide
WORKDIR /home/app/micronautguide
RUN $GRAALVM_HOME/bin/native-image --no-server -cp build/libs/complete-*-all.jar
FROM frolvlad/alpine-glibc
RUN apk update && apk add libstdc++
EXPOSE 8080
COPY --from=graalvm /home/app/micronautguide/micronautguide /micronautguide/micronautguide
ENTRYPOINT ["/micronautguide/micronautguide", "-Xmx68m"]
Though by running gu command from the terminal works.
Your context does not contain RUN $GRAALVM_HOME/bin/gu . What is $GRAAL_VM_HOME? Whatever this variable is, it is set as null. Also, $GRAALVM_HOME/bin/gu needs to be part of docker image.
$GRAALVM_HOME does not exists in the oracle/graalvm-ce:20.0.0-java11 container. Thus, make suer to specify the right path. In this case it is /bin/gu
I think $GRAALVM_HOME is a variable you use in the local machine and gu tool is already installed and available at /bin in the docker image. So I have kept the $GRAALVM_HOME unchanged in the second build stage.
So, the Dockerfile should be like below,
FROM oracle/graalvm-ce:20.0.0-java11 as graalvm
RUN /bin/gu install native-image
COPY . /home/app/micronautguide
WORKDIR /home/app/micronautguide
RUN /bin/native-image --no-server -cp build/libs/complete-*-all.jar
FROM frolvlad/alpine-glibc
RUN apk update && apk add libstdc++
EXPOSE 8080
COPY --from=graalvm /home/app/micronautguide/micronautguide /micronautguide/micronautguide
ENTRYPOINT ["/micronautguide/micronautguide", "-Xmx68m"]

Categories