run-java.sh
| Usage
run-java.sh
is a universal startup script for Java applications, especially crafted for being run from within containers.
Some highlights:
-
Chooses sane default for JVM parameters based on container constraints on memory and cpus. See this research investigation by @astefanutti which explains the rational behind the parameters chosen.
-
Supports
- bash
- sh (plain bourne shell)
- ash
- dash
- ksh
zsh
is not supported yet. -
Support for switching on debugging via the environment variable
JAVA_DEBUG
-
Autodetection of JAR files within a directory
-
Support for fish-pepper so that this script can be used as a fish-pepper block
-
Integration tests for all those shells mentioned above. See the build on CircleCI for more details. Look in the "Artifacts" tab of a test run for the test results.
-
Maven artefacts for easy usage of this script in Maven projects.
The full documentation for run-java.sh
can be found in this README
Installation
run-java.sh can be used directly by copying all files from fish-pepper/run-java-sh/fp-files to a directory in your container or it can be easily included in various build systems.
Maven Builds
Maven builds can declare a dependency on
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>run-java-sh</artifactId>
<version>1.2.1</version>
</dependency>
Then, within your code the script can be obtained with
// Copy it to a destination, possibly somewhere below target/
RunShLoader.copyRunScript(new File("target/assembly/startup/"));
If you want to use this script in Docker image built with maven-docker-plugin, the startup script can be directly used by declaring a plugin dependency like:
<plugin>
<groupId>io.fabric8</groupId>
<artifactId>docker-maven-plugin</artifactId>
<version>0.26.0</version>
<dependencies>
<dependency>
<groupId>io.fabric8</groupId>
<artifactId>run-java-sh</artifactId>
<version>1.2-SNAPSHOT</version>
</dependency>
</dependencies>
</plugin>
Then when you execute plugin the run script will be placed in target/docker-extra/run-java/run-java.sh
and can be directly used e.g. in a Dockerfile for the simple Dockerfile mode:
FROM openjdk:jre
ADD target/${project.build.finalName}.jar /opt/hello-world.jar
ADD target/docker-extra/run-java/run-java.sh /opt
CMD JAVA_MAIN_CLASS=HelloWorld sh /opt/run-java.sh
You can also use this jar file directly for extracting the shell script on the fly, or even executing it:
Usage: java -jar run-java.jar <command>
with the following commands:
help : This help message
copy <file> : Write run-java.sh out to this file or directory
readme : Print the README
exec <arg> : Execute the script directly from the JVM.
Note that this will keep the current JVM running, so you end up with 2 JVMs
By default (no command) print out the content of this script
fish-pepper
fish-pepper is a Docker build composition tool based on templates. It has a concept called blocks which is a collection of templates and files to be copied into a Docker image. Blocks can also be obtained remotely from a Git repository. In order to use this startup script for fish-pepper, you need to add the following refernce to the main configuration fish-pepper.yml
in you Docker image build:
blocks:
- type: "git"
url: "https://github.com/fabric8io/run-java-sh.git"
path: "fish-pepper"
From within the Docker templates you then can reference this block as usual e.g. {{= fp.block('run-java-sh','copy.dck') }}
for adding the proper COPY
commands to your Dockerfile and copying over the run script into you Docker build directory.
For more information on fish-pepper please refer to its documentation.
Integration Test
run-java.sh
uses bats for bash integration testing.
The tests are typically fired up by using a Docker test container which contains all shells which are supported, but you can call the test locally, too.
Running test locally
- Install
bats
(e.g. viabrew install bats
on macOS) - Goto directory
test/t
- Run:
bats .
- In order to use a different shell, set the environment variable $TEST_SHELL :
TEST_SHELL=ash bats .
. This shell must be installed locally, too, of course. - You can run individual tests by calling a test file directly:
bats 01_basic.bats
Running in a Docker container
- Be sure to have a local Docker daemon running and accessible
- Then just call
test/run_all.sh
- The following environment variables can influence this script:
JDK_TAG
: Which JVM to use for testing. Should beopenjdk8
oropenjdk9
MEMORY
: A memory limit to set to the containerCPUS
: Number of cores to constraint the container toREPORT_DIR
: Directory where to store the reports. By default this in the top-levelreports/
directory.
Example:
JDK_TAG=openjdk9 MEMORY=400m CPUS=1.5 test/run_all.sh
The builder containers can be recreated from the Dockerfile in test/docker
. Look into the CircleCI build for how these containers are built.
CircleCI
The integrations tests run on CircleCI on every commit and PR. The configuration can be found in config.yml. You find the test reports in the "Artifacts" tap of a build, e.g. like here.
Currently the following combinations are tested
- OpenJDK 8 and OpenJDK 11
- Memory limits: unlimited, 160m, 400m
- CPUs: unlimited, 1.5
Releasing
Release should be performed via Maven, so that the Maven artefacts get updated properly:
mvn -Dmaven.repo.local=/tmp/clean-repo -DdevelopmentVersion=1.3-SNAPSHOT -DreleaseVersion=1.3.4 -Dtag=v1.3.4 -Prelease release:prepare
mvn -Dmaven.repo.local=/tmp/clean-repo -Prelease release:perform