How to set environment variables via env-file - java

I have a Dockerfile based on the spring guide about docker. My application consumes some private data, so I want to pass these parameters through environment variables. When I run a docker container:
docker run -p 8080:8080 -t myname/myapplication --env-file=~/env.list
it appears that the variables are not set and the application can't see them, what do I do wrong? How to pass these parameters?
env.list:
ACCOUNT_ID=my_account_id
ACCOUNT_PASSWORD=my_secret_password
My ENTRYPOINT:
ENTRYPOINT java -Djava.security.egd=file:/dev/./urandom -jar $APPLICATION_NAME

I think
docker run
takes all parameters before the image and the command. If I do
docker run -t --env-file=env.list ubuntu sh -c "while true; do echo world; sleep 100 ;done"
and then
docker exec -it container_id env
I get
HOSTNAME=195f18677a91
TERM=xterm
ACCOUNT_ID=my_account_id
ACCOUNT_PASSWORD=my_secret_password
HOME=/root
Try
docker run -p 8080:8080 --env-file=~/env.list -t myname/myapplication

This works very well:
cat <<EOF > test.env
MYVAR=test
EOF
docker run -it --env-file test.env busybox env | grep MYVAR
That will print as expected:
MYVAR=test
In your case in your Java application you can access the environment variables via System.getenv().

Related

How to specify a list of JVM parameters for Dockerized SpringBoot REST jar execution

I have a simple REST application developed using SpringBoot and this application jar has been deployed in a docker container. The end goal is to test the latency of this application under different JVM flag value combinations. I need to know how I can specify a long list of JVM flag values that can be repeatedly changed?
I know that you can specify one or two flags like this:
Dockerfile
FROM openjdk:9
ADD target/java-container.jar /usr/src/myapp/
WORKDIR /usr/src/myapp
EXPOSE 8080
CMD java -XX:+PrintFlagsFinal $JAVA_OPTIONS -jar java-container.jar
and running the command:
$ docker run -d --name mycontainer8g -p 8080:8080 -m 800M -e JAVA_OPTIONS='-Xmx300m' rafabene/java-container:openjdk-env
using the JAVA_OPTIONS. But I have a very long list of JVM flags as shown below:
-XX:+UseSerialGC -XX:+ResizePLAB -XX:-ResizeOldPLAB -XX:-AlwaysPreTouch -XX:-ParallelRefProcEnabled -XX:+ParallelRefProcBalancingEnabled -XX:+UseTLAB -XX:-ResizeTLAB -XX:-ZeroTLAB -XX:-FastTLABRefill -XX:+NeverActAsServerClassMachine -XX:-AlwaysActAsServerClassMachine -XX:+UseAutoGCSelectPolicy -XX:+UseAdaptiveSizePolicy -XX:+UsePSAdaptiveSurvivorSizePolicy -XX:-UseAdaptiveGenerationSizePolicyAtMinorCollection -XX:+UseAdaptiveGenerationSizePolicyAtMajorCollection -XX:+UseAdaptiveSizePolicyWithSystemGC -XX:+UseAdaptiveGCBoundary -XX:+UseAdaptiveSizePolicyFootprintGoal -XX:-UseAdaptiveSizeDecayMajorGCCost -XX:+UseGCOverheadLimit -XX:+DisableExplicitGC -XX:-CollectGen0First -XX:+BindGCTaskThreadsToCPUs -XX:+UseGCTaskAffinity -XX:YoungPLABSize=3397 -XX:OldPLABSize=1123 -XX:GCTaskTimeStampEntries=240 -XX:TargetPLABWastePct=6 -XX:PLABWeight=75 -XX:OldPLABWeight=46 -XX:MarkStackSize=4617021 -XX:MarkStackSizeMax=713160576 -XX:RefDiscoveryPolicy=0 -XX:InitiatingHeapOccupancyPercent=48 -XX:MaxRAM=139765086242 -XX:ErgoHeapSizeLimit=0 -XX:MaxRAMFraction=4 -XX:DefaultMaxRAMFraction=4 -XX:MinRAMFraction=2 -XX:InitialRAMFraction=61 -XX:AutoGCSelectPauseMillis=5557 -XX:AdaptiveSizeThroughPutPolicy=0 -XX:AdaptiveSizePausePolicy=0 -XX:AdaptiveSizePolicyInitializingSteps=28 -XX:AdaptiveSizePolicyOutputInterval=0 -XX:AdaptiveSizePolicyWeight=12 -XX:AdaptiveTimeWeight=19 -XX:PausePadding=0 -XX:PromotedPadding=3 -XX:SurvivorPadding=3 -XX:ThresholdTolerance=10 -XX:AdaptiveSizePolicyCollectionCostMargin=49 -XX:YoungGenerationSizeIncrement=16 -XX:YoungGenerationSizeSupplement=104 -XX:YoungGenerationSizeSupplementDecay=9 -XX:TenuredGenerationSizeIncrement=22 -XX:TenuredGenerationSizeSupplement=117 -XX:TenuredGenerationSizeSupplementDecay=2 -XX:MaxGCPauseMillis=13557897735059052544 -XX:GCPauseIntervalMillis=0 -XX:MaxGCMinorPauseMillis=16119267456708329472 -XX:GCTimeRatio=73 -XX:AdaptiveSizeDecrementScaleFactor=4 -XX:AdaptiveSizeMajorGCDecayTimeScale=11 -XX:MinSurvivorRatio=1 -XX:InitialSurvivorRatio=6 -XX:BaseFootPrintEstimate=272901592 -XX:GCHeapFreeLimit=2 -XX:PrefetchCopyIntervalInBytes=654 -XX:PrefetchScanIntervalInBytes=748 -XX:PrefetchFieldsAhead=1 -XX:ProcessDistributionStride=3
How can this be achieved?
As A. Wolf said, I'd put all jvm options in a file and run
docker run --rm -d --name mycontainer8g -p 8080:8080 -m 800M -e JAVA_OPTIONS="$(cat myjavaoptions)" rafabene/java-container:openjdk-env
While passing values using .sh is valid, you have so many params so I think that the clearer way is using docker-compose.
Just install it from here then you can specify in your docker-compose.yml something like this:
environment:
- JAVA_OPTS=-Xmx128m -Xms128m
You will be able to change your configuration and then restart the container just typing:
docker-compose down
docker-compose up -d
You can use --env-file parameter for passing multiple env variables.
docker run --env-file ./env.list image-name
Here env.list file will be list of env values you want to set inside docker container.

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

Docker - oracle.kv.FaultException: Could not contact any RepNode

I am new to Docker and nosql, I created a Oracle Linux VM (ipAddr 192.168.10.2) on my windows machine.
Further I created docker container (on this VM ) for kvlite and run my nosql-container as below:
$ docker run --name nosql-container -p 5000:5000 -d kvlite:latest
followed by below commands:
$ docker exec -it nosql-container bash
# java -jar lib/kvcli.jar -host localhost -port 5000
kv-> connect store -host localhost -port 5000 -name kvstore ;
This works fine till here and I believe my Docker container for kvlite is up and running fine.
Now I need to create a Client Java program from my windows machine to access this kvlite (running in docker container on a VM)
To accomplish I downloaded kvclient.jar file and put that in my classpath.
The Java code-snippet below:
KVStore store = KVStoreFactory.getStore(new KVStoreConfig("kvstore", "192.168.10.2:5000"));
This throws an exception:
oracle.kv.FaultException: Could not contact any RepNode at: [192.168.10.2:5000] (12.1.4.0.9)
....
Caused by: java.rmi.UnknownHostException: Unknown host: ecfe59938ea4; nested exception is:
Any help appreciated in advance.
I resolved the issue by adding a param --net=host when running nosql-container
$ docker run --name nosql-container --net=host -p 5000:5000 -d kvlite:latest
Now instead of IPAddress you can use VM hostname in Java Client code to access kvlite DB.
KVStore store = KVStoreFactory.getStore(new KVStoreConfig("kvstore", "VMHostname:5000"));

Docker - Unable to use placeholders inside ENTRYPOINT

I have this Dockerfile:
FROM java:8
ARG HOST
...
...
ENTRYPOINT java -DHOST=${HOST} -jar ./app.jar
I build the docker image passing the necessary build-arg: docker build -t co/myprogram --build-arg=HOST=myhost.com .
However when I run the image: docker run co/myprogram I get an exception in my program because the placeholder didn't substitute the HOST value. The url looks like http:///action/get instead of http://myhost.com/action/get..
Is there a way to use placehoders in the ENTRYPOINT?
ARGs are not used for interpolating ENTRYPOINT.
To achieve what you want to do, you can add a line with ENV HOST $HOST.
The entrypoint will then use $HOST at runtime, rather the interpolated value at buildtime, but, the variable will be set with the default value which was set at buildtime, but is still overridable.
Here is an example:
$ cat Dockerfile
FROM busybox
ARG what
ENV what $what
RUN echo ${what} > /tmp/${what}
ENTRYPOINT cat /tmp/${what}
$ docker run -ti $(docker build -q --build-arg=what=test . )
test
Unfortunately it seems to be impossible by design: https://github.com/docker/docker/issues/18492

Categories