There are a few apps that I’ve written to help make my life a bit more convenient for me and my wife. For better or for worse, Grails was my rapid application development framework of choice for a long time. I wanted to be able to take those apps and run them within my new Docker hosting architecture.
Dockerhub is awesome. Many open source software projects have already contributed official images to Dockerhub, including Tomcat. This image allows you to configure Tomcat without having to extend the image in your own container. However, I wanted to also use the
docker build command to build a war file and copy that war file into the
$CATALINA_HOME/webapps directory, making it a ready-to-go application container.
To begin with, I created my own Dockerfile which extends the official Tomcat image:
MAINTAINER David Malone <firstname.lastname@example.org>
The Tomcat image extends the official Java Docker image, but that only gets us a JRE. In order to build a war file (or any Java artifact for that matter) we will need to pull down a JDK. The Java image happens to extend an Ubuntu image, so we can use
apt to install the necessary packages:
RUN apt-get update
RUN apt-get install -y git
RUN apt-get install -y openjdk-7-jdk
ENV JAVA_HOME /usr/lib/jvm/java-7-openjdk-amd64
The previous commands install the OpenJDK v7 JDK, and sets the JAVA_HOME environment variable, which is required by Grails in order to build my war file. I also installed the git client since I am hosting my Grails source code on github.com.
For the purposes of this post, we’ll use the grails-petclinic sample application. This app contains the Grails Wrapper. The Grails Wrapper simplifies environment setup necessary to build a Grails app by downloading the version of Grails that the wrapper was generated with. It’s recommended for use with CI build servers, last I checked, but it’s also good for ad hoc build environments such as this one. Finally, we’ll build the war file, and copy it into the Tomcat webapps directory to allow it to be automatically deployed when the container starts up:
RUN git clone https://github.com/grails-samples/grails-petclinic.git
RUN cd ./grails-petclinic && ./grailsw war
RUN cp ./grails-petclinic/target/grails-petclinic*.war /usr/local/tomcat/webapps/
CMD [“catalina.sh”, “run”]
The last line in the Dockerfile ensures that the default behavior of this Docker container is to run Tomcat. To read up more about the CMD instruction, check out the Dockerfile reference.
Now we have a Dockerfile, but we need to build it and then launch it in order to access our application. To build this container, open up your terminal and ensure that your current working directory is the one in which you created the Dockerfile. Then, execute the following command:
sudo docker build --no-cache=true -t dmalone/grails-petclinic .
I’ve found that the –no-cache=true flag is important for this style of build, because it will force it to run the
git clone command every time the image is built, thus ensuring that the latest code is always grabbed from Github.
The previous step builds the image with the name
dmalone/grails-petclinic, where dmalone is my username on Dockerhub. It’s important to note that when building your images locally, you’ll want to ensure that the username you use to build your images is the same as your username on Dockerhub, otherwise you won’t be able to upload those to Dockerhub.
Finally, we’re ready to run our application. Depending on your application’s needs, your run command may look slightly different. My
docker run command looks like this:
sudo docker run --rm -it -p 80:8080 dmalone/grails-petclinic
Since I’ve mapped the host port 80 to the Tomcat container instance’s port 8080, I can access the grails-petclinic webapp at http://<your-docker-host-ip>/grails-petclinic. It’s that simple.