Docker is one the most popular tools, if not the most popular, for virtual “infrastructure”. It provides a special lightweight vm-like structure called containers that can be used for packaging, building, and deploying an application. Some of the key advantages of Docker is resource efficiency ( compared to a virtual machine), and portability: as you long as docker is there, the container will work the same way on different environments(Package Once Deploy everywhere). Because of these advantages, Docker has become a must for the build / test / deploy cycle. It’s about time for GWT developers to make Docker part of their development and build routine. In this post, we will go through how to use docker for building and deploying a GWT application. Before taking off, some basic knowledge of how Docker works is required. The Docker for Java Developpers tutorial by Zero Turnaround is a good starting point.
Building/Testing a GWT application in Docker:
Besides deploying applications, Docker can also be used to create a sandbox environment for building an application. In GWT, the environment has to have GWT libraries, Java, and maybe a build system like maven. To demonstrate this use case, we are going to use docker to build the gwt-polymer-starter-kit application. For our build, we are going to need a Docker image with maven, and Java 8:
FROM java:8 RUN \ export DEBIAN_FRONTEND=noninteractive && \ sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \ apt-get update && \ apt-get -y upgrade && \ apt-get install -y wget curl maven RUN mkdir gwt-polymer-starter-kit WORKDIR /gwt-polymer-starter-kit CMD ["mvn", "package"]
In this image, we made use of an already existing Java 8 image and added maven on the top of it. We told docker to apply mvn package on start up. We also added some linux package upgrade, since java:8 image is based on a Debian linux image. Once the command will finish, the docker container will shutdown. Finally, we are going to build and run our image using the following docker commands:
docker build -t gwidgets/polymer-starter-build .
docker run -ti --rm -v /c/GWidgets/workspace/test/gwt-polymer-starter-kit:/gwt-polymer-starter-kit --name gwt-build gwidgets/polymer-starter-build
In this way, we are making sure that our build is clean and that no other settings from other projects or from the host OS are interfering with our build.
Deploying a GWT application in Docker
A GWT application can have many forms or architectures. Some common ones are: monolithic application (single war with both the front and backend), a client side only application, or a multi layered application. let’s see how we can apply docker in each of these cases.
- Monolithic application :
- a client side only application:
- Multi layered application:
To deploy a monolithic GWT application, an application server is needed. We are going to use Jetty for demonstration purposes. In order not to reivent the wheel, we are going to use the official jetty image which is available on Docker Hub.
Our DockerFile looks like :
FROM jetty VOLUME /c/Users/GWidgets/workspace/test/test-pwa2/ COPY target/test-pwa2-0.1.war /var/lib/jetty/webapps
Explanation: we basically told docker to attach our app directory as a volume using the VOLUME command and then copy our app war file into the webapps folder of jetty. The application will automatically be deployed on start up. Now, we need to build our image and run it:
docker build -t gwidgets/gwt-jetty .
docker run -ti -p 8080:8080 --rm --name gwt-jetty gwidgets/gwt-jetty
A client side only application contains only static files like html, js, css,..etc, so we can do without an application server. We can use any web server like Apache or Nginx. We can also use Node Js modules like Express or http-sever to write our own server functionalities or Python SimpleHTTPServer module for an even simpler web server. Since we only need minimal functionalities in this example we are going to use SimpleHTTPServer for serving our files.
For this purpose, we are going to use the official python docker image. Our dockfile looks like:
FROM python:2.7 WORKDIR /test/ EXPOSE 8080 CMD python -m SimpleHTTPServer 8080
docker build -t gwidgets/gwt-client-python-server .
docker run --rm -ti -p 8080:8080 -v /c/GWidgets/workspace/test/python-server-docker:/tes t/ --name gwt-client2 gwidgets/gwt-client-python-server
We built our image using the build command and gave it a tag using the -t flag, and then we used docker run with the -p option which specifies which port on the host machine is to be interfaced with the docker container port. the -v option specifies which file on our host system to be associated with the container specified mount point, in our case /test/.
Multi layered application are usually decoupled into a client side and several back-end services where the communication is carried out using HTTP. In this case we are going to combine what we have learned in previous sections. For the client side, we can use a container with a web server like we have seen in section two. For the backend services, we can use an application server container or just a container with java8 if an embedded server is used like the case of Spring boot. Since we have now a set of interdependent containers, we need to use docker-compose which is a tool provided by Docker to help run multiple containers applications. docker-compose rely on a yaml file that describes the containers that an application is composed of. Supposing our GWT application is divided into a client side, and two Restful backend services, our docker compose would look like:
version: '2' services: client: build: gwidgets/gwt-client ports: - "8080:8080" volumes: - .:/client rest-service1: image: gwidgets/service1 ports: - "8081:8081" rest-service2: image: gwidgets/service2 ports: - "8082:8082" depends_on: - service1
After defining our system of interdependant containers using in the docker-compose.yml file, we can run our application using the following docker command: docker-compose up
Docker can make developing GWT applications a better experience, especially when it concerns large scale applications with complex environments, and a long compile time. Docker may help provide a better test and build environment and allocate resources more effectively when deploying.