Load JavaAgent on JVM - java

I have a theoretic question about java Agents. It's posible do a java or openJDK instruction to add a java agent before execute java?
The normally execution of javaagent (i discard runtime execution) is:
java -jar -javaagent myJavaAgent myProgram.jar
But my idea is create a docker container with OpenJDK version and my agent load
PersonalJDK
FROM openjdk:7
RUN java LOAD AGENT // I DONT KNOW THIS INSTRUCTION
the customer use my container with my agent load
FROM personalJDK:7
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN javac Main.java
CMD ["java", "Main"]

Searching solutions i come with this:
https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/envvars002.html
The answer is using _JAVA_OPTIONS, you must include a enviroment variables includes java agent.
PersonalJDK
FROM openjdk:7
COPY . /agent
RUN _JAVA_OPTIONS=-javaagent:/agent/myagent.jar
the customer use my container with my agent load
FROM PersonalJDK
COPY . /usr/src/myapp
WORKDIR /usr/src/myapp
RUN javac Main.java
CMD ["java", -jar, "Main.jar"]

Related

Converting Shell Script to Dockerfile

I have Java app and want to generate docker image, I have shell script like this:
#!/bin/sh
java -version
export APPLICATION_DIR=$PWD
for rJarFile in `ls ${APPLICATION_DIR}/lib/*.jar`
do
export CLASSPATH=$rJarFile:$CLASSPATH
done
export CLASSPATH=$APPLICATION_DIR/classes:$CLASSPATH
java -Xverify:none -Xmx2048m -Djava.awt.headless=true -DFI_IS_CONFIGSER=N -DFICLIENT_APP_PATH=${APPLICATION_DIR} -DFI_APP_NAME=FIONLINE -DFI_BASE_INSTANCE_ID=1 -DPRODUCT_BOOTSTRAP_FILE=${APPLICATION_DIR}/data/BootstrapFile.properties -DFEBA_SYS_PATH=${APPLICATION_DIR}/data
And I try to convert it into Dockerfile like this
# FROM openjdk:8
FROM openjdk:11
RUN javac -version
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
COPY . .
ENV APPLICATION_DIR=/usr/src/app
RUN echo $APPLICATION_DIR
RUN for rJarFile in `ls ${APPLICATION_DIR}/lib/*.jar`; do export CLASSPATH=$rJarFile:$CLASSPATH; done
RUN echo $CLASSPATH
ENV $CLASSPATH=$APPLICATION_DIR/classes:$CLASSPATH
# Run app
ENTRYPOINT ["java", "-Xverify:none", "-Xmx2048m", "-Djava.awt.headless=true", "-DFI_IS_CONFIGSER=N", "-DFICLIENT_APP_PATH=${APPLICATION_DIR} -DFI_APP_NAME=FIONLINE -DFI_BASE_INSTANCE_ID=1", "-DPRODUCT_BOOTSTRAP_FILE=${APPLICATION_DIR}/data/BootstrapFile.properties", "-DFEBA_SYS_PATH=${APPLICATION_DIR}/data"]
It can be generated, but there's an error when I try to run it like this:
Error response from daemon: OCI runtime create failed: container_linux.go:370: starting container process caused: process_linux.go:459: container init caused: setenv: invalid argument: unknown
I've also changed this script RUN for rJarFile in `ls ${APPLICATION_DIR}/lib/*.jar`; do export into this RUN for rJarFile in ls ${APPLICATION_DIR}/lib/*.jar; do export CLASSPATH=$rJarFile:$CLASSPATH; done, but none of them working. I don't want to make Dockerfile execute the script. Below is logs when i generate and run it.
You cannot update the classpath as you do with:
ENV $CLASSPATH=$APPLICATION_DIR/classes:$CLASSPATH
instead you can do
ENV CLASSPATH=$APPLICATION_DIR/classes:$CLASSPATH
Also - please consider moving the script into a separate shell script and adding into the container. This would greatly simplify the Dockerfile, for example:
# FROM openjdk:8
FROM openjdk:11
RUN javac -version
# Create app directory
WORKDIR /usr/src/app
# Bundle app source
COPY . .
ENV APPLICATION_DIR=/usr/src/app
RUN echo $APPLICATION_DIR
ENTRYPOINT ["/usr/src/app/start_java.sh"]
and keep your existing script inside start_java.sh

Running java by arguments in Docker

Let's say we have the following Dockerfile for the purpose of creating a java image and compiling two scripts.
FROM openjdk:latest
COPY src JavaDocker
WORKDIR JavaDocker
RUN mkdir -p bin
RUN javac -d bin ./com/myapp/HelloWorld1.java
RUN javac -d bin ./com/myapp/HelloWorld2.java
WORKDIR bin
ENTRYPOINT java
How can I run any of these two scripts that have been compiled?
I'm using the command: docker run myapp-image "com.myapp.Server"
And I get:
Usage: java [options] <mainclass> [args...]
(to execute a class)
or java [options] -jar <jarfile> [args...]
(to execute a jar file)
or java [options] -m <module>[/<mainclass>] [args...]
java [options] --module <module>[/<mainclass>] [args...]
(to execute the main class in a module)
or java [options] <sourcefile> [args]
(to execute a single source-file program)
Arguments following the main class, source file, -jar <jarfile>,
-m or --module <module>/<mainclass> are passed as the arguments to
main class.
I'd suggest building a separate image per application; that can help clarify what the image is supposed to do. I also generally recommend using CMD over ENTRYPOINT.
So a Dockerfile that runs only the first application could look like:
FROM openjdk:latest
# Prefer an absolute path for clarity.
WORKDIR /JavaDocker
# Set up the Java class path.
RUN mkdir bin
ENV CLASSPATH=/JavaDocker/bin
# Use a relative path as the target, to avoid repeating it.
# (If you change the source code, repeating `docker build` will
# skip everything before here.)
COPY src .
# Compile the application.
RUN javac -d bin ./com/myapp/HelloWorld1.java
# Set the main container command.
CMD ["java", "com.myapp.HelloWorld1"]
What if you do have an image that contains multiple applications? If you use CMD here, it's very easy to provide an alternate command when you run the image:
docker run myapp-image \
java com.myapp.HelloWorld2
# Wait, what's actually in this image?
docker run --rm myapp-image \
ls -l bin/com/myapp
I generally recommend reserving ENTRYPOINT for a wrapper script that does some first-time setup, then runs exec "$#" to run a normal CMD. There's an alternate pattern of giving a complete command in ENTRYPOINT, and using CMD to provide its arguments. In both of these cases ENTRYPOINT needs to be JSON-array syntax, not shell syntax.
ENTRYPOINT ["java", "com.myapp.HelloWorld1"] # <-- JSON-array syntax
CMD ["-argument", "to-program-1"]
docker run myapp-image \
-argument=different -options
but it's harder to make that image do something else
docker run \
--entrypoint ls \ # <-- first word of the command is before the image name
myapp-image \
-l bin/com/myapp # <-- and the rest after
docker run \
--entrypoint java \
myapp-image \
com.myapp.HelloWorld2
Your original Dockerfile will probably work if you change the ENTRYPOINT line from shell to JSON-array syntax; using shell syntax will cause the CMD part to be ignored (including a command passed after the docker run image-name). You might find it easier to make one complete application invocation be the default and include the java command if you need to run the other.

How to call java main class from inside docker image using argument parameter

I have one apps which contains 10 java main class . Each main class has own responsibility.
I want to call each class in docker using class name parameter.
My Docker Image like below.
FROM azul/zulu-openjdk-alpine:11
ADD xyzproject/target/abc.jar abc.jar
CMD ["java", "-cp", "abc.jar" ,"Class1"]
I want to run multiple class using docker run argument parameter
Please suggest and help me to resolved
You can supply an alternate CMD when you launch the container:
docker run ... xyzproject/abc \
java -cp abc.jar Class2
The Compose command: and Kubernetes Pod args: similarly replace the CMD part.
If the java command is too involved, you can write a wrapper script to launch each embedded application:
#!/bin/sh
# run_class3.sh
exec java -cp abc.jar Class3 "$#"
docker run ... xyzproject/abc \
./run_class3.sh

How to run jar files sequentially from a shell script

I am trying to run two java application one after other in my docker container.
In my dockerfile i have specified invoker.sh as the entry point.
ENTRYPOINT ["sh", "/opt/invoker.sh"]
Then i use this script to run two jar files.
#!/bin/sh
java -jar loader.jar
java -jar service.jar
but this does not work. It gives
Error: Unable to access jarfile javaimpl-loader.jar
and only the service.jar is executed. When i tried echo $(ls) it shows that both the jar files are there.
but if i change the script to
#!/bin/sh
echo $(java -jar loader.jar)
java -jar service.jar
then both the jars work. Why cant i use the 1st script. any help regarding this highly apreciated.
It appears the first example is being treated as a single line, you could work with that. Also, I would prefer bash to /bin/sh. Like,
#!/usr/bin/env bash
java -jar loader.jar && java -jar service.jar

Specify Java Location for Gatling

I am running Gatling on Centos server. The Server has Java 1.7 installed which is not supported by Gatling 2.2 and I am not allowed to update Java version. I was wondering if there was a way to specify java location in gatling configuration to run from a specific Java installation and not from /usr/bin or /usr/sbin. Thanks in advance.
Regards,
AB
You could export JAVA_HOME=/<your-path> before running gatling.
Assuming you're using the gatling.sh script to launch Gatling, you can just edit that script to refer to whatever installation of the JDK that you want. You can set a local JAVA_HOME value and also prefix the calls to java executable with the full path of your JDK 8 installation.
For example, near the end of the shell script, something like this:
JAVA_HOME=/path/to/JDK8
# Run the compiler
${JAVA_HOME}/bin/java java $COMPILER_OPTS -cp "$COMPILER_CLASSPATH" io.gatling.compiler.ZincCompiler -ccp "$COMPILATION_CLASSPATH" "$#" 2> /dev/null
# Run Gatling
${JAVA_HOME}/bin/java $JAVA_OPTS -cp "$GATLING_CLASSPATH" io.gatling.app.Gatling "$#"

Categories

Resources