Corrupt jar in minikube - java

I try to run my spring-boot application in the minikube from local docker image.
$ eval $(minikube docker-env)
$ docker build -t built_name .
$ kubectl run serviceName --image=image_name:latest --image-pull-policy=Never
My Dockerfile:
FROM registry.access.redhat.com/redhat-openjdk-18/openjdk18-openshift
ARG jarFinal
ENV LC_ALL=en_US.utf8
COPY --chown=185:0 ${jarFinal} app.jar
COPY --chown=185:0 entrypoint.sh /entrypoint.sh
COPY --chown=185:0 version.json /version.json
RUN chmod +x /entrypoint.sh
EXPOSE 8080
ENTRYPOINT [ "/entrypoint.sh" ]
CMD java -Xmx256m -jar app.jar
After this i see in the kubernets pods logs:
Error: Invalid or corrupt jarfile app.jar
But when i tried to start this jar locally, with 'RUN java -Xmx256m -jar app.jar', its starting successfully. What i do wrong? Thanks.
UPD: I tried to start image with local docker (docker run) and all ok, then i tried the same in minikube with minikube docker (minikube ssh -> docker run), and I get the same error 'corrupt jar'...

Problem solved!
$ docker save myImage | (eval $(minikube docker-env) && docker load)
$ kubectl ssh 'docker tag myImage myTag'
$ kubectl run ServiceName --image=myTag --image-pull-policy=Never
'docker build' crashed my image..

Related

Use cp in entrypoint for docker run

There is Dockerfile
FROM openjdk:11.0.12-jre-slim
COPY target/app.jar /app.jar
COPY configs configs
ENTRYPOINT ["java","-jar","/app.jar"]
In folder configs contains json configs for java application.
The build docker command is:
docker build --build-arg -f ~/IdeaProjects/app --no-cache -t app:latest
And the run command is:
docker run --entrypoint="cp configs var/opt/configs/ && java -jar app.jar" app:latest
Let's omit the ability to copy configs in the Dockerfile via COPY command. Unfortunately, this must be done using --entrypoint.
An error occurs when the docker run command was executed:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: exec: "cp configs var/opt/configs/ && java -jar app.jar": stat cp configs var/opt/configs/ && java -jar app.jar: no such file or directory: unknown.
Could you explain why the error occurred in this case?
I would do this with an entrypoint wrapper script. A Dockerfile can have both an ENTRYPOINT and a CMD; if you do, the CMD gets passed as arguments to the ENTRYPOINT. This means you can make the ENTRYPOINT a shell script that does first-time setup, then ends with exec "$#" to replace itself with the CMD.
#!/bin/sh
# docker-entrypoint.sh
# copy the configuration to the right place
cp configs var/opt/configs/
# run the main container command
exec "$#"
In the Dockerfile, make sure to COPY the script in (it should be checked in to source control as executable) and set it as the ENTRYPOINT.
...
COPY docker-entrypoint.sh .
ENTRYPOINT ["./docker-entrypoint.sh"] # must be JSON-array syntax
CMD ["java", "-jar", "/app.jar"] # what was previously ENTRYPOINT
When you run the container it's straightforward to replace the CMD, so you can double-check that this is doing the right thing by running an interactive shell in place of the java application.
docker run -v "$PWD/alt-configs:/configs" --rm -it my-image sh
If you do need to override the command like this at docker run time, the command you show uses && to run two commands consecutively. This needs to run a shell to be understood correctly, and in this context you need to manually provide a /bin/sh -c wrapper.
I would still recommend changing ENTRYPOINT to CMD in your Dockerfile; then you could run a relatively straightforward
docker run \
... \
-v "$PWD/alt-configs:/configs" \
my-image \
/bin/sh -c 'cp configs var/opt/configs && java -jar /app.jar'
If you use --entrypoint, it only takes the first word out of this command, and it is a Docker options so it needs to come before the image name. I'd recommend designing your image to avoid needing this awkward construct.
docker run \
... \
-v "$PWD/alt-configs:/configs" \
--entrypoint /bin/sh \
my-image \
-c 'cp configs var/opt/configs && java -jar /app.jar'
Your proposed command is having problems because it's trying to pass the entire command, including the embedded spaces and shell operators, as a single word, but that causes the OS-level process handling to try to look for an executable file with spaces and ampersands in the filename, hence the "no such file or directory" error.

Docker how to recompile jar file with maven

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

Docker - Run Wildfly standalone

I have a Ubuntu server with a WildFly standalone installation configured, here i have a Java app that is accesible on port 80, i want to dockerize it. When create the container, i'm copying the entire WildFly directory from my local storage to the container, when i run the command docker run -d --name dej_website -p 80:80 wildfly_dej_website:2.0 the container start, but when try to access in my local machine localhost doesn't works.
What am i doing wrong? How can i do to access to this container, with the configured server?
This is my dockerfile
FROM centos
#INSTALL JAVA
RUN yum -y install java-11-openjdk
RUN java -version
RUN mkdir /opt/DEJ_Wildfly/
#SET OPT AS WORK DIRECTORY
WORKDIR /opt/DEJ_Wildfly/
#COPY WILDFLY SERVER FILES
COPY wildfly-11.0.0.Final .
#DEFINE ENVIRONMENT VARIABLE
ENV JBOSS_HOME /opt/DEJ_Wildfly/wildfly-11.0.0.Final/
#EXECUTE SH FILE
CMD JBOSS_HOME/bin/standalone.sh -b=0.0.0.0
CMD tail -f /var/log/lastlog
#EXPOSE 80
This is the log of docker build --tag wildfly_dej_website:2.0 . command:
Sending build context to Docker daemon 597.4MB
Step 1/9 : FROM centos
---> 300e315adb2f
Step 2/9 : RUN yum -y install java-11-openjdk
---> Using cache
---> f333f6149e02
Step 3/9 : RUN java -version
---> Using cache
---> 0110143899c7
Step 4/9 : RUN mkdir /opt/DEJ_Wildfly/
---> Running in 88bc6f0632c1
Removing intermediate container 88bc6f0632c1
---> c0ab7cc8a364
Step 5/9 : WORKDIR /opt/DEJ_Wildfly/
---> Running in 84705355ac2c
Removing intermediate container 84705355ac2c
---> 6986f8229cb0
Step 6/9 : COPY wildfly-11.0.0.Final .
---> 3caf8ec0e5d0
Step 7/9 : ENV JBOSS_HOME /opt/DEJ_Wildfly/wildfly-11.0.0.Final/
---> Running in b5f649e4e2e0
Removing intermediate container b5f649e4e2e0
---> 27d775c3d0cb
Step 8/9 : CMD JBOSS_HOME/bin/standalone.sh -b=0.0.0.0
---> Running in c7ffddb4bcdf
Removing intermediate container c7ffddb4bcdf
---> 533d3836f94d
Step 9/9 : CMD tail -f /var/log/lastlog
---> Running in f92aca5a63ba
Removing intermediate container f92aca5a63ba
---> 974e6ec6c415
Successfully built 974e6ec6c415
Successfully tagged wildfly_dej_website:2.0
This is the list of containers:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
95ee0139f42c wildfly_dej_website:2.0 "/bin/sh -c 'tail -f…" 4 seconds ago Up 2 seconds 0.0.0.0:80->80/tcp dej_website
The problem here is in your dockerfile.
You need to add a CMD at the end of your dockerfile to run the command you want and keep it running for the docker file to stay alive and provide you with logs through docker logs command.
Add a line like this to your dockerfile:
RUN ./standalone.sh -b 0.0.0.0
CMD tail -f /var/log/syslog
And to make the port accessible on the local machine you'll need to use -p option when issuing the docker run command like this:
docker run -d -p 127.0.0.1:80:8080 <image>
you can find out more here:
https://docs.docker.com/engine/reference/commandline/run/

Building a docker image from dockerfile, can't get java to run correctly, but can run java from image as command line parameters in docker run command

I am new to docker and dockerfile files, having just started trying to write them. I have built a simple java console application and can successfully build a docker image from a dockerfile, but if I include
CMD ["java","-jar","app.jar"]
when I try to run the image I always get a bin/sh error, typically "java not found" or the like.
However, when I don't include the CMD line and just use this Dockerfile to build my image
FROM openjdk:8-jre-alpine
COPY app.jar /app.jar
and then run
docker run -it --rm my-container:tag
I can then run
java -jar app.jar
and the application runs as expected.
I can also run
docker run -it --rm my-container:tag java -jar app.jar
and the application runs as expected.
Every guide I read says I should be able to use CMD or ENTRYPOINT as written above, but nothing ever works.
What might I be missing in this simple example?
Thank you,
Trevor
EDIT: I am running docker version 18.06.1-ce-mac73 (26764) on MacOS Sierra. I am not positive that docker works this way, but I have two image versions in my public docker hub. The dockerfile for v1 is:
FROM openjdk:8-jre-alpine
COPY 454calendar.jar app.jar
The dockerfile for v2 is:
FROM openjdk:8-jre-alpine
ENV PROJECT_DIR=/app
WORKDIR $PROJECT_DIR
COPY 454calendar.jar $PROJECT_DIR
If I add
CMD [“java”,”-jar”,”454calendar.jar”]
to the v2 dockerfile and rebuild, I get this error with the docker run command.
/bin/sh: [“java”,”-jar”,”454calendar.jar”]: not found
Without the CMD line, I can run container and it starts right into the /app working directory where I can run the java command and execute the program.
The two versions of the container in my public docker repository do not have the CMD line in their respective dockerfiles.
The solution was maddeningly simple. Thanks to #Rakesh, I checked the configuration for TextEdit on MacOS and saw that Smart Quotes was turned on. Once I turned off that option and retyped the double quotes, then rebuilt and ran the docker container, the application started up just as expected.
I don't see any problem with your approach. I was able to make a HelloWorld application to run with the below Dockerfile.
FROM openjdk:8-jre-alpine
RUN mkdir /app
RUN cd /app
COPY HelloWorld.jar /app/HelloWorld.jar
WORKDIR /app
CMD ["java","-jar", "HelloWorld.jar"]
I'm on the following docker version
docker -v
Docker version 18.06.1-ce, build e68fc7a
docker-compose -v
docker-compose version 1.22.0, build f46880f

How to pass System property to docker containers?

So I know you can pass Environment variables to a docker container using -e like:
docker run -it -e "var=var1" myDockerImage
But I need to pass a System Property to a docker container, because this is how I run my JAR:
java -Denvironment=dev -jar myjar.jar
So how can I pass a -D System property in Docker? Like:
docker run -it {INSERT Denvironment here} myDockerImage
Use the variable you passed into the container on the java command:
docker run -it -e "ENV=dev" myDockerImage
java -Denvironment=$ENV -jar myjar.jar
One more way to do it, if running under Tomcat, is setting your system variables in your Dockerfile using ENV JAVA_OPTS like this:
ENV JAVA_OPTS="-Djavax.net.ssl.trustStore=C:/tomcatDev.jks -D_WS_URL=http://some/url/"
Hope it helps!
One can also use the following start.sh ENTRYPOINT for the Docker container, make sure to use the array syntax, e.g.:
Dockerfile:
...
ENTRYPOINT ["/start.sh"]
The actual start.sh script:
#!/bin/bash
export JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64"
exec $JAVA_HOME/bin/java -jar myjar.jar $#
Then you can just pass the Java system properties directly to your application as docker run container arguments:
docker run myDockerImage "-Dvar=var1"
Have a start.sh file, e.g.:
#!/usr/bin/env sh
exec java -Djava.security.egd=file:/dev/./urandom $* -jar /app.jar
In your Dockerfile:
...
COPY start.sh /start.sh
RUN chmod a+rx /start.sh
ENTRYPOINT ["/start.sh"]

Categories

Resources