Skip to content

Instantly share code, notes, and snippets.

@wreulicke
Last active December 13, 2022 11:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wreulicke/3bf5db367e7a5df1c3e896119657eff0 to your computer and use it in GitHub Desktop.
Save wreulicke/3bf5db367e7a5df1c3e896119657eff0 to your computer and use it in GitHub Desktop.
quarkus getting started
#!/bin/sh
# Detected container limits
# If found these are exposed as the following environment variables:
#
# - CONTAINER_MAX_MEMORY
# - CONTAINER_CORE_LIMIT
#
# This script is meant to be sourced.
max_unbounded() {
cat /proc/meminfo | grep 'MemTotal:' | awk '{print $2*1024}'
}
container_memory() {
# High number which is the max limit unit which memory is supposed to be
# unbounded.
local mem_file="/sys/fs/cgroup/memory/memory.limit_in_bytes"
local max_mem_unbounded="$(max_unbounded)"
if [ -r "${mem_file}" ]; then
local max_mem="$(cat ${mem_file})"
if [ ${max_mem} -lt ${max_mem_unbounded} ]; then
echo "${max_mem}"
fi
fi
}
min() {
printf "%s\n" "$@" | sort -g | head -n1
}
local max_mem="$(container_memory)"
if [ x$max_mem != x ]; then
export CONTAINER_MAX_MEMORY="$max_mem"
fi
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/s2i
container=oci
HOME=/home/jboss
JAVA_HOME=/usr/lib/jvm/java-17
JAVA_VENDOR=openjdk
JAVA_VERSION=17
JBOSS_CONTAINER_OPENJDK_JDK_MODULE=/opt/jboss/container/openjdk/jdk
AB_PROMETHEUS_JMX_EXPORTER_CONFIG=/opt/jboss/container/prometheus/etc/jmx-exporter-config.yaml
JBOSS_CONTAINER_PROMETHEUS_MODULE=/opt/jboss/container/prometheus
JBOSS_CONTAINER_MAVEN_36_MODULE=/opt/jboss/container/maven/36/
MAVEN_VERSION=3.6
S2I_SOURCE_DEPLOYMENTS_FILTER=*.jar
JBOSS_CONTAINER_S2I_CORE_MODULE=/opt/jboss/container/s2i/core/
JBOSS_CONTAINER_JAVA_PROXY_MODULE=/opt/jboss/container/java/proxy
JBOSS_CONTAINER_JAVA_JVM_MODULE=/opt/jboss/container/java/jvm
JBOSS_CONTAINER_UTIL_LOGGING_MODULE=/opt/jboss/container/util/logging/
JBOSS_CONTAINER_MAVEN_DEFAULT_MODULE=/opt/jboss/container/maven/default/
JBOSS_CONTAINER_MAVEN_S2I_MODULE=/opt/jboss/container/maven/s2i
JAVA_DATA_DIR=/deployments/data
JBOSS_CONTAINER_JAVA_RUN_MODULE=/opt/jboss/container/java/run
JBOSS_CONTAINER_JAVA_S2I_MODULE=/opt/jboss/container/java/s2i
JBOSS_IMAGE_NAME=ubi8/openjdk-17
JBOSS_IMAGE_VERSION=1.14
LANG=C.utf8
LANGUAGE=en_US:en
JAVA_OPTS=-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager
JAVA_APP_JAR=/deployments/quarkus-run.jar
#!/bin/sh
# =================================================================
# Detect whether running in a container and set appropriate options
# for limiting Java VM resources
#
# Usage: JAVA_OPTS="$(java-default-options.sh)"
# Env Vars respected:
# JAVA_OPTIONS: Checked for already set options. Deprecated, use JAVA_OPTS.
# JAVA_OPTS: Checked for already set options
# JAVA_INITIAL_MEM_RATIO: Ratio of maximum memory to use for initial heap size
# (i.e. -Xms). Defaults to 25 (i.e -Xms=-Xmx/4).
# JAVA_MAX_INITIAL_MEM: The maximum value of the initial heap size, defaults to 4G.
# JAVA_MAX_MEM_RATIO: Ratio use to calculate a default maximum Memory, in percent.
# E.g. the default value "50" implies that 50% of the Memory
# given to the container is used as the maximum heap memory with
# '-Xmx'. It is a heuristic and should be better backed up with real
# experiments and measurements.
# For a good overviews what tuning options are available -->
# https://youtu.be/Vt4G-pHXfs4
# https://www.youtube.com/watch?v=w1rZOY5gbvk
# https://vimeo.com/album/4133413/video/181900266
# Also note that heap is only a small portion of the memory used by a JVM. There are lot
# of other memory areas (metadata, thread, code cache, ...) which addes to the overall
# size. There is no easy solution for this, 50% seems to be are reasonable compromise.
# However, when your container gets killed because of an OOM, then you should tune
# the absolute values
#
__DEFAULT_JAVA_MAX_MEM_RATIO=50
__DEFAULT_JAVA_INITIAL_MEM_RATIO=25
__DEFAULT_JAVA_MAX_INITIAL_MEM=4096
# stubs for jvm specific overrides
jvm_specific_options() {
:
}
jvm_specific_diagnostics() {
:
}
# Include overridden jvm_specific_*() functions
if [ -f "${JBOSS_CONTAINER_OPENJDK_JDK_MODULE}/jvm-options" ]; then
source "${JBOSS_CONTAINER_OPENJDK_JDK_MODULE}/jvm-options"
fi
initialize_container_limits() {
# we can't run without limits
source ${JBOSS_CONTAINER_JAVA_JVM_MODULE}/container-limits
}
# Check for memory options and calculate a sane default if not given
max_memory() {
# Check whether -Xmx is already given in JAVA_OPTIONS. Then we dont
# do anything here
# XXX: I think this should be removed. If folks want to hard code max/min,
# then they can set the ratios to zero and set the options in JAVA_OPTS_APPEND.
if echo "${JAVA_OPTS:-${JAVA_OPTIONS}}" | grep -q -- "-Xmx"; then
return
fi
# Check if explicitely disabled
if [ "x$JAVA_MAX_MEM_RATIO" = "x0" ]; then
return
fi
# Check for the 'real memory size' and caluclate mx from a ratio
# given (default is 50%)
if [ "x$CONTAINER_MAX_MEMORY" != x ]; then
local max_mem="${CONTAINER_MAX_MEMORY}"
local ratio=${JAVA_MAX_MEM_RATIO:-${__DEFAULT_JAVA_MAX_MEM_RATIO}}
local mx=$(echo "${max_mem} ${ratio} 1048576" | awk '{printf "%d\n" , ($1*$2)/(100*$3) + 0.5}')
echo "-Xmx${mx}m"
fi
}
# Check for memory options and calculate a sane default if not given
initial_memory() {
# Check whether -Xms is already given in JAVA_OPTS. Then we dont
# do anything here
# XXX: I think this should be removed. If folks want to hard code max/min,
# then they can set the ratios to zero and set the options in JAVA_OPTS_APPEND.
if echo "${JAVA_OPTS:-${JAVA_OPTIONS}}" | grep -q -- "-Xms"; then
return
fi
# Check if explicitly disabled
if [ "x$JAVA_INITIAL_MEM_RATIO" = "x0" ]; then
return
fi
# Check for the 'real memory size' and calculate ms from a ratio
# given (default is 25%)
if [ "x$CONTAINER_MAX_MEMORY" != x ]; then
local max_mem="${CONTAINER_MAX_MEMORY}"
local max_ratio=${JAVA_MAX_MEM_RATIO:-${__DEFAULT_JAVA_MAX_MEM_RATIO}}
local initial_ratio=${JAVA_INITIAL_MEM_RATIO:-${__DEFAULT_JAVA_INITIAL_MEM_RATIO}}
local ms=$(echo "${max_mem} ${max_ratio} ${initial_ratio} 1048576" | awk '{printf "%d\n" , ($1*(($2*$3)/10000))/$4 + 0.5}')
local max_initial_memory=${JAVA_MAX_INITIAL_MEM:-${__DEFAULT_JAVA_MAX_INITIAL_MEM}}
if [ "${ms}" -lt "${max_initial_memory}" ] ; then
echo "-Xms${ms}m"
else
echo "-Xms${max_initial_memory}m"
fi
fi
}
# Switch on diagnostics except when switched off
diagnostics() {
if [ "x$JAVA_DIAGNOSTICS" != "x" ]; then
echo "$(jvm_specific_diagnostics)"
fi
}
gc_config() {
local minHeapFreeRatio=${GC_MIN_HEAP_FREE_RATIO:-10}
local maxHeapFreeRatio=${GC_MAX_HEAP_FREE_RATIO:-20}
local timeRatio=${GC_TIME_RATIO:-4}
local adaptiveSizePolicyWeight=${GC_ADAPTIVE_SIZE_POLICY_WEIGHT:-90}
local gcOptions="${GC_CONTAINER_OPTIONS:--XX:+UseParallelGC}"
# for compat reasons we don't set a default value for metaspaceSize
local metaspaceSize
# We also don't set a default value for maxMetaspaceSize
local maxMetaspaceSize=${GC_MAX_METASPACE_SIZE}
if [ -n "${GC_METASPACE_SIZE}" ]; then
metaspaceSize=${GC_METASPACE_SIZE}
if [ -n "${maxMetaspaceSize}" ]; then
# clamp the max size of metaspaceSize to be <= maxMetaspaceSize
if [ "${metaspaceSize}" -gt "${maxMetaspaceSize}" ]; then
metaspaceSize=${maxMetaspaceSize}
fi
fi
fi
local allOptions="$(jvm_specific_options) "
allOptions+="${gcOptions} "
allOptions+="-XX:MinHeapFreeRatio=${minHeapFreeRatio} "
allOptions+="-XX:MaxHeapFreeRatio=${maxHeapFreeRatio} "
allOptions+="-XX:GCTimeRatio=${timeRatio} "
allOptions+="-XX:AdaptiveSizePolicyWeight=${adaptiveSizePolicyWeight} "
# if no value was specified for maxMetaSpaceSize we should skip passing it entirely
if [ -n "${maxMetaspaceSize}" ]; then
allOptions+="-XX:MaxMetaspaceSize=${maxMetaspaceSize}m "
fi
if [ -n "${metaspaceSize}" ]; then
allOptions+="-XX:MetaspaceSize=${metaspaceSize}m "
fi
echo "${allOptions}"
}
error_handling() {
echo "-XX:+ExitOnOutOfMemoryError"
}
initialize_container_limits > /dev/null
## Echo options, trimming trailing and multiple spaces
echo "$(initial_memory) $(max_memory) $(gc_config) $(diagnostics) $(error_handling)" | awk '$1=$1'
#!/bin/bash
# Fail on a single failed command
set -eo pipefail
source "$JBOSS_CONTAINER_UTIL_LOGGING_MODULE/logging.sh"
if [ "${SCRIPT_DEBUG}" = "true" ] ; then
set -x
log_info "Script debugging is enabled, allowing bash commands and their arguments to be printed as they are executed"
fi
# ==========================================================
# Generic run script for running arbitrary Java applications
#
# Source and Documentation can be found
# at https://github.com/fabric8io/run-java-sh
#
# ==========================================================
# Error is indicated with a prefix in the return value
check_error() {
local msg=$1
if echo ${msg} | grep -q "^ERROR:"; then
log_error ${msg}
exit 1
fi
}
# Try hard to find a sane default jar-file
auto_detect_jar_file() {
local dir=$1
# Filter out temporary jars from the shade plugin which start with 'original-'
local old_dir=$(pwd)
cd ${dir}
if [ $? = 0 ]; then
local nr_jars=`ls *.jar 2>/dev/null | grep -v '^original-' | wc -l | tr -d '[[:space:]]'`
if [ ${nr_jars} = 1 ]; then
ls *.jar | grep -v '^original-'
exit 0
fi
log_error "Neither \$JAVA_MAIN_CLASS nor \$JAVA_APP_JAR is set and ${nr_jars} JARs found in ${dir} (1 expected)"
cd ${old_dir}
else
log_error "No directory ${dir} found for auto detection"
fi
}
# Check directories (arg 2...n) for a jar file (arg 1)
get_jar_file() {
local jar=$1
shift;
if [ "${jar:0:1}" = "/" ]; then
if [ -f "${jar}" ]; then
echo "${jar}"
else
log_error "No such file ${jar}"
fi
else
for dir in $*; do
if [ -f "${dir}/$jar" ]; then
echo "${dir}/$jar"
return
fi
done
log_error "No ${jar} found in $*"
fi
}
load_env() {
# Configuration stuff is read from this file
local run_env_sh="run-env.sh"
# Load default default config
if [ -f "${JBOSS_CONTAINER_JAVA_RUN_MODULE}/${run_env_sh}" ]; then
source "${JBOSS_CONTAINER_JAVA_RUN_MODULE}/${run_env_sh}"
fi
# Check also $JAVA_APP_DIR. Overrides other defaults
# It's valid to set the app dir in the default script
if [ -z "${JAVA_APP_DIR}" ]; then
# XXX: is this correct? This is defaulted above to /deployments. Should we
# define a default to the old /opt/java-run?
JAVA_APP_DIR="${JBOSS_CONTAINER_JAVA_RUN_MODULE}"
else
if [ -f "${JAVA_APP_DIR}/${run_env_sh}" ]; then
source "${JAVA_APP_DIR}/${run_env_sh}"
fi
fi
export JAVA_APP_DIR
# Read in container limits and export the as environment variables
if [ -f "${JBOSS_CONTAINER_JAVA_JVM_MODULE}/container-limits" ]; then
source "${JBOSS_CONTAINER_JAVA_JVM_MODULE}/container-limits"
fi
# JAVA_LIB_DIR defaults to JAVA_APP_DIR
export JAVA_LIB_DIR="${JAVA_LIB_DIR:-${JAVA_APP_DIR}}"
if [ -z "${JAVA_MAIN_CLASS}" ] && [ -z "${JAVA_APP_JAR}" ]; then
JAVA_APP_JAR="$(auto_detect_jar_file ${JAVA_APP_DIR})"
check_error "${JAVA_APP_JAR}"
fi
if [ "x${JAVA_APP_JAR}" != x ]; then
local jar="$(get_jar_file ${JAVA_APP_JAR} ${JAVA_APP_DIR} ${JAVA_LIB_DIR})"
check_error "${jar}"
export JAVA_APP_JAR=${jar}
else
export JAVA_MAIN_CLASS
fi
}
# Check for standard /opt/run-java-options first, fallback to run-java-options in the path if not existing
run_java_options() {
if [ -f "/opt/run-java-options" ]; then
echo `sh /opt/run-java-options`
else
type -p run-java-options >/dev/null 2>&1
if [ $? = 0 ]; then
echo `run-java-options`
fi
fi
}
# Combine all java options
get_java_options() {
local java_opts
local debug_opts
if [ -f "${JBOSS_CONTAINER_JAVA_JVM_MODULE}/java-default-options" ]; then
java_opts=$(${JBOSS_CONTAINER_JAVA_JVM_MODULE}/java-default-options)
fi
if [ -f "${JBOSS_CONTAINER_JAVA_JVM_MODULE}/debug-options" ]; then
debug_opts=$(${JBOSS_CONTAINER_JAVA_JVM_MODULE}/debug-options)
fi
if [ -f "${JBOSS_CONTAINER_JAVA_PROXY_MODULE}/proxy-options" ]; then
source "${JBOSS_CONTAINER_JAVA_PROXY_MODULE}/proxy-options"
proxy_opts="$(proxy_options)"
fi
# Normalize spaces with awk (i.e. trim and elimate double spaces)
echo "${JAVA_OPTS} $(run_java_options) ${debug_opts} ${proxy_opts} ${java_opts} ${JAVA_OPTS_APPEND}" | awk '$1=$1'
}
# Read in a classpath either from a file with a single line, colon separated
# or given line-by-line in separate lines
# Arg 1: path to claspath (must exist), optional arg2: application jar, which is stripped from the classpath in
# multi line arrangements
format_classpath() {
local cp_file="$1"
local app_jar="$2"
local wc_out=`wc -l $1 2>&1`
if [ $? -ne 0 ]; then
log_error "Cannot read lines in ${cp_file}: $wc_out"
exit 1
fi
local nr_lines=`echo $wc_out | awk '{ print $1 }'`
if [ ${nr_lines} -gt 1 ]; then
local sep=""
local classpath=""
while read file; do
local full_path="${JAVA_LIB_DIR}/${file}"
# Don't include app jar if include in list
if [ x"${app_jar}" != x"${full_path}" ]; then
classpath="${classpath}${sep}${full_path}"
fi
sep=":"
done < "${cp_file}"
echo "${classpath}"
else
# Supposed to be a single line, colon separated classpath file
cat "${cp_file}"
fi
}
# Fetch classpath from env or from a local "run-classpath" file
get_classpath() {
local cp_path="."
if [ "x${JAVA_LIB_DIR}" != "x${JAVA_APP_DIR}" ]; then
cp_path="${cp_path}:${JAVA_LIB_DIR}"
fi
if [ -z "${JAVA_CLASSPATH}" ] && [ "x${JAVA_MAIN_CLASS}" != x ]; then
if [ "x${JAVA_APP_JAR}" != x ]; then
cp_path="${cp_path}:${JAVA_APP_JAR}"
fi
if [ -f "${JAVA_LIB_DIR}/classpath" ]; then
# Classpath is pre-created and stored in a 'run-classpath' file
cp_path="${cp_path}:`format_classpath ${JAVA_LIB_DIR}/classpath ${JAVA_APP_JAR}`"
else
# No order implied
cp_path="${cp_path}:${JAVA_APP_DIR}/*"
fi
elif [ "x${JAVA_CLASSPATH}" != x ]; then
# Given from the outside
cp_path="${JAVA_CLASSPATH}"
fi
echo "${cp_path}"
}
# Set process name if possible
get_exec_args() {
if [ "x${JAVA_APP_NAME}" != x ]; then
echo "-a '${JAVA_APP_NAME}'"
fi
}
# Ensure that the running UID has the "jboss" passwd metadata
# XXX: Maybe we should make this an entrypoint for the image?
function configure_passwd() {
# OPENJDK-533: this file is only writeable if the image uses the
# nss_wrapper module. ubi8/openjdk-17 does not.
if [ -w "$HOME/passwd" ]; then
sed "/^jboss/s/[^:]*/$(id -u)/3" /etc/passwd > "$HOME/passwd"
fi
}
# Start JVM
startup() {
# Initialize environment
load_env
configure_passwd
local args
cd ${JAVA_APP_DIR}
if [ "x${JAVA_MAIN_CLASS}" != x ] ; then
args="${JAVA_MAIN_CLASS}"
else
args="-jar ${JAVA_APP_JAR}"
fi
log_info "exec $(get_exec_args) java $(get_java_options) -cp \"$(get_classpath)\" ${args} $*"
exec $(get_exec_args) java $(get_java_options) -cp "$(get_classpath)" ${args} $*
}
# =============================================================================
# Fire up
startup $*
#!/bin/bash
# Command line arguments given to this script
args="$*"
source "${JBOSS_CONTAINER_UTIL_LOGGING_MODULE}/logging.sh"
source "${JBOSS_CONTAINER_S2I_CORE_MODULE}/s2i-core"
# include our s2i_core_*() overrides/extensions
source "${JBOSS_CONTAINER_JAVA_S2I_MODULE}/s2i-core-hooks"
# Global S2I variable setup
s2i_core_env_init
# CLOUD-3387: RHEL7-based images enable maven in the runtime environment. This
# is not needed for RHEL8-based images.
if test -r "${JBOSS_CONTAINER_MAVEN_DEFAULT_MODULE}/scl-enable-maven"; then
source "${JBOSS_CONTAINER_MAVEN_DEFAULT_MODULE}/scl-enable-maven"
fi
JAVA_OPTS="${JAVA_OPTS:-${JAVA_OPTIONS}}"
if [ -f "${JBOSS_CONTAINER_JOLOKIA_MODULE}/jolokia-opts" ]; then
# Always include jolokia-opts, which can be empty if switched off via env
JAVA_OPTS="${JAVA_OPTS} $(${JBOSS_CONTAINER_JOLOKIA_MODULE}/jolokia-opts)"
fi
if [ -f "${JBOSS_CONTAINER_PROMETHEUS_MODULE}/prometheus-opts" ]; then
JAVA_OPTS="${JAVA_OPTS} $(source ${JBOSS_CONTAINER_PROMETHEUS_MODULE}/prometheus-opts && get_prometheus_opts)"
fi
export JAVA_OPTS
export JAVA_OPTIONS="$JAVA_OPTS"
if [ -f "${S2I_TARGET_DEPLOYMENTS_DIR}/bin/run.sh" ]; then
echo "Starting the application using the bundled ${S2I_TARGET_DEPLOYMENTS_DIR}/bin/run.sh ..."
exec ${DEPLOYMENTS_DIR}/bin/run.sh $args ${JAVA_ARGS}
else
echo "Starting the Java application using ${JBOSS_CONTAINER_JAVA_RUN_MODULE}/run-java.sh $args..."
exec "${JBOSS_CONTAINER_JAVA_RUN_MODULE}/run-java.sh" $args ${JAVA_ARGS}
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment