Cannot run my Java 8 application from docker container - java

I can properly launch this Java 8 application using this command from a bash shell:
java -cp "simple-queue-0.1-SNAPSHOT.jar:jms-1.1.jar:commons-logging-1.2.jar:activemq-all-5.13.3.jar"
-Dserver1="my1.domain.com"
-Dserver2="my2.domain.com"
-Dusername="user"
-Dpassword="passwd"
com.fusesource.activemq.exercises.simple.queue.SimpleProducer
I want to containerize this application, so here is my Dockerfile:
FROM store/oracle/serverjre:8
MAINTAINER <me#myco.com>
EXPOSE 4567
VOLUME /data
COPY build/libs/*.jar /usr/local/bin/
COPY /app/simple-queue-0.1-SNAPSHOT.jar /usr/local/bin/
CMD ["java", "-cp", "/usr/local/bin/simple-queue-0.1-SNAPSHOT.jar:/usr/local/bin/jms-1.1.jar:/usr/local/bin/commons-logging-1.2.jar:/usr/local/bin/activemq-all-5.13.3.jar", "-Dserver1=$SERVER1", -Dserver2="$SERVER2", -Dusername="$USER", -Dpassword="$PASSWORD"]
I start my container like this:
docker run -it --rm -e SERVER1=my1.domain.com -e SERVER2=my2.domain.com -e USER=user -e PASSWORD=passwd ecosystem/simple-queue-client:1.1 com.fusesource.activemq.exercises.simple.queue.SimpleProducer
And I get this error message:
docker: Error response from daemon: OCI runtime create failed: container_linux.go:346: starting container process caused "exec: \"com.fusesource.activemq.exercises.simple.queue.SimpleProducer\": executable file not found in $PATH": unknown.
When I get into that container, I can see that my jar files are in fact inside /usr/local/bin directory which is in the PATH. The CLASSPATH in the container is empty...
What do I need to do to fix this?

I used info from the link provided by midelb above and ended up with two containers: one for SimpleProducer and another for SimpleReceiver.
Here is the Docker file for one:
FROM store/oracle/serverjre:8
MAINTAINER <james.depaul#maxar.com>
VOLUME /data
COPY build/libs/*.jar /usr/local/bin/
COPY /app/simple-queue-0.1-SNAPSHOT.jar /usr/local/bin/
ENTRYPOINT java -classpath /usr/local/bin/simple-queue-0.1-SNAPSHOT.jar:/usr/local/bin/jms-1.1.jar:/usr/local/bin/commons-logging-1.2.jar:/usr/local/bin/activemq-all-5.13.3.jar -Dserver1=$SERVER1 -Dserver2=$SERVER2 -Dusername=$USER -Dpassword=$PASSWORD com.fusesource.activemq.exercises.simple.queue.SimpleConsumer
Build
docker build -t mysystem/simple-client-consumer:1.0
And I call it like this now:
docker run -d --rm -e SERVER1=server-b0.domain.com -e SERVER2=server-b1.domain.com -e USER=user -e PASSWORD=passwd mysystem/simple-client-consumer:1.0

Related

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.

docker run with port-forward fails

This is my docker file
FROM openjdk:8-jre-slim
RUN mkdir /app
COPY dept-1.0.jar /app
CMD java -jar /app/dept-1.0.jar
EXPOSE 8080
The docker image can be run without any issues if I were to run like without port-forward
docker run --name=department dept:latest
But with port-forward docker run --name=department dept:latest -p 8082:8080 I see this error -
docker: Error response from daemon: OCI runtime create failed: container_linux.go:345: starting container process caused "exec: \"-p\": executable file not found in $PATH": unknown.
Can someone help pls ?
I changed the following in the Dockerfil
CMD java -jar /app/dept-1.0.jar
to
ENTRYPOINT ["java", "-jar", "/app/dept-1.0.jar"]
This solved my issue.

When building a Maven project in Docker, all target files are rooted

I have a Maven project which I want to build in a Docker container, so that I don't have to install Java, Maven, ... on my Jenkins system.
I build the Maven project as following:
docker run -it --rm -v /var/run/docker.sock:/var/run/docker.sock:ro
-v $(pwd):/opt/maven
-w /opt/maven
maven
mvn clean install
This works great, the build is correctly made. However, when doing this as my regular user, all files in the target/ directory are owned by root and no by jester, which is my current user.
Is there an easy way to fix this?
You chan check out the option -u, as in this gist, which wraps docker run in a script:
#!/bin/sh
set -e
test ":$DEBUG" != :true || set -x
# set image
set -- debian:jessie "$#"
# use current user and its groups at host
for v in /etc/group /etc/passwd; do
[ ! -r "$v" ] || set -- -v $v:$v:ro "$#"
done
set -- --user "`id -u`:`id -g`" "$#"
for g in `id -G`; do
set -- --group-add "$g" "$#"
done
set -- -v "$HOME":"$HOME" "$#"
exec docker run --rm -it "$#"
The goal is to make sure the container mounts the local user definition, and uses the same uid/gid.

Redeploy spring-boot application in docker container?

I have a spring-boot project and I want automatically redeploy my jar in the container.
How to do it correctly?
So far, all I see is this way. It's the right way?
# cd /home/jdev;
# sudo docker stop ca_spring_boot;
# sudo docker rm ca_spring_boot;
# sudo docker rmi ca_app_image;
# sudo docker build -t ca_app_image .;
# sudo docker run -d -p 8888:8080 --name ca_spring_boot ca_app_image
And my Dockerfile
FROM java:8
VOLUME /tmp
EXPOSE 8080
ADD docker-storage/jenkins/workspace/CA/build/libs/ca-1.0.jar app.jar
RUN bash -c 'touch /app.jar'
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-Dspring.profiles.active=container","-jar","/app.jar"]
Thanks.
You could mount a volume and put your app.jar in there. So you do not need to rebuild the image, you just restart the container.
Dockerfile
FROM java:8
ENTRYPOINT [ "sh", "-c", "java -jar /mnt/app.jar" ]
Put your app.jar in /docker/spring/
Build and run:
docker build -t spring_test .
docker run -d -v /docker/spring/:/mnt -p 12384:8080 --name spring_test_running spring_test
If you update your spring application you just do:
docker restart spring_test_running
The previous answer is good. But there is need to restart container every time when you want to test your code. But we can avoid this problem. Just use Spring dev tool
And mount destination directory as described above.

How to run a specific profile on WebSphere on Docker?

Is it possible to copy an existing WebSphere profile and run it on WebSphere in Docker?
I am doing some research on containerization, virtualization, etc. and am currently working with Docker. Getting WebSphere up and running on Docker is simple enough:
docker run --name wasserver -h wasserver -p 9043:9043 -p 9443:9443 -d ibmcom/websphere-traditional:install
What I'd like to do is use a profile from another WebSphere instance and run that on the Docker WebSphere. I have tried to do the following in an attempt to mount a directory that contains the profile in question, and to run same:
docker run -v /opt/WebSphere/WAS8_5/:/WASDIR --name myprofileserver -h myprofileserver -p 9043:9043 -p 9443:9443 -d ibmcom/websphere-traditional:install -e PROFILE_NAME=/WASDIR/profiles/myprofile1
The end result of this command is that the container is created, but does not run:
docker: Error response from daemon: oci runtime error: exec: "-e": executable file not found in $PATH
Perhaps there is a switch, setup, or other configuration I am missing here?
The last argument to docker run is the command you want to run inside the container (or the name of the image if you're running the default entrypoint / cmd). You just need to move your environment variable definition back in the command like this:
docker run -v /opt/WebSphere/WAS8_5/:/WASDIR --name myprofileserver -h myprofileserver -p 9043:9043 -p 9443:9443 -d -e PROFILE_NAME=/WASDIR/profiles/myprofile1 ibmcom/websphere-traditional:install

Categories