Skip to content

Commit

Permalink
feature(container): Refactor Dockerfile basing on openjdk:11-jre
Browse files Browse the repository at this point in the history
Instead of using the upstream Payara image we build on the OpenJDK
image which is also used by Solr. That way we reduce image pulls.
We also optimize the domain1 configuration to be more production ready.

Relates to IQSS#5292
  • Loading branch information
poikilotherm committed Aug 23, 2021
1 parent 32d89a6 commit 5059c09
Show file tree
Hide file tree
Showing 10 changed files with 272 additions and 32 deletions.
145 changes: 118 additions & 27 deletions conf/container/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,128 @@
# THIS FILE IS TO BE USED WITH MAVEN DOCKER BUILD:
# mvn -Pcontainer clean package docker:build

FROM payara/server-full:@payara.version@-jdk11
# Using same base image as Solr (https://hub.docker.com/_/solr), reducing pulls
FROM openjdk:11-jre
LABEL maintainer="FDM FZJ <forschungsdaten@fz-juelich.de>"
# Default payara ports to expose
# 4848: admin console
# 9009: debug port (JPDA)
# 8080: http
# 8181: https
EXPOSE 4848 9009 8080 8181

ENV DATA_DIR=/data\
DOCROOT_DIR=/docroot\
METADATA_DIR=/metadata\
SECRETS_DIR=/secrets\
DUMPS_DIR=/dumps\
DOMAIN_DIR=${PAYARA_DIR}/glassfish/domains/${DOMAIN_NAME}\
JREBEL_LIB=${HOME_DIR}/jrebel/lib/libjrebel64.so\
ENV HOME_DIR="/opt/payara"
ENV PAYARA_DIR="${HOME_DIR}/appserver" \
SCRIPT_DIR="${HOME_DIR}/scripts" \
CONFIG_DIR="${HOME_DIR}/config" \
DEPLOY_DIR="${HOME_DIR}/deployments" \
DATA_DIR="/data" \
DOCROOT_DIR="/docroot" \
METADATA_DIR="/metadata" \
SECRETS_DIR="/secrets" \
DUMPS_DIR="/dumps" \
PASSWORD_FILE="${HOME_DIR}/passwordFile" \
ADMIN_USER="admin" \
ADMIN_PASSWORD="admin" \
DOMAIN_NAME="domain1" \
PAYARA_ARGS=""
ENV PATH="${PATH}:${PAYARA_DIR}/bin" \
DOMAIN_DIR="${PAYARA_DIR}/glassfish/domains/${DOMAIN_NAME}" \
JVM_ARGS="" \
MEM_MAX_RAM_PERCENTAGE="70.0" \
MEM_XSS="512k" \
PREBOOT_COMMANDS="${CONFIG_DIR}/pre-boot-commands.asadmin" \
POSTBOOT_COMMANDS="${CONFIG_DIR}/post-boot-commands.asadmin" \
DEPLOY_PROPS="" \
# Make heap dumps on OOM appear in DUMPS_DIR
JVM_ARGS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\${ENV=DUMPS_DIR}"\
ENABLE_DUMPS=0 \
JVM_DUMPS_ARGS="-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=\${ENV=DUMPS_DIR}" \
# Documenting development options (see init_3_enabledev.sh)
ENABLE_JMX=0\
ENABLE_JDWP=0\
ENABLE_JREBEL=0
ENABLE_JMX=0 \
ENABLE_JDWP=0 \
ENABLE_JREBEL=0 \
JREBEL_LIB="${HOME_DIR}/jrebel/lib/libjrebel64.so"

# Create basic pathes
ARG PAYARA_VERSION="@payara.version@"
ARG TINI_VERSION=0.19.0
ARG ESH_VERSION=0.3.1
ARG ESH_CHECKSUM=""
ARG PKGS="jq imagemagick curl unzip"
ARG ASADMIN="${PAYARA_DIR}/bin/asadmin --user=${ADMIN_USER} --passwordfile=${PASSWORD_FILE}"

### PART 1: SYSTEM ###
USER root
RUN mkdir -p ${DATA_DIR} ${METADATA_DIR} ${DOCROOT_DIR} ${SECRETS_DIR} ${DUMPS_DIR} && \
WORKDIR /
RUN true && \
# Download tini
curl -sSfL -o /tini "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini" && \
curl -sSfL -o /tini.sha256 "https://github.com/krallin/tini/releases/download/v${TINI_VERSION}/tini.sha256sum" && \
# Check and install tini
sha256sum -c /tini.sha256 && \
chmod +x /tini && \
# Create pathes
mkdir -p ${HOME_DIR} ${PAYARA_DIR} ${DEPLOY_DIR} ${CONFIG_DIR} ${SCRIPT_DIR} && \
mkdir -p ${DATA_DIR} ${METADATA_DIR} ${DOCROOT_DIR} ${SECRETS_DIR} ${DUMPS_DIR} && \
# Create user
addgroup --gid 1000 payara && \
adduser --system --uid 1000 --no-create-home --shell /bin/bash --home "${HOME_DIR}" --gecos "" --ingroup payara payara && \
echo payara:payara | chpasswd && \
# Set permissions
chown -R payara: ${HOME_DIR} && \
chown -R payara: ${DATA_DIR} ${METADATA_DIR} ${DOCROOT_DIR} ${SECRETS_DIR} ${DUMPS_DIR}

# Install prerequisites
RUN apt-get -qq update && \
apt-get -qqy install jq imagemagick curl wget unzip && \
rm -rf /var/lib/apt/lists/*

# Install esh template engine from Github
RUN wget --no-verbose -O esh https://raw.githubusercontent.com/jirutka/esh/v0.3.0/esh && \
echo 'fe030e23fc1383780d08128eecf322257cec743b esh' | sha1sum -c - && \
chmod +x esh && mv esh /usr/local/bin
RUN true && \
# Download & check esh template script
curl -sSfL -o /usr/bin/esh https://raw.githubusercontent.com/jirutka/esh/v${ESH_VERSION}/esh && \
echo '1e0bd783f930cba13d6708b11c1ac844bbb1eddd02ac1666fc10d47eb9517bd7 /usr/bin/esh' | sha256sum -c - && \
chmod +x /usr/bin/esh && \
# Download & unzip JRebel to $JREBEL_LIB = ${HOME_DIR}/jrebel/lib/libjrebel64.so (for development use)
curl -sS -f -o ${HOME_DIR}/jrebel.zip http://dl.zeroturnaround.com/jrebel-stable-nosetup.zip && \
unzip -q "${HOME_DIR}/jrebel.zip" -d "${HOME_DIR}" && \
# Install packages
apt-get update -q && \
apt-get install -qqy ${PKGS} && \
rm -rf /var/lib/apt/lists/* "${HOME_DIR}/jrebel.zip"

# Install JRebel library (for development use)
### PART 2: PAYARA ###
# After setting up system, now configure Payara
USER payara
RUN wget --no-verbose -O "${HOME_DIR}/jrebel.zip" http://dl.zeroturnaround.com/jrebel-stable-nosetup.zip && \
unzip -q "${HOME_DIR}/jrebel.zip" -d "${HOME_DIR}"
WORKDIR ${HOME_DIR}

# Download, check and install Payara
RUN curl -sSfL -o payara.zip "https://repo1.maven.org/maven2/fish/payara/distributions/payara/${PAYARA_VERSION}/payara-${PAYARA_VERSION}.zip" && \
curl -sSfL -o payara.zip.sha256 "https://repo1.maven.org/maven2/fish/payara/distributions/payara/${PAYARA_VERSION}/payara-${PAYARA_VERSION}.zip.sha256" && \
echo "$(cat payara.zip.sha256) payara.zip" | sha256sum -c - && \
unzip -q payara.zip -d ${HOME_DIR} && \
mv ${HOME_DIR}/payara5/* ${PAYARA_DIR}/ && \
rm -rf ${HOME_DIR}/payara5 payara.zip*

# Copy the system (appserver level) scripts like entrypoint, etc
COPY --chown=payara:payara maven/scripts/system ${SCRIPT_DIR}/

# TODO: refactor and make production ready
# Configure the domain to be container and production ready
RUN true && \
# Set admin password
echo "AS_ADMIN_PASSWORD=\nAS_ADMIN_NEWPASSWORD=${ADMIN_PASSWORD}" > /tmp/password-change-file.txt && \
echo "AS_ADMIN_PASSWORD=${ADMIN_PASSWORD}" >> ${PASSWORD_FILE} && \
asadmin --user=${ADMIN_USER} --passwordfile=/tmp/password-change-file.txt change-admin-password --domain_name=${DOMAIN_NAME} && \
# Start domain for configuration
${ASADMIN} start-domain ${DOMAIN_NAME} && \
# Allow access to admin with password only
${ASADMIN} enable-secure-admin && \
# List & delete memory settings from domain
for MEMORY_JVM_OPTION in $(asadmin --user=${ADMIN_USER} --passwordfile=${PASSWORD_FILE} list-jvm-options | grep "Xm[sx]\|Xss"); \
do \
${ASADMIN} delete-jvm-options $MEMORY_JVM_OPTION;\
done && \
${ASADMIN} create-jvm-options '-XX\:+UseContainerSupport:-XX\:MaxRAMPercentage=${ENV=MEM_MAX_RAM_PERCENTAGE}:-Xss${ENV=MEM_XSS}' && \
${ASADMIN} set-log-attributes com.sun.enterprise.server.logging.GFFileHandler.logtoFile=false && \
${ASADMIN} stop-domain ${DOMAIN_NAME} && \
rm -rf \
/tmp/password-change-file.txt \
${PAYARA_DIR}/glassfish/domains/${DOMAIN_NAME}/osgi-cache \
${PAYARA_DIR}/glassfish/domains/${DOMAIN_NAME}/logs

# Make docroot of Payara reside in higher level directory for easier targeting
# Due to IQSS/dataverse-kubernetes#177: create the generated pathes so they are
Expand All @@ -51,6 +137,7 @@ RUN rm -rf ${DOMAIN_DIR}/docroot && \
ln -s ${DOCROOT_DIR} ${DOMAIN_DIR}/docroot && \
mkdir -p ${DOMAIN_DIR}/generated/jsp/dataverse

### PART 3: DATAVERSE INSTALLATION ###
# Copy app and deps from assembly in proper layers
COPY --chown=payara:payara maven/deps ${DEPLOY_DIR}/dataverse/WEB-INF/lib/
COPY --chown=payara:payara maven/app ${DEPLOY_DIR}/dataverse/
Expand All @@ -62,5 +149,9 @@ RUN ln -s ${DEPLOY_DIR}/dataverse/supplements/jhove.conf ${PAYARA_DIR}/glassfish
sed -i ${PAYARA_DIR}/glassfish/domains/${DOMAIN_NAME}/config/jhove.conf -e "s:/usr/local/payara5/glassfish/domains/domain1:${PAYARA_DIR}/glassfish/domains/${DOMAIN_NAME}:g"

# Copy init and application scripts
COPY --chown=payara:payara maven/scripts ${SCRIPT_DIR}/
COPY --chown=payara:payara maven/scripts/app ${SCRIPT_DIR}/
RUN chmod +x ${SCRIPT_DIR}/*

# Set the entrypoint
ENTRYPOINT ["/tini", "--"]
CMD "${SCRIPT_DIR}/entrypoint.sh"
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ echo "# Dataverse postboot configuration for Payara" > ${DV_POSTBOOT}
# TODO: This is ugly and dirty. It leaves leftovers on the filesystem.
# It should be replaced by using proper config mechanisms sooner than later,
# like MicroProfile Config API.
for alias in rserve doi db
for alias in rserve doi
do
if [ -f ${SECRETS_DIR}/$alias/password ]; then
echo "INFO: Defining password alias for $alias"
Expand Down Expand Up @@ -93,12 +93,15 @@ env -0 | grep -z -Ee "^(dataverse|doi)_" | while IFS='=' read -r -d '' k v; do
echo "create-system-properties ${KEY}=${v}" >> ${DV_POSTBOOT}
done

# 4. Add the commands to the existing postboot file, but insert BEFORE deployment
# 4. Disable phone home. Always.
echo "disable-phone-home" >> ${DV_POSTBOOT}

# 5. Enable config dir for dealing with secrets etc.
echo "set-config-dir --directory=$SECRETS_DIR" >> ${DV_POSTBOOT}

# 6. Add the commands to the existing postboot file, but insert BEFORE deployment
echo "$(cat ${DV_POSTBOOT} | cat - ${POSTBOOT_COMMANDS} )" > ${POSTBOOT_COMMANDS}
echo "DEBUG: postboot contains the following commands:"
echo "--------------------------------------------------"
cat ${POSTBOOT_COMMANDS}
echo "--------------------------------------------------"

# 6. Disable phone home. Always.
echo "disable-phone-home" >> ${PREBOOT_COMMANDS}
File renamed without changes.
File renamed without changes.
11 changes: 11 additions & 0 deletions conf/container/scripts/system/entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#!/bin/bash

for f in ${SCRIPT_DIR}/init_* ${SCRIPT_DIR}/init.d/*; do
case "$f" in
*.sh) echo "[Entrypoint] running $f"; . "$f" ;;
*) echo "[Entrypoint] ignoring $f" ;;
esac
echo
done

exec ${SCRIPT_DIR}/startInForeground.sh $PAYARA_ARGS
62 changes: 62 additions & 0 deletions conf/container/scripts/system/init_1_generate_deploy_commands.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#!/bin/bash
################################################################################
#
# A script to append deploy commands to the post boot command file at
# $PAYARA_HOME/scripts/post-boot-commands.asadmin file. All applications in the
# $DEPLOY_DIR (either files or folders) will be deployed.
# The $POSTBOOT_COMMANDS file can then be used with the start-domain using the
# --postbootcommandfile parameter to deploy applications on startup.
#
# Usage:
# ./generate_deploy_commands.sh
#
# Optionally, any number of parameters of the asadmin deploy command can be
# specified as parameters to this script.
# E.g., to deploy applications with implicit CDI scanning disabled:
#
# ./generate_deploy_commands.sh --properties=implicitCdiEnabled=false
#
# Environment variables used:
# - $PREBOOT_COMMANDS - the pre boot command file.
# - $POSTBOOT_COMMANDS - the post boot command file.
#
# Note that many parameters to the deploy command can be safely used only when
# a single application exists in the $DEPLOY_DIR directory.
################################################################################

# Check required variables are set
if [ -z $DEPLOY_DIR ]; then echo "Variable DEPLOY_DIR is not set."; exit 1; fi
if [ -z $PREBOOT_COMMANDS ]; then echo "Variable PREBOOT_COMMANDS is not set."; exit 1; fi
if [ -z $POSTBOOT_COMMANDS ]; then echo "Variable POSTBOOT_COMMANDS is not set."; exit 1; fi

# Create pre and post boot command files if they don't exist
touch $POSTBOOT_COMMANDS
touch $PREBOOT_COMMANDS

deploy() {

if [ -z $1 ]; then
echo "No deployment specified";
exit 1;
fi

DEPLOY_STATEMENT="deploy $DEPLOY_PROPS $1"
if grep -q $1 $POSTBOOT_COMMANDS; then
echo "post boot commands already deploys $1";
else
echo "Adding deployment target $1 to post boot commands";
echo $DEPLOY_STATEMENT >> $POSTBOOT_COMMANDS;
fi
}

# RAR files first
for deployment in $(find $DEPLOY_DIR -mindepth 1 -maxdepth 1 -name "*.rar");
do
deploy $deployment;
done

# Then every other WAR, EAR, JAR or directory
for deployment in $(find $DEPLOY_DIR -mindepth 1 -maxdepth 1 ! -name "*.rar" -a -name "*.war" -o -name "*.ear" -o -name "*.jar" -o -type d);
do
deploy $deployment;
done
73 changes: 73 additions & 0 deletions conf/container/scripts/system/startInForeground.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#!/bin/bash
##########################################################################################################
#
# This script is to execute Payara Server in foreground, mainly in a docker environment.
# It allows to avoid running 2 instances of JVM, which happens with the start-domain --verbose command.
#
# Usage:
# Running
# startInForeground.sh <arguments>
# is equivalent to running
# asadmin start-domain <arguments>
#
# It's possible to use any arguments of the start-domain command as arguments to startInForeground.sh
#
# Environment variables used:
# - $ADMIN_USER - the username to use for the asadmin utility.
# - $PASSWORD_FILE - the password file to use for the asadmin utility.
# - $PREBOOT_COMMANDS - the pre boot command file.
# - $POSTBOOT_COMMANDS - the post boot command file.
# - $DOMAIN_NAME - the name of the domain to start.
# - $JVM_ARGS - extra JVM options to pass to the Payara Server instance.
# - $AS_ADMIN_MASTERPASSWORD - the master password for the Payara Server instance.
#
# This script executes the asadmin tool which is expected at ~/appserver/bin/asadmin.
#
##########################################################################################################

# Check required variables are set
if [ -z $ADMIN_USER ]; then echo "Variable ADMIN_USER is not set."; exit 1; fi
if [ -z $PASSWORD_FILE ]; then echo "Variable PASSWORD_FILE is not set."; exit 1; fi
if [ -z $PREBOOT_COMMANDS ]; then echo "Variable PREBOOT_COMMANDS is not set."; exit 1; fi
if [ -z $POSTBOOT_COMMANDS ]; then echo "Variable POSTBOOT_COMMANDS is not set."; exit 1; fi
if [ -z $DOMAIN_NAME ]; then echo "Variable DOMAIN_NAME is not set."; exit 1; fi

# The following command gets the command line to be executed by start-domain
# - print the command line to the server with --dry-run, each argument on a separate line
# - remove -read-string argument
# - surround each line except with parenthesis to allow spaces in paths
# - remove lines before and after the command line and squash commands on a single line

# Create pre and post boot command files if they don't exist
touch $POSTBOOT_COMMANDS
touch $PREBOOT_COMMANDS

OUTPUT=`${PAYARA_DIR}/bin/asadmin --user=${ADMIN_USER} --passwordfile=${PASSWORD_FILE} start-domain --dry-run --prebootcommandfile=${PREBOOT_COMMANDS} --postbootcommandfile=${POSTBOOT_COMMANDS} $@ $DOMAIN_NAME`
STATUS=$?
if [ "$STATUS" -ne 0 ]
then
echo ERROR: $OUTPUT >&2
exit 1
fi

COMMAND=`echo "$OUTPUT"\
| sed -n -e '2,/^$/p'\
| sed "s|glassfish.jar|glassfish.jar $JVM_ARGS |g"`

echo Executing Payara Server with the following command line:
echo $COMMAND | tr ' ' '\n'
echo

# Run the server in foreground - read master password from variable or file or use the default "changeit" password

set +x
if test "$AS_ADMIN_MASTERPASSWORD"x = x -a -f "$PASSWORD_FILE"
then
source "$PASSWORD_FILE"
fi
if test "$AS_ADMIN_MASTERPASSWORD"x = x
then
AS_ADMIN_MASTERPASSWORD=changeit
fi
echo "AS_ADMIN_MASTERPASSWORD=$AS_ADMIN_MASTERPASSWORD" > /tmp/masterpwdfile
exec ${COMMAND} < /tmp/masterpwdfile

0 comments on commit 5059c09

Please sign in to comment.