# This Dockerfile will build an image to run a MVS38J system based
# on my copy of the TK4- system.
#
# Runs hercules under uid 6001 (named hercules) to keep it clear of normal
# host system uids starting in the 1000 range.
#
# >>>> You M U S T change <<<<<
#  globally change tk4-minus to the directory name your mvs3.8j system
#  lives under. And that dir must be directly under the dir with this
#  Dockerfile.
#
# In the container I place my mvs38j install under /home/hercules/tk4-minus
# which is set as an environment variable in this dockerfile and used
# everywhere in the dockerfile EXCEPT
# EXCEPT for the CMD and HEALTHCHECK where a dockerfile variable
# should not be used.
# The environment conf file used by all teh scripts copied into
# the container should be updated to match anything you change here.
#
# Build with one of the two below, depending upon what you use
# (you may change the name from mvs38j of course)
#    docker build -t localhost/mvs38j .
#    podman build -t localhost/mvs38j .
#
# Can be run to test it with (once built of course) 
# Adjust the timezone offset that will be uodated in the config file
# for your location is needed.
#    docker run --memory=250m --cpus="0.5" --rm -d --name mvstest \
#      -p 3270:3270/tcp -p 3505:3505/tcp \
#      -e "MVSTZOFFSET=+1100" \
#      localhost/mvs38j

# ============================================================
# The first block --- create a temporary image
# IMPORTANT name it (I am naming it 'build') so all those
# messy layers we created can be copied from the 'build'
# image to the final container image as a single layer.
# (I can save 500Mb in image size this way).
# Building as a named temporary image lets us in a later stage
# of this file 'copy' everything we have done under /home/hercules
# in the 'build' image to the final image as a single layer.
# ============================================================
#
# I will mainly run this on Debian12 and Debian13 servers so
# use lowest common base image.
#
FROM debian:12-slim AS build

MAINTAINER Mark <user@example.com>

# For documentatin you should update the version
LABEL version="1.01"
LABEL hercules_website="http://www.hercules-390.eu/"
LABEL tk3_website="http://bsp-gmbh.com/turnkey/"

# Where my mvs3.8j system goes WITHIN THE CONTAINER file structure
# >>>> Must be under /home/hercules as that is the user we create  <<<<<
# IN THE SCRIPTS MATCH THIS
ENV HERCULES_DIR /home/hercules/tk4-minus

# Set uid to 6001 to keep it well away from existing docker host uids
# We need this in the 'build' image so we can chown/chmod things before
# they are copied to the final image.
RUN useradd hercules -u 6001 -U -c "Used to run the hercules system"

# where we generate workfiles on the image filesystem
# also the home filesystem when 'docker exec -it <imageid> /bin/bash' is run
WORKDIR /var/tmp

# --------- documentation block ----------
# These are the packages required (commands run much later on)
# for each distro type. This example file uses Debian:12-slim
# in the commands later down so uses the debian packages.
# 
# For rhel/fedora
#RUN microdnf -y install coreutils x3270-text screen telnet procps-ng net-tools nmap-ncat which vim-minimal hercules && microdnf clean all
#
# For Debian
# must do the update to get the package list or all packages are not found
# "which" is in "debianutils", the "su" command is in util-linux
#RUN apt -y update && apt -y install c3270 screen telnet procps net-tools netcat-openbsd vim-tiny util-linux debianutils curl hercules && useradd hercules -u 6001 -U -c "Used to run the hercules system" 
# --------- end documentation block ----------

RUN mkdir -p $HERCULES_DIR
# COPY src-onlocalfilesystem dest-onimagefilesystem
# no * after first copy will keep the directory structure
# On docker dev machine files are directly under docker build dir

# hands-off startup script
COPY ./container_scripts/container_start_system.sh $HERCULES_DIR/container_start_system.sh

# in a container the initial command must never exit, so we need a wrapper
# that runs forever (in a very long sleep loop at the end)...
# and does the initial customisations
COPY ./container_scripts/container_start_system_wrapper.sh $HERCULES_DIR/container_start_system_wrapper.sh

# (2) copy the entire mvs38j directory structure into the container
# My mvs38j directory structure is under subdir tk4-minus, copy all to desired container dir
# your hercules CONFIG file should be under here somewhere also
COPY ./tk4-minus/ $HERCULES_DIR/

# set correct owner and we need them executable
RUN chown -R hercules:hercules $HERCULES_DIR
RUN chmod 755 $HERCULES_DIR/container_start_system.sh $HERCULES_DIR/container_start_system_wrapper.sh 

# Copy the healthcheck script in, healthceck entry defined much later on
COPY ./container_scripts/container_healthcheck.sh $HERCULES_DIR/container_healthcheck.sh
RUN chmod 755 $HERCULES_DIR/container_healthcheck.sh 

# ============================================================
# The second block --- create the final image we will use
# Now we have a final layer (well lots of layers) cached and
# mamed 'build' we will create a new image from the debian12
# slim image and copy across from the cached image only the
# application under /home/hercules. That will copy the data as a 
# single layer (saving around 500Mb of stuff that exists in
# multiple layers because of all the copy/run steps we used 
# in creating that build image.
# ============================================================
FROM debian:12-slim 
# environment variables used by the scripts
RUN mkdir /etc/hercules_local && chmod 755 /etc/hercules_local
COPY ./container_scripts/container_environment.conf /etc/hercules_local/container_environment.conf
# packages needed
RUN apt -y update && apt -y install c3270 screen telnet procps net-tools netcat-openbsd vim-tiny util-linux debianutils curl hercules && useradd hercules -u 6001 -U -c "Used to run the hercules system" 
# copy all the stuff from the build image as one layer
COPY --from=build /home/hercules /home/hercules

# ============================================================
# Notes on how EXPOSE works, really only useful (and confusing)
# if the image is run with -P which is a bad idea anyway as you
# wil never know what host port is assigned).
# Exposed ports for docker start on the host at 32768 upward, so 
# 3270 is on the host at 32768, 3505 on the host at 32769 etc.
# Those are used if the docker run is with -P to map everything exposed;
# it is not ideal as you do not really know what is listening where.
# It is better to use docker run mapping with lowercase p such
# as -p hostip:80:80/tcp or -p 80:80/tcp so you have known host ports
# (if a ipv4 hostip: is prefixed then only ipv4 will be used, the default
# is docker will start a proxy for both ipv4 and ipv6 doubling the
# running process count so if you only need ipv4 use the host ipaddr.
#
# If EXPOSE is used docker will always start a docker-proxy for the port
# even if no -p mapping is used, so lets not use EXPOSE.
# What ports I may map are just commented here for documentation.
# EXPOSE 3270     TSO
# EXPOSE 3505     Socket card reader

# Entrypoint is normally used to do setup work before starting the app,
# ie: a script to change app passwords etc.
# CMD should be used to do the actual start of the container app
# cmd can be overwritten with docker run args, entrypoint cannot.
# cmd must be a script that never ends, if it ends the container startup
#   is considered failed, so at the end of the script go into a sleep/loop
#   but keep running.
# cmd can also be used to do lots of customisations 
# this script was copied into place in earlier steps
CMD ["/home/hercules/tk4-minus/container_start_system_wrapper.sh"]

# I have no setup needed other than what is in the script run by CMD
# so do not use the below
# ENTRYPOINT ["/bin/bash"]

# Add a healthcheck, check every 5mins (300s)
# Note 5min interval is to stop hammering the 3270 port
# with http (curl) requests to check it responds, that curl will always
# treat the response as invalid data but at least a response to test.
# The actual healthcheck script was copied in earlier.
HEALTHCHECK --interval=300s --timeout=20s --start-period=120s --retries=3 \
  CMD bash /home/hercules/tk4-minus/container_healthcheck.sh
#
# End of Dockerfile
