Monday, August 18, 2014

Deploying JavaEE apps with TomEE and Docker

What will you see in this post? How to use CoreOS and Docker to deploy Apache TomEE behind a Nginx proxy with multiple connected Docker containers.

Source code: https://github.com/tveronezi/chatdocker

A brand new Apache TomEE version was released this week. We will commemorate this milestone (details in the official announcement) with a new way to deploy software. Do you remember the chat applications that we created in the last post? We will deploy them again. They will use the same computer but now we will have one application per container. Our solution will also include a third container that will work as proxy for our jchat and springchat applications.

This is an overview of our solution:
  • The "Container 1" contains an Apache TomEE instance with ActiveMQ activated and the jchat application installed. 
  • The "Container 2" contains another Apache TomEE instance and the springchat application. 
  • The "Container 3" contains the proxy server [nginx] that will serve as facade to our applications via port 80.
  • The springchat application will connect to the ActiveMQ broker in the "Container 1". 
  • The "Container 3" exposes two links: http://jchat.ddns.net/ and http://springchat.ddns.net/.
The hardest part of the demo is to create a CoreOS instance. Once we have it ready, the deployment of our apps is trivial. It requires a simple "run.sh" script execution.

Our CoreOS machine will host the containers. It can be bare-metal or VM. In this post, we are going to use a VirtualBox machine.

Installation process

Download the ISO file [https://coreos.com/docs/running-coreos/platforms/iso/] and create your VM.




Change your network adapter type to Bridged, so you can bypass the Host firewall.


Start your server with the CoreOS ISO file.


Create the cloud-config file that will be used by the installer. Save this file in a public place (your Dropbox, for example).
 #cloud-config  
 users:  
  - name: myusr  
   passwd: $6$rounds=4096$I950HqPomw$IVTXdX38Xvlkgp7K1vZqejhiYJXoztMZAuvRZPK.UCY2csQuwPt/tjz6JYtInOS1HTlA/TwkD.AvFtJmz3Nxf0  
   groups:  
    - sudo  
    - docker  

Did you notice how crazy complex is the password above? It's a password hash. Check here how to create your own.

Download your config file and execute "coreos-install" to start the installation process.

 wget https://dl.dropboxusercontent.com/u/1459144/cloud-config.txt   
 coreos-install -d /dev/sda -C stable -c cloud-config.txt  

Remove the virtual DVD from the virtual DVD driver and reboot your VM.


Please note that your cloud-config file can configure much more than just passwords. Please check the documentation for a complete reference [https://coreos.com/docs/cluster-management/setup/cloudinit-cloud-config/].

Once your VM is back online, use PUTTY to access it...



You are ready to deploy your applications. Execute the following lines in order to deploy them...

 wget https://github.com/tveronezi/chatdocker/archive/master.zip  
 unzip master.zip  
 cd chatdocker-master/   
 ./run.sh  

Now sit back and relax (approximately 20 minutes). Docker is preparing the containers...



Assuming that 192.168.1.120 is the IP address of your Docker host machine, you now have two new links:

You can also map them with your own DNS values. Open /chatdocker-master/chat/proxy/jchat.conf and /chatdocker-master/chat/proxy/springchat.conf and replace jchat.ddns.net and springchat.ddns.net by your own domains. Tip: I'm using "ddns.net" from http://www.noip.com/. They provide free subdomains.

After updating your files, execute the main "run.sh" command again. Don't worry. It will be much faster now...



What did just happen? 

Docker:
  • downloaded an image of the CentOS distribution [http://www.centos.org/].
  • installed Java, Maven, Git, Tar, Supervisor and TomEE in this image.
  • cleaned up the TomEE installation directory.
  • downloaded and built the jchat and the springchat projects.
  • installed jchat and springchat WAR files.
  • started and linked the TomEE instances
  • downloaded and installed a nginx proxy in a third container.
  • started and linked the nginx to the two TomEE instances.

Dockerfile

This is the recipe used by docker to create our Linux images. Reference here: https://docs.docker.com/reference/builder/

nginx

It's our proxy server. It maps our applications with our own domains. Reference here: http://blog.martinfjordvald.com/2010/07/nginx-primer/

supervisord

In order to run a container, you need to specify what image to use and what process to start. Note that Docker containers are able to track the execution of only one process at a time. Once that one process terminates, the whole container stops. If the user decides to manually stop a container, docker will try to gracefully stop its internal running process.

What if you wanted to execute more than one process at the same time? The solution is simple and elegant. You can use a process manager. Docker will manage the process manager process, and the process manager will manage the extra processes.

Reference here: http://docs.docker.com/articles/using_supervisord/

TomEE with ActiveMQ

These are our Apache friends. The first one is our application server. The second one is our message broker.

Linking containers

Docker containers share the same internal network. They use dynamic IPs, so how would you link these guys? Docker has a great solution: it will map the container names and IPs for you. It will update the "hosts" file of the containers with the provided information.

In the lines below we create three containers...

 docker run -d -p 8080:8080 --name=jchat jchat  
 docker run -d -p 8081:8080 --link=jchat:mybroker --name=springchat springchat  
 docker run -d -p 80:80 --link=jchat:jchat --link=springchat:springchat --name=proxy proxy  
  • The first one is the jchat container. It makes the port 8080 available from the host interface. 
  • The second one is the springchat. The springchat one maps its port 8080 to the port 8081 in the host machine. It also adds a link to the jchar container. "--link-jchat:mybroker" means that the springchat container can ping jchat with "ping mybroker". See how we use this information in the tomee.xml.
  • The third one creates the proxy and links jchat and springchat with the same approach.

Reference here: https://docs.docker.com/userguide/dockerlinks/

More resources