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.