Use docker to deploy a Glassfish application

Posted on 2015-05-24 in Programmation

Recently I had to deploy an application on Glassfish. Since Glassfish is not packaged on the distribution I have on my server (Fedora Server) and I wanted to avoid to pollute my system I decided to use Docker.

In order to deploy my application correctly, I based my Dockerfile on the latest official image of glassfish from the docker hub. This image is based on debian and it supports java 8 (there is another image which support java 7).

Nothing fancy in the dockerfile. I copy the the war file in the container and set the entry points to a custom script. This script will start Glassfish, deploy the application and then restart the server in verbose mode.

## -*- docker-image-name: "aot-java" -*-
# AoT
#
# Version 1

FROM glassfish:latest

MAINTAINER Jujens "jujens@jujens.eu"

COPY aot.war /
COPY start.sh /

EXPOSE 8080

ENTRYPOINT ["/start.sh"]

Why didn't I just deploy the application in the dockerfile? In order to deploy the app, Glassfish must be running. If we used the following code to deploy the application, what would have happened?

RUN /usr/local/glassfish4/bin/asadmin start-domain
RUN /usr/local/glassfish4/bin/asadmin -u admin deploy /aot.war

Docker create a temporary container and launch the command in it. Once the server has started, the command will exit and the container will stop. Then docker will create a new temporary container and launch /usr/local/glassfish4/bin/asadmin -u admin deploy /aot.war in it. But since the first container is stopped, Glassfish is not running any more. So the deploy command fails.

If we started the server with /usr/local/glassfish4/bin/asadmin start-domain --verbose, the command would never have exited and docker would have been stuck.

So the solution is to use a custom script as entry point which will:

  • Start the server
  • Deploy the application
  • Stop the server
  • Restart it in verbose mode so this command doesn't exit and the container doesn't stop.

You can then run the container with: docker run --name <container-name> -d -p 8080:8080 <image-name>.

Here is the script:

#!/bin/sh

/usr/local/glassfish4/bin/asadmin start-domain
/usr/local/glassfish4/bin/asadmin -u admin deploy /aot.war
/usr/local/glassfish4/bin/asadmin stop-domain
/usr/local/glassfish4/bin/asadmin start-domain --verbose

Another solution would have been to simply use the default image, launch a container from it, connect to it with nsenter and deploy the war from there. But I find this method quite tricky and you have to use docker in a way that was never intended.