How it works...

Let's understand our first Dockerfile:

FROM openjdk:8-jdk

The FROM keyword will ask Docker to pull the openjdk:8-jdk image, but what does this mean?

This means that there's a registry somewhere where Docker will find prebuilt images. If there's no image registry in your local environment, it will search for it in Docker Hub, the official and public Docker registry in the cloud.

When you say that you are using a pre-built image, this means that you don't need to build the whole Linux container from scratch. There's already a template that you can rely on:

ENV GLASSFISH_HOME /usr/local/glassfish
ENV PATH ${GLASSFISH_HOME}/bin:$PATH
ENV GLASSFISH_PKG glassfish-5.1.0.zip
ENV GLASSFISH_URL https://www.eclipse.org/downloads/download.php?file=/glassfish/glassfish-5.1.0.zip&r=1

RUN mkdir -p ${GLASSFISH_HOME}

WORKDIR ${GLASSFISH_HOME}

Here are just some environment variables to help with the coding process:

RUN set -x \
&& curl -fSL ${GLASSFISH_URL} -o ${GLASSFISH_PKG} \
&& unzip -o $GLASSFISH_PKG \
&& rm -f $GLASSFISH_PKG \
&& mv glassfish5/* ${GLASSFISH_HOME} \
&& rm -Rf glassfish5

The RUN clause in Dockerfiles executes some bash commands inside the container when it has been created. Here, GlassFish is being downloaded and then prepared in the container:

RUN addgroup glassfish_grp \
&& adduser --system glassfish \
&& usermod -G glassfish_grp glassfish \
&& chown -R glassfish:glassfish_grp ${GLASSFISH_HOME} \
&& chmod -R 777 ${GLASSFISH_HOME}

For safety, we define the user that will hold the permissions for GlassFish files and processes:

COPY docker-entrypoint.sh /
RUN chmod +x /docker-entrypoint.sh

Here, we are including a bash script inside the container so that we can perform some GlassFish administrative tasks:

#!/bin/bash

if [[ -z $ADMIN_PASSWORD ]]; then
ADMIN_PASSWORD=$(date| md5sum | fold -w 8 | head -n 1)
echo "##########GENERATED ADMIN PASSWORD: $ADMIN_PASSWORD
##########"
fi

echo "AS_ADMIN_PASSWORD=" > /tmp/glassfishpwd
echo "AS_ADMIN_NEWPASSWORD=${ADMIN_PASSWORD}" >> /tmp/glassfishpwd

asadmin --user=admin --passwordfile=/tmp/glassfishpwd change-admin-password --domain_name domain1
asadmin start-domain

echo "AS_ADMIN_PASSWORD=${ADMIN_PASSWORD}" > /tmp/glassfishpwd

asadmin --user=admin --passwordfile=/tmp/glassfishpwd enable-secure-admin
asadmin --user=admin stop-domain
rm /tmp/glassfishpwd

exec "$@"

After copying the bash file into the container, we can go to the final block:

USER glassfish

ENTRYPOINT ["/docker-entrypoint.sh"]

EXPOSE 4848 8080 8181
CMD ["asadmin", "start-domain", "-v"]

From the preceding code, we can see the following:

Now, let's understand our second Dockerfile:

FROM eldermoraes/gf-jakartaee-jdk8

We need to take the same considerations regarding the prebuilt image into account, but here, the image was made by you. Congratulations!

ENV DEPLOYMENT_DIR ${GLASSFISH_HOME}/glassfish/domains/domain1/autodeploy/

Here, we are building an environment variable to help with the deployment process. This is done in the same way as it's done for Linux systems:

COPY app.war ${DEPLOYMENT_DIR}

This COPY command will literally copy the app.war file to the folder defined in the DEPLOYMENT_DIR environment variable.

From here, you are ready to build an image and create a container. The image builder is self-explanatory:

docker build -t eldermoraes/gf-jakartaee-cookbook .

Let's check the docker run command:

docker run -d --name gf-jakartaee-cookbook \
-h gf-jakartaee-cookbook \
-p 80:8080 \
-p 4848:4848 \
-p 8686:8686 \
-p 8009:8009 \
-p 8181:8181 \
eldermoraes/gf-jakartaee-cookbook

If we break this down, this is what the various elements of the command mean: