Skip to content

Commit

Permalink
#234: Docker changes related to ZIO & custom config (#279)
Browse files Browse the repository at this point in the history
Docker adjusted + dynamic config change
  • Loading branch information
lsulak authored Sep 27, 2024
1 parent ae026c8 commit 73c19b5
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 22 deletions.
62 changes: 43 additions & 19 deletions server/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,42 @@
#

# Atum Service docker file

# build via (docker root = project root):
# docker build -t absaoss/atum-service:latest \
# --build-arg BUILD_PROXY=http://my.cool.proxy.here:3128 \
# --build-arg CONFIG=./path/to/my.awesome.local.reference.conf \
# --build-arg SSL=true \
# --build-arg SSL_DNAME="CN=*.my.domain.com, OU=project1, O=mycorp, L=Johannesburg, ST=Gauteng, C=za" .
# run via
# docker run -p 8080:8080 -p 8443:8443 absaoss/atum-service:latest

# test via:
# http://localhost:8080/token/public-key
# https://localhost:8443/token/public-key
#
# Note: the JAR file is expected to be build prior the docker build process and will be eventually placed in this
# location inside the running container: `/opt/app/atum-service.jar`
#
# Note: you can specify application configuration dynamically during `docker run` command, see below.
# The application will primarily run with the configuration file provided in `/opt/config/resource.conf`,
# but if that file does not exist (i.e. wasn't supplied via `docker run` command, or its desination path was not
# `/opt/config/`, or the file you are mounting via `docker run` wasn't named as `resource.conf`), then the
# application will use # configuration that was provided during the build (i.e. the one in the JAR file).
#
# Build via (docker root = project root):
#
# docker build -t absaoss/atum-service:latest \
# --build-arg BASE_IMAGE=amazoncorretto:11.0.22 \
# --build-arg BUILD_PROXY=http://my.cool.proxy.here:3128 \
# --build-arg SSL=true \
# --build-arg LDAP_SSL_CERTS_PATH=certs/ \
# --build-arg AS_PREFIX=. \
# --build-arg SCALA_VERSION=2.13 \
# --build-arg JAR_FILE=./target/jvm-2.13/*.jar \
# --build-arg SSL_DNAME="CN=*.my.domain.com, OU=project1, O=mycorp, L=Johannesburg, ST=Gauteng, C=za" .
#
# Run [with custom config] via
#
# docker run -v /absolute/path/resource.conf:/opt/config/resource.conf \
# -p 8080:8080 -p 8443:8443 absaoss/atum-service:latest
#
# Test via
#
# http://localhost:8080/token/public-key
# https://localhost:8443/token/public-key

# Conditional Docker image creation idea: https://stackoverflow.com/a/60820156/1773349
# change to false to disable SSL
ARG SSL

# Amazon correto base image
ARG BASE_IMAGE=amazoncorretto:11.0.22

Expand All @@ -39,13 +58,15 @@ FROM $BASE_IMAGE as base

# Provide your proxy if needed, e.g. http://my.proxy.examle.com:3128
ARG BUILD_PROXY
# Override of the example application config is possible
ARG CONFIG=./src/main/resources/resource.conf

# Provide path to the directory with LDAP certs in PEM format
ARG LDAP_SSL_CERTS_PATH

# ARG SSL_DNAME is defined below in the SSL-enabled image

# In case you build the Dockerfile from another location than the default 'service' dir, provide a prefix to reach it
ARG AS_PREFIX=.

# Version of scala that server was built against
ARG SCALA_VERSION=2.13

Expand All @@ -54,8 +75,8 @@ LABEL org.opencontainers.image.authors="ABSA"
# The application's jar file
ARG JAR_FILE=${AS_PREFIX}/target/jvm-${SCALA_VERSION}/*.jar

# Add the application's jar to the container
ADD ${JAR_FILE} app.jar
# Add the application's jar to the container in location & with filename that is easily discoverable and usable
ADD ${JAR_FILE} /opt/app/atum-service.jar

ENV http_proxy=$BUILD_PROXY
ENV https_proxy=$BUILD_PROXY
Expand Down Expand Up @@ -85,16 +106,19 @@ RUN keytool -genkeypair -keyalg RSA -alias selfsigned -keysize 2048 \
-validity 365 -storepass changeit -keystore /etc/ssl/certs/selfsigned.jks -storetype JKS

EXPOSE 8080 8443
ENTRYPOINT ["java","-jar","/app.jar"]

# --- SSL=false image specifics ---
FROM base AS base-ssl-false
ENV SSL_ENABLED=false
RUN echo "This stage sets SSL=$SSL_ENABLED"

EXPOSE 8080
ENTRYPOINT ["java","-jar","/app.jar"]

# --- Final image assembly ---
FROM base-ssl-${SSL} AS final

COPY ./docker_entrypoint.sh /opt/app/docker_entrypoint.sh
RUN chmod +x /opt/app/docker_entrypoint.sh

RUN echo "Running final stage with SSL_ENABLED=$SSL_ENABLED."
ENTRYPOINT ["/opt/app/docker_entrypoint.sh"]
9 changes: 6 additions & 3 deletions server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,15 @@ sbt clean assembly

docker build -t absaoss/atum-service:latest --progress=plain --no-cache \
--build-arg BUILD_PROXY=http://zproxycloud.intra.absaafrica:80 \
--build-arg CONFIG=./src/main/resources/reference.conf \
--build-arg SSL=true \
--build-arg SSL=false \
--build-arg LDAP_SSL_CERTS_PATH=./certs \
--build-arg SSL_DNAME="CN=*.my.domain.com, OU=project1, O=mycorp, L=Johannesburg, ST=Gauteng, C=za" ./

docker run -p 8080:8080 -p 8443:8443 absaoss/atum-service:latest
# If you want to run it against AWS, you need to add AWS related credentials into the docker container, possibly via
# environment variables; but you can also run it against your a local Postgres DB (in host or another Docker container).
docker run -v /absolute/path/resource.conf:/opt/config/resource.conf \
-e AWS_ACCESS_KEY_ID="abc" -e AWS_SECRET_ACCESS_KEY="def" -e AWS_SESSION_TOKEN="xyz" \
-p 8080:8080 -p 8443:8443 absaoss/atum-service:latest

# reference.conf file has to be configured as below when running with ssl enabled
ssl {
Expand Down
27 changes: 27 additions & 0 deletions server/docker_entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#!/bin/sh

# These two are locations known and used in the Dockerfile.
CUSTOM_CONFIG_LOCATION="/opt/config/resource.conf"
JAR_LOCATION="/opt/app/atum-service.jar"

# Why `exec` - mostly for a correct termination signal handling & finishing the application.
#
# Explanation: The exec command replaces the shell process with the Java process, so the Java process (our application)
# becomes the main process (PID 1) in the container. Docker automatically sends termination signals
# (SIGTERM, SIGINT, etc.) to PID 1, so the Java process will directly receive the signals and can terminate cleanly.
#
# When you define ENTRYPOINT in a Dockerfile and it points to a shell script, as it is in our case, what actually
# happens is that the shell starts first, executes the script, and then runs whatever commands are inside that script.
# For example, without exec, the process flow looks like this:
# 1. Docker starts the container, and the shell process (/bin/sh) is launched.
# 2. The shell process begins executing this `docker_entrypoint.sh` script.
# 3. Inside the script, if you run java, the shell spawns a child process to run the java command, while the shell
# process remains the parent process (still PID 1). But what we want is our Java to have PID 1 to receive
# termination signals.
if [ -f "${CUSTOM_CONFIG_LOCATION}" ]; then
echo "Running with custom config"
exec java -Dconfig.file="${CUSTOM_CONFIG_LOCATION}" -jar "${JAR_LOCATION}"
else
echo "Running with default config"
exec java -jar "${JAR_LOCATION}"
fi

0 comments on commit 73c19b5

Please sign in to comment.