UnsatisfiedLinkError using openjdk:17 inside Docker container - java

I want to Dockerize a web application, which works perfectly fine locally. When trying to run the application inside Docker, an UnsatisfiedLinkError is thrown when invoking a function from the Nauty library.
To work with this library locally, the Spring application has to be started by doing
java -Djava.library.path="<PATH>/backend/lib/" -jar backend.jar
This library path points to the directory where the Nauty library (libnauty.so) resides. In my ~/.bashrc, I also had to set the environment variable LD_LIBRARY_PATH=<PATH>/backend/lib/:/usr/local/lib. After making these two changes, the application works fine and functions from the Nauty library can be invoked without any problems.
After Dockerizing the application, I get the following error when invoking a library function
java.lang.UnsatisfiedLinkError: no nauty in java.library.path: "/home/backend/lib/"
However, the libnauty.so file is copied to the Docker container and is present in /home/backend/lib directory. I also set the environment variable LD_LIBRARY_PATH in the Docker container. The issue however still remains.
I use docker-compose to set up the application. The Dockerfile for the back-end looks like this.
FROM openjdk:17-oracle
ARG JAR_FILE=target/*.jar
EXPOSE 8080
ENV LD_LIBRARY_PATH=/home/backend/lib/:/usr/local/lib
COPY ${JAR_FILE} /home/backend/backend.jar
COPY . /home/backend
ENTRYPOINT ["java", "-Djava.library.path=\"/home/backend/lib/\"", "-jar", "/home/backend/backend.jar"]
Any pointers to how this issue could be solved would be greatly appreciated. I have looked around for quite some time now, but I can't seem to fix the problem.

After hours of googling and debugging, the problem was the double quotes around the library path in the ENTRYPOINT. The correct way to specify it is just
ENTRYPOINT ["java", "-Djava.library.path=/home/backend/lib/", "-jar", "/home/backend/backend.jar"]

Related

Unable to access jarfile docker using distroless-debug

I switched from distroless/java:8 to distroless/java:8-debug container and, when deployed to kubernetes, I started getting following error:
Error: Unable to access jarfile /MyApp-0.1.jar
This is my Dockerfile:
FROM gcr.io/distroless/java:8-debug
LABEL CONTAINER_NAME=my-api
ARG JAR_FILE=MyApp/core/build/libs/core-0.1-boot.jar
COPY ${JAR_FILE} MyApp-0.1.jar
ENTRYPOINT ["java","-jar","/MyApp-0.1.jar"]
While I was using regular distroless (everything else was the same) I didn't have this problem.
What is interesting is that when I try to run this Dockerfile locally, I don't get this error. Is this some permission issue?
I redeployed and it is working now. The only logical explanation is that I tried to use nonroot one first and when I switched to root one, some of the pods with nonroot were still there causing the problem.
From what I gathered from this build script:
https://github.com/GoogleContainerTools/distroless/blob/main/java/BUILD
Both of those containers are identical. only the debug one includes java compiler
Also, you could try running the app from the container itself. Run something similar to this:
docker run -it --entrypoint sh my-api
running the whoami inside the container verifies that the user is root, so no restrictions should exist

Where to find produced Docker image

I'm trying to implement the example from this tutorial:
https://spring.io/guides/gs/spring-boot-docker/
I successfully compiled the package:
C:\Users\Desktop\rest_api>docker build -t springio/gs-spring-boot-docker .
Sending build context to Docker daemon 105.6MB
Step 1/5 : FROM openjdk:13-alpine
---> c4b0433a01ac
Step 2/5 : EXPOSE 8080
---> Using cache
---> 010600c5a7d0
Step 3/5 : ARG JAR_FILE=target/rest_api.jar
---> Running in 8ba2e28e0870
Removing intermediate container 8ba2e28e0870
---> b453cd05cbd2
Step 4/5 : ADD ${JAR_FILE} app.jar
---> dade5dd3eff2
Step 5/5 : ENTRYPOINT ["java","-jar","/app.jar"]
---> Running in e8a1f985f0fd
Removing intermediate container e8a1f985f0fd
---> cfa353eb23c5
Successfully built cfa353eb23c5
Successfully tagged springio/gs-spring-boot-docker:latest
SECURITY WARNING: You are building a Docker image from Windows against a non-Windows Docker host. All files and directories added to build context will have '-rwxr-xr-x' permissions. It is recommended to double check and reset permissions for sensitive files and directories.
C:\Users\Desktop\rest_api>
It's not clear for me where is the compiled package located? Can you guide me where it's located and how to mount it into Docker?
Docker file:
FROM openjdk:13-alpine
EXPOSE 8080
ARG JAR_FILE=target/rest_api.jar
ADD ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
In order to get the "compiled package" (spring boot jar) you need to invoke mvn package first.
This command will compile the sources and create a JAR in the target directory of your project.
Since you're working with spring boot, you'll need to configure spring boot maven plugin (make sure it appears in the pom.xml) This plugin creates a special jar of spring boot applications with all the dependencies inside. It stores it in the target directory
So, after invoking mvn package command and before running docker build command go to target directory and make sure that you have a relatively big JAR of the application.
This explanation, I assume, answers the part of the question "where is the compiled package located?"
Now as for "how to mount to Docker" part of the question:
In the Dockerfile you use ADD command. This command takes the jar and "adds" it to the docker image (like into the filesystem of the container), so It will be available under /app.jar (because you also rename the artifact on the way)
At build time, the jar file has been copied from your computer into the container and is since located at /app.jar. No need to mount it.

running war from command line without maven jetty

I am trying to put a piece of open source software in a docker container (https://github.com/att/XACML) but in this container I can not use maven. The documentation for running this service says to use mvn jetty, which does work fine, but in order to get this in a container I don't want to include a build step (maven).
Instead, I'd like a way to compile the a war, so I can copy just the war into the container and execute it from there.
I have tried many attempts to get the war running without maven jetty but none of them work.
java -jar /path/to/jar
no main manifest attribute error. There is no main class, it extends an HttpServlet
using jetty-runner
when I launch the war with jetty-runner through the command line I do not get any errors, but it boots up to a page showing the directory of files, and not the actual project.
Making an 'uber-jar' to package all deps
same issue as 1, get a no main manifest issue.
I can include more code if that would be helpful (pom files etc), but I don't want to add too much if it is unneeded. I am super unfamiliar with how java projects are packaged and deployed, so I am having a difficult time figuring out what needs to be done.
Thanks!
Minimal Dockerfile to work with your webapp / war file is ...
FROM jetty:9.4.18
ADD ROOT.war /var/lib/jetty/webapps/
This uses the official jetty docker image at
https://hub.docker.com/_/jetty
Managed at
https://github.com/eclipse/jetty.docker
The name ROOT.war is special, and will deploy your webapp in the "root" context path of "/"
Building Image
If you build it like this ...
$ docker build -t stackoverflow/jetty:latest .
Running Image
Interactively (so you can the logs)
$ docker run --interactive --tty --rm --publish 80:8080 stackoverflow/jetty:latest
As Daemon
$ docker run --detach --publish 80:8080 stackoverflow/jetty:latest
The server will be available on port 80 of the machine you ran the docker run command on.
Configuring Jetty Base
If you need to configure the jetty image you can use any of the standard start.jar commands.
Example:
FROM jetty:9.4.18
WORKDIR $JETTY_BASE
RUN java -jar $JETTY_HOME/start.jar --add-to-start=jsp
ADD ROOT.war /var/lib/jetty/webapps/
How This Works Without Maven
See the official image details ...
https://github.com/eclipse/jetty.docker/blob/master/9.4-jdk11/Dockerfile
The key commands are ...
WORKDIR $JETTY_BASE
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["java","-jar","/usr/local/jetty/start.jar"]

Installing jar file via nssm

I'm struggling to get this to work using nssm (Non-sucking Service Manager).
I'm trying to get a jar file (Spring-Boot application) to run. With out arguments, I got the service to install and run fine, but I need to pass in VM arguments and I'm banging my head trying to get it to work using nssm.
So the command I need to feed into nssm to make a windows service is:
$> java "-Dspring.profiles.active=dev" -jar .\neo-0.0.1-SNAPSHOT.jar
Any help would be greatly appreicated.
I was able to get it running; instead of passing in a system property (VM property) I pass in the value via application argument.
nssm install JarServiceWithArgs FullJavaPath\java.exe -jar app.jar --spring.profiles.active=dev

Run Java 8 application on server with Java 7 using docker

I have application wrote in Java 8, and now I have to deploy this application on server which has jdk 1.7 but I was using lambdas, optionals and streams and I'm looking for a method to run this application on this server.
Is it possible to create on this server docker container with jdk 1.8 and run my application in this container?
Basically, yes.
You'll need to have some kind of container runtime on that server, e.g. Docker. All you need would be to create an image based on a Dockerfile similar to this one:
FROM java:8-jdk-alpine
RUN adduser -Dh /home/app-user app-user
USER app-user
WORKDIR /app
COPY ./path/to/app.jar /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]
CMD ["--spring.profiles.active=prod"]
Base images for Apache Tomcat are available, too: https://hub.docker.com/_/tomcat/
The example app might help you getting started with a more complex setup: https://github.com/dockersamples/atsea-sample-shop-app/
Contrary to my initial answer it can be done. Docker store has images availible.
Only done partial testing with functionality though.

Categories