Deploying Command Line Interface app using jib - java

Ok, I am building a jib based docker image which contains a java CLI app. The application is run like this :
java -jar app.jar --opt1=<opt1-value>
what i want to do is run a docker container which does nothing when the container is started but can accept arguments anytime and pass that arguments to the JVM application in the container and let it do its job. It looks like that when the jib docker container is run, the application is run and it closes itself.
Not sure how to go about doing this. Any help on this is much appreciated.

I think you're trying to use a container in an unconventional way, but I'll leave an answer anyway.
I'll assume you run your container image on a Docker runtime.
Run java -jar app.jar inside a container.
$ docker run --entrypoint java <your image> -jar app.jar
Run java -jar app.jar --opt1=some-value inside a container.
$ docker run --entrypoint java <your image> -jar app.jar --opt1=some-value
Run sh inside a container, and use the shell.
(This requires having the sh program installed in your image. An old version of Jib by default used a base image that doesn't have a shell program, so in that case, you would have needed to specify a different base image such as openjdk using the jib.from.image config option.)
$ docker run -it --entrypoint sh <your image>
(now you're in a "sh" process running inside a container)
# ls
...
# java -jar app.jar
...
# exit
Update based on the OP's comment:
There are many ways to achieve what you want, and here's one:
Run a container with a process that can hang while does nothing, such as the very common Linux tool sleep. (Again, as with sh above, you may use a base image that comes with the sleep binary, such as openjdk.)
$ docker run --name my-running-container --entrypoint sleep <your image> infinity
In another terminal, you'll be able to verify that your container named "my-running-container" is running with the command sleep infinity:
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
51c4568d2d2a debian:buster "sleep infinity" 6 seconds ago Up 3 seconds my-running-container
When you want to run your app inside the running container, do
$ docker exec my-running-container java -jar app.jar --opt1=some-value

Related

Simple Docker container dies immediatelly after docker run command

I have a Dockerfile which looks like this:
FROM alpine:3.9
RUN apk add --update openjdk8
RUN mkdir /var/generator/
COPY generator.jar /var/generator
EXPOSE 8080
ENTRYPOINT [ "/bin/sh" ]
Dockerfile is inside generator/ folder. I am building it using:
docker build -t generator generator/
It builds successfully:
Successfully built 878e81f622cc
Successfully tagged generator:latest
but when I am trying to run this image with
docker run -d -p 8080:8080 generator
it dies immediately. docker logs gives no output.
What is wrong with my Dockerfile? Why is the container dying?
Try to run the JAR. Currently, it just runs sh command and exits. Make it something as below to run the JAR in foreground -
FROM alpine:3.9
RUN apk add --update openjdk8
RUN mkdir /var/generator/
COPY generator.jar /var/generator
EXPOSE 8080
ENTRYPOINT ["java","-jar","/var/generator/generator.jar"]
Beside your entrypoint is wrong (sh exits immediately) I would also recommend to start with an appropriate base image instead of starting with alpine and installing the openjdk package. Since you want to run a java application just use the JRE and not a full JDK and start the application as a foreground process.
Here's a minimal version which is also more efficient in disksize as the image will be smaller.
FROM openjdk:8-jre-alpine
COPY generator.jar /opt/generator.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/opt/generator.jar"]

Docker Springboot not running

I am new to docker,
I have pre cooked a docker image(updated and installed Java and other dependancies) and stored it on my GitHub repo,
I have stored a simple hello world Spring Boot application on an AWS S3 bucket,
I want to my DockerFile -
1. Get the docker image from my GitHub repo
2. Do an update patch
3. Set my working to directory to /home/ubuntu
4. Download application from S3 bucket using wget(it's publicly accessible)
5. run the application inside the container
After which I will run the image.
Command to build -
docker build -t someTag .
Command to run -
docker run -p 9090:8090 someTag
My java application jar that will be downloded is - docker.jar
And the application runs on port 8080
I have the following Dockerfile -
FROM someRepoHere
WORKDIR /home/ubuntu
RUN apt-get update
RUN cd /home/ubuntu
VOLUME /home/ubuntu
RUN wget S3BucketLocationHere
#RUN nohup java -jar docker.jar &
# Expose the default port
EXPOSE 8080
#Old command - CMD nohup java -jar docker.jar &
CMD ["java", "-jar", "docker.jar"]
The DockerFile is able to successfully build the image but,
My application is unreachable, It did not run inside the container.
Locally if I wget my application and run the nohup command, the application responds successfully.
Your command being run is what controls the existence of the container, when it exits/returns, the container exits and stops. Therefore you need to run your command in the foreground. When you are in an interactive shell in a container, that command is your shell. The command you've listed uses a shell, but that shell exits when it runs out of commands to process and nothing is running in the foreground:
CMD nohup java -jar docker.jar &
The string syntax will run the command with /bin/sh -c "nohup java ...".
A better option is to run with json syntax if you don't need a shell, and run your java app in the foreground, avoid the nohup and background syntax:
CMD ["java", "-jar", "docker.jar"]
A few more comments on the provided Dockerfile:
WORKDIR /home/ubuntu
RUN apt-get update
That only creates a cache inside your container that will become stale and result in cache misses if you try to use it in the future. This doesn't upgrade any packages if that's what you intended. That line should be removed.
RUN cd /home/ubuntu
This makes no filesystem changes, and will have no impact on the resulting image. The current shell state is lost after the RUN line exits, including the current directory and any variables you set. This line should be removed.
VOLUME /home/ubuntu
From this line forward, changes to /home/ubuntu will be lost. You'll only see anonymous volumes created as a result unless you specify a volume at runtime at the same location. You likely don't want the above volume line because it will break things like the next line.
RUN wget S3BucketLocationHere
This line has been obfuscated but I suspect you are outputting in /home/ubuntu because of the value of WORKDIR. Anything created here will be lost because of the VOLUME line above.

Dockerized Java app dies with no error message but runs fine standalone

Please note: I know this questions is very similar to this one however you'll note that the solution in that case was to EXPOSE the port, which I am already doing. Hence although this questions sounds similar, I think its simply a different problem altogether with similar symptoms as the other question.
Docker Version 17.12.0-ce-mac49 (21995) here. I am experimenting with Docker for the first time and have built my first Docker image. My Dockerfile is:
FROM openjdk:8
RUN mkdir /opt/myapp
ADD build/libs/myapp.jar /opt/myapp
ADD application.yml /opt/myapp
ADD logback.groovy /opt/myapp
WORKDIR /opt/myapp
EXPOSE 9200
ENTRYPOINT java -Dspring.config=. -jar myapp.jar
I build it via:
docker build -t myapp .
Everything succeeds. I then tag it as if I'm going to push it to Quay:
docker tag <imageId> quay.io/myregistry/myapp:0.1.0-SNAPSHOT
However before I publish to Quay I want to run it locally to make sure it works:
docker run -it -p 9200:9200 -d --env-file /Users/myuser/myapp-local.env --name myapp myapp
When I run this I get an indication that the container is running, and I can even see it for a few seconds via docker ps:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
f3fa8f7a4288 myapp "/bin/sh -c 'java -D…" Less than a second ago Up 7 seconds 0.0.0.0:9200->9200/tcp myapp
However after a few seconds it stops running and disappears from docker ps altogether:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Furthermore I'm not able to SSH into the container:
docker exec -it f3fa8f7a4288 bash
Error: No such container: f3fa8f7a4288
...or see any logs/console output.
When I run myapp.jar outside of Docker (as a typical Spring Boot app, it starts up and runs beautifully without exceptions). How can I troubleshoot what is going on?
The docker logs command will show you the output a container is generating when you run it detached (with -d). This is likely to include the error message.
docker logs --tail 50 --follow --timestamps container
You can run the image in the foreground without the -d to see the output like when you run myapp.jar outside of Docker.
docker run my/image
So in this specific case:
docker run -it -p 9200:9200 --env-file /Users/myuser/myapp-local.env --name myapp myapp
If I am not mistaken, the issue you are experiencing is because you are using the shell form of ENTRYPOINT. Change it to use the exec version, as follows:
ENTRYPOINT ["java", "-Dspring.config=.", "-jar", "myapp.jar"]
The shell form will launch Java as a separate process just like a shell command. This causes PID 1 to return making Docker believe the container is finished. Using the exec form, the Java process replaces PID 1 and the container will continue running.

Why does wildcard for jar execution not work in docker CMD?

I have a Dockerfile with the following CMD to start my spring boot app:
FROM java:8-jre
# ...
CMD ["java", "-jar", "/app/file*.jar"]
When I try to start a container from the created image I get:
Error: Unable to access jarfile /app/file*.jar
But when I override the CMD while starting the container and execute the command in the container everything works fine:
docker run -it <imageId> bash
root#<containerId>:/app# java -jar /app/file*.jar
<spring boot app starts...>
Is it possible to use wildcards with java -jar command using docker CMDs?
Please don't tell me not to use wildcards. I want to use it cause of reasons ;-)
Update
Based on the answer I was able to fix it:
CMD ["/bin/sh", "-c", "java -jar /app/file*.jar"]
This kind of asterisk expansion is done by the command line processor - the shell - and you circumvent that by invoking java directly.
Much the same way as commands should be invoked with "CMD /C" under Windows to get full treatment.
Invoke /bin/sh instead.
CMD java -jar /app/file*.jar worked for me

How do write a CSV file in a docker container volume with Java 8?

I am struggling with docker and the file system. I would like to write a file in a docker volume from my Java application. The main goal is that another application running on the same machine can read the file.
I read the related question, but I did not find any answer solving this with a java application. Any idea on how to do this?
Building on the answer to your other question:
How to import a CSV inside a Docker container with Java 8?
Example
So you have two docker containers with a need to share a file system? Assuming your java application is containerized, use it to create a persistent data container:
$ docker create -v /data --name mydata mydockerimage
Run your containerized programs using this data container
$ docker run -it --rm --volumes-from mydata mydockerimage create "/data/myfile.csv"
$ docker run -it --rm --volumes-from mydata mydockerimage read "/data/myfile.csv"
It's possible to pull files out of the data container:
$ docker cp mydata:/data/myfile.csv myfile.csv
Finally you'll want to cleanup the data container eventually
$ docker rm -v mydata
Update
You have not indicated how you're building or using your java program. I have assumed it's an executable jar that can either write or read a CSV file:
java -jar myjar.jar create "/data/myfile.csv"
java -jar myjar.jar read "/data/myfile.csv"
For an example of how to build such a container see:
How to build a docker container for a java app

Categories