I am wondering if is possible to do the following...
I have a small application in java (and gradle)
I am trying to set it in a container, so I created the Dockerfile and worked fine UNTIL I have to set a parameter.
To run it locally on my IDLE I set these program arguments:
server application-local.yml
That actually loads a file with many properties, without this the app will fail.
On my Dockerfile I have this
FROM openjdk:8-jdk-alpine
USER root:root
ENV NAME test
LABEL maintainer="myself"
WORKDIR /opt/apps
COPY build/libs/myapp.jar /opt/apps/myapp.jar
EXPOSE 8080
CMD ["java", "myapp.jar"]
I was wondering if I could do the following:
CMD ["java", "-server:application-local.yml", "myapp.jar"]
but doesnt work, also I cannot do
java -jar myapp.jar -server:application-local.yml
simply doesnt do anything
Dont wanna do a gradleBuild because it is supposed to use java only at my docker image...
Any idea how to do this?
Edit:
So, I have done the following, move my application-local.yml to a folder I can copy and added this
COPY some-path/application-local.yml /opt/apps/local.yml
and moved the CMD for this
CMD ["java", "myapp.jar", "server", "local.yml"]
I still get the same error, basically cannot resolve the values from that yml file.
EDIT 2 ---
Basically what I cannot do is to figure out how to send the application.default.yml as configuration file, I realise also that the -server does not anything, is my config file the one I cannot load and is not present in the jar (normal behaviour)
When using the java command, order of the arguments matter
First you put the java options, like -server, then the -jar ... Or the class name in the case of running classes directly, and then the application arguments
The proper way to run your app is:
CMD ["java", "-jar", "myapp.jar", "server", "application-local.yml"]
Then you have another problem, you are only copying the final jar file to your docker container, so it can can't find the application-local.yml file, copy this also to your docker container
COPY build/libs/application-local.yml /opt/apps/application-local.yml
Related
Good day everyone.
I have a simple java-based cucumber application, that runs in Docker. I planing to specify which scenarios to run by using ENV for Cucumber tags.
My Dockerfile that able to run specified tags:
FROM maven:3.6.1-jdk-11
COPY target/cucumber-app.jar ./
CMD java -jar -Dcucumber.options='--tags #default' cucumber-app.jar
In this case, during docker run command all works perfectly.
I plan to set up a default scenario for not specified Tags and ability to set up special scenarios through ENV:
FROM maven:3.6.1-jdk-11
COPY target/cucumber-app.jar ./
ENV TAG '--tags #default'
CMD java -jar -Dcucumber.options=$TAG cucumber-app.jar
Unfortunately in this case after running docker container I got:
Error: could not open `default'
Possible you have any ideas why using ENV crash possibility to specify cucumber.options?
If you have a recent version of Cucumber rather then trying to squeeze command line options in through a system property via an environment variable, you can set the environment variable straight away. I.e:
ENV CUCUMBER_FILTER_TAGS '#Cucumber and not (#Gherkin or #Zucchini)'
CMD java -jar cucumber-app.jar
https://github.com/cucumber/cucumber-jvm/tree/main/core
I have configured a Docker Image for my Spring boot application. I have also configured logs using log4j.xml. But, on running the docker image, the logs are getting printed neither in the docker logs nor on the location specified in log4j.xml.
Below is my Dockerfile
FROM openjdk:8
ADD <relative path to jar>/jar-name.jar jar-name.jar
ADD <relative path to property file>/application.properties /app/application.properties
ADD <relative path to log4j file>/log4j2-8081.xml /logs/log4j2-8081.xml
ENV JAVA_OPTS="8080"
ENTRYPOINT ["java", "-Dapp.home=classpath:file:/app/", "-
Dlog4j.configurationFile=classpath:file:/logs/log4j2-8081.xml", "-jar", "jar-name.jar"]
I need to pass the log4j.xml file path during the execution of the docker run command.
Thanks in advance
Docker Run Command:-
docker run -p 8081:8081 -e JAVA_OPTS=-Dserver.port=8081 rdsstg
So per your query you are saying the logs aren't getting printed per the log4j config in application code and in your docker container, kindly correct my inference. Thanks.
Now per your comment,
I want to create logs outside the container. In the location /log of the system.
The answer is to use volumes, where-in the path of host machine and docker container is provided. The bare minimal usage is to use -v option See below. For deep dive please refer Use volumes for more details.
docker run -p 8081:8081 -e JAVA_OPTS=-Dserver.port=8081 -v /host_machine/log:/container/var/app/log rdsstg
BUT, you do need to understand in order for your docker container to direct log files(or any files per say) on host machine, those files should be generated in container i.e app logging should be working in container. This is your #1
Let me know if above make sense.
On a side note
for -e usage, I would recommend to use the --env-file option so that you can keep multiple env variables in one file instead of passing multiple -e.
It would have been difficult to explain in comments section.
I have a very simple java jar application that fetches DB properties from the env variables.
I`ve dockerized it and migrated to Kubernetes. I also created a config map and secret with parameters to my DB - so I have access to these properties in the container.
Is it possible to fetch all properties and inject it in Dockerfile? How can I do it?
FROM openjdk:8-jre
ADD target/shopfront-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8010
ENTRYPOINT ["java","-Ddb.host=**value-from-env-variable**","-jar","/app.jar"]
You can use them like this
ENTRYPOINT ["java", "-jar", "-Ddb.host=${DB_HOST}", "/app.jar"]
where DB_HOST should be defined in config map you have created.
I have tried this in my Spring Boot Application for setting Spring Profile.
The array or "exec form" of entrypoint uses exec to run the specified binary rather than a shell. Without a shell the string $DB_HOST is passed to your program as argument.
Shell form
ENTRYPOINT java -Ddb.host="${DB_HOST}" -jar /app.jar
Shell script
If your startup get more complex you can also use an ENTRYPOINT script.
ENTRYPOINT ["/launch.sh"]
Then launch.sh contains:
#!/bin/sh -uex
java -Ddb.host="${DB_HOST}" -jar /app.jar
As I understand you need to fetch parameters from config map and secret and set them as environment variables in your container. Furtunately it's quite nicely described in Kubernetes documentation.
Have a look at below links:
How to use secret: https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets-as-environment-variables
How to use config map: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#use-configmap-defined-environment-variables-in-pod-commands
To sum up, such resources need to be just defined in Pod's configuration.
I want to build a docker image. And I run
docker build --build-arg project_file_name=account.jar -t account:1.0 .
The docker file looks like this (#1)
FROM anapsix/alpine-java:8u172b11_server-jre
ARG project_file_name
MAINTAINER jim
COPY src/${project_file_name} /home/${project_file_name}
CMD java -jar /home/${project_file_name}
If hardcode the variable, it will look like this (#2)
FROM anapsix/alpine-java:8u172b11_server-jre
MAINTAINER jim
enter code here
COPY src/account.jar /home/account.jar
CMD java -jar /home/account.jar
After I build the image with #1 and #2
Using #1, when I docker run, docker tell me it cannot find the specified jar file
Using #2, when I docker run, docker is able to execute the java jar file correctly.
To me both #1 and #2 are same. Just #1 use build-arg variable way and #2 is hardcoding the value. I believe the way I use build-args is incorrect. Can anyone guide me on this?
Regards
A running container won’t have access to an ARG variable value., you'll need ENV variable for that. Though you can use ARG variable to set ENV variable. In your situation you can do
FROM anapsix/alpine-java:8u172b11_server-jre
ARG project_file_name
ENV PROJECT_FILE=${project_file_name}
MAINTAINER jim
COPY src/${project_file_name} /home/${project_file_name}
CMD java -jar /home/${PROJECT_FILE}
You can read more here
According to http://www.eclipse.org/jetty/documentation/current/quickstart-running-jetty.html it is possible to manage web applications in base directories in jetty 9.x. The guide explains what can be put inside those and gives an example by pointing to the demo-base directory in the binary distribution. However it would have been useful to point out what actually needs to be in such a jetty base in order to make deployment successful, e.g. so that
cd /path/to/my-base/
java -jar ~/jetty-distribution-9.2.3.v20140905/start.jar jetty.home=~/jetty-distribution-9.2.3.v20140905/ jetty.base=.
succeeds. Putting a minimal valid war file (with only one jsf file) into /path/to/my-base or /path/to/my-base/webapps/ fails with WARNING: Nothing to start, exiting ..., although it would make sense to deploy a minimal application or display a helpful warning what needs to be added.
What needs to be added to be able to deploy an application from a separate base directory?
Jetty can make this for you through flags to the start.jar
There's an exmample in the docs, here: http://www.eclipse.org/jetty/documentation/9.3.0.v20150612/quickstart-running-jetty.html
"The following commands: create a new base directory; enables a HTTP connector and the web application deployer; copies a demo webapp to be deployed.
Simplified:
mkdir /home/me/mybase
cd /home/me/mybase
java -jar $JETTY_HOME/start.jar --add-to-startd=http,deploy
Then copy your war, if you use ROOT.war, it will map to /, and start jetty:
cp my.war webapps/ROOT.war
java -jar $JETTY_HOME/start.jar
Alternatively, if you have docker installed, you can also get the official setup by copying it, like so:
First, have docker download and run jetty, map a directory on the host to the docker container. I was already mapping webapps, so I just continued to use that mapping. This removes the container when done (-rm) so it's clean and it starts an interactive bash shell, logging you right into an official barebones jetty container that is ready to deploy wars plopped into the webapps directory (just what we want!)
sudo docker run --rm -it -v /home/myuser/jetty/webapps:/var/lib/jetty/webapps jetty:latest /bin/bash
If you run and env on the container, you'll see:
JETTY_BASE=/var/lib/jetty
Just tar this base up, copy the tar to the webapps directory, which is mapped back to the localhost, and exit. (feel free to map
root#f99cc00c9c77:/var/lib# tar -czvf ../jetty-base.tar.gz .
root#f99cc00c9c77:/var/lib# cp ../jetty-base.tar.gz jetty/webapps/
root#f99cc00c9c77:/var/lib# exit
Back on the localhost, you have a tar of the official jetty base! The docker container should have stopped on exit, you can test this with sudo docker ps, which should show an empty list (just headers).
Just to finish this off, back on the host, create a base directory (as myuser, not root, of course):
mkdir ~/jetty/localbase
cp ~/jetty/jetty-base.tar.gz ~/jetty/localbase/
cd ~/jetty/localbase/
tar xvzf jetty-base.tar.gz
Then start it up like before:
java -jar $JETTY_HOME/start.jar