#Docker: Create a custom #Glassfish based enterprise application docker image

By | October 25, 2016

In the following post I am going to describe how to create a custom docker image that contains the following:
– Glassfish Application Server
– Java JDK 1.8
– A custom deployed EJB 3.1 Application

In connection with this a Postgres docker image from which we start a container with a certain database name and user to be used by the application docker image.

STEP 1: Pull from docker.io registry the Glassfish and Postgres images

Note that we already have a local registry.

STEP 2: Start new container from postgres image

Specify the following environment variables to the postgres image:
– POSTGRES_USER= a user name to be created when the postgres container is initialized
– POSTGRES_PASSWORD= a user name password to be created when the postgres container is initialized
– POSTGRES_DB= a database to be created when the postgres container is initialized and associated with the above user

This way we can create the custom parameters the EJB3 application expects to exist. The above parameters must be specified in the data source definition in the glassfish container.

STEP 3: Start a new container from glassfish image

Note: In a docker run command we can either use the alias of the image or the Image ID as the last parameter of the command. Note also that we link the container with the postgres container and we give it the alias postgres. As a result we will be able to access from this container the db with the server name postgres.

List the containers that are started in docker.


STEP 4: Customize the glassfish based application image with our own JAVA JDK.

The default image we use as a base point has a JAVA 1.7 JRE installed. We need to upgrade it to JDK 1.8 for our EJB 3.1 application.
The tricky part will start now. We will copy inside the container file-system the new JDK.
First try to identify under which devicemapper device the container file-system is mounted.

Our application container id is 2a5eb73b4c45 and as we can see there is a devicemapper that has that prefix

Copy the new Java JDK in the container filesystem:

Remove the old Java from the container filesystem:

Note that this change is only on this container. In case we start a new container from the original image all is lost. In case we stop and restart this same container the change is still there. If we need to interrupt the config at any point make sure to restart container 2a5eb73b4c45 to continue.

STEP 5: Customize the glassfish based application image with our own glassfish 3.1.2

I already have a glassfish domain under which I deployed my EJB 3.1 application. I am not going to insist on how to setup the application specific configurations and how to deploy the binary. In short the application has a JMS connection factory, several JMS queues , a data source and some other glassfish application specific settings for sign-on and security.

There are several steps to set all in order.

STEP 5.1 Copy in the container my own glassfish
I do not like the glassfish application server deployed in the default image. I need Glassfish 3.1.2 with mq support.

Remove the old glassfish from the container/image filesystem:

Copy my own glassfish 3.1.2 in the container filesystem:

STEP 5.2 Activate secure admin to the container

I want to be able to connect only on https port to the glassfish admin console.
Copy a password.txt file under glassfish3/glassfish in the container filesystem.
Content is like the following:

Then execute the following command to execute the config on the running container

After the above command is executed and we stop aqnd start the container we can access the glassfish admin console with:

STEP 5.3 Change the data source to point to the postgres container
Copy first the postgres JDBC driver postgresql-9.4.1211.jar under opt/glassfish3/glassfish/lib in the container filesystem.

Change the JDBC Connection Pool defined to be used by our application to use:

Then under Additional Properties:

Note we refer to the postgres alias we gave to the database container when we started our application container.
Note that we assumed that also the ear binary of the application was custom build to support postgres also.

STEP 5.4 Finalize the configuration and clean-up

At this point we have to do all the other configuration changes in the glassfish admin console.
Execute also a basic clean-up so we can create a new image from this running container.
– delete glassfish logs
– delete /tmp
– delete imq logs
– delete imq lock: /rootfs/opt/glassfish3/glassfish/domains/demo/imq/instances/imqbroker/lock

STEP 6 Create a new image with all the changes

Now this are some very counter intuitive steps one must perform. Due to the layered way docker framework is constructed all the changes we have done in the previous steps are visible only in the container layer.
The devicemapper mount is the container/image file-system. It means that any change to it will be carried out if a new container will be instantiated from the associated image. This also means that some changes from a running container will not be visible there. To make the changes permanent we have to save the changes from the running container and add them to a new image.

STEP 6.1 Copy files from container to host
Using docker cp we will copy the modified files we want to put in the new image to the host. This includes the entire /opt/glassfish3 directory. We are forced to do this because all the changes made from GUI of the glassfish admin console are stored only as file diffs in the container layer.

STEP 6.2 Copy files from host to the container/image filesystem
We copy the files we saved from the container back to the container/image devicemapper

STEP 6.3 Take a snapshot of current running state of the application container

With the above command we have first paused a running container with -p option, made a commit to save the entire snapshot as a docker image with a new name.

As an alternative if we had to create several layers during the creation of our image, we can flatten the image by taking a snapshot of the container and then importing it.

STEP 6.4 Save on disk the new image

The following command will actually save the devicemapper content.

STEP 6.5 Push the new image to the local private registry

STEP 7 Test the new image on a remote site

Copy to remote site and load the image

Then to start the new environment:

Where image_id is the image id of the loaded image.

STEP 8 Monitor the new application

To monitor the new application start a tail on the domain logs in the container.

Execute an interactive bash to have access to more commands, like top or ps.


One thought on “#Docker: Create a custom #Glassfish based enterprise application docker image

  1. George Voina

    Using the above method allows a very easy migration of already available test environments from a development machine. Migrating the test environment to docker images allows the QA department to start in no time work without having to do configurations of a test environment. Also with every new release of the application we just have to release a new application image for the QA to continue without interruption.