Results for tag "infrastructure"

Multiple Tomcat Instances

posted by Roberto Cortez on

Multiple Tomcat InstancesWhen building a real application you often find yourself having to deal with different stages of the software. The most common stages are development, testing and production, but you can have many more. This means that you need a different environment to deploy the application on each of the current stages. You use different environments to be able to perform versioning, different configurations, test bug fixes and so on. This also poses challenges on upgrading environments, changing shared configuration or keeping track of the servers. I will show you how to do it with Tomcat.

The easiest way to set up multiple Tomcat instances is to duplicate the entire Tomcat folder and change a few configurations. I don’t advise doing it this way, since it’s harder to maintain, harder to spin up new instances and harder to upgrade. Instead, we will set up the instances in a much more flexible way, by duplicating only a few things and keeping a shared base folder for all instances.

Installation

You need Tomcat of course. Download it here.

I’ve used version 7.0, but this should also work with other versions. I’m also doing the setup in a Unix like environment. This can also be accomplished in a Windows box, but the commands need to be adjusted.

Unzip the installation folder to a directory of your choice. I just recommend to do it in a parent folder and you can use a name like tomcat or server.

Now, instead of using the unzipped folder, we are going to create a link to it, like this:
ln -s apache-tomcat-7.0.64/ current

Here is a sample:

Setup

To keep this simple, we are going to create two instances: development and production. But keep in mind that you can create as many as you want by making the necessary adjustments to the scripts.

Folders

Create a folder now named instances or environments. Inside, create a folder named development:

Now copy the folders conf, logs, temp, webapps and work from the Tomcat install folder into development and production:

If you wish, you can now remove these folders from the Tomcat install folder, but is not mandatory.

Home and Base

The idea here is to share the main Tomcat folders and each instance has a copy of their personal folders to not clash with each other. Tomcat defines two environment variables called CATALINA_HOME and CATALINA_BASE that allow us to do that.

Create a bin folder in the instances development. Add the following exec.sh script:

Note: If you are using MacOSX, you might need to install core-utils using brew and replace readlink by greadlink to achieve the proper behaviour.

This script is going to set up the proper configuration variables to point to our shared Tomcat and the specific instance folders. Note the properties http.port, https.port, ajp.port and shutdown.port are included in the CATALINA_OPTS environment variable. With these we can pass specific configuration to the server.xml file. Tomcat is smart enough to perform property replace substitution as long as you have the proper placeholders in place.

Files

All these operations are performed in the development folder instance.

conf/server.xml

Edit the file conf/server.xml do the following changes;

ReplaceBy
8080${http.port}
8443${https.port}
8009${ajp.port}

Note: Unfortunately the only place where property replacement doesn’t work is the shutdown port. I think this is a bug in Tomcat and should be fixed. So for now, we need to keep it hardcoded.

bin/exec.sh

On the bin folder, create links to exec.sh to the following files: catalina.sh, startup.sh, shutdown.sh.

This will allow you to call the original Tomcat, but by calling the exec.sh set up first. The magic is done by the line $CATALINA_HOME/bin/"$(basename "$0")" "$@" in the exec.sh script.

Run

The instance should be ready to be executed. Just run it as you would do it normally by executing sh catalina.sh run or sh startup.sh from the development instance folder.

Additional Instances

Just duplicate the development instance folder to a production one and edit the bin/exec.sh to update it with different ports. You can user 7080 for http, 7443 for https, 7009 for ajp and 7005 for the shutdown.

Since property replacement is not working properly for the shutdown port, we need to manually edit conf/server.xml from the production instance and replace 8005 by 7005. When this bug is fixed, and you actually use a property, you don’t have to worry about doing this.

Note: You might need to reestablish the proper links in the scripts catalina.sh, startup.sh and shutdown.sh stored in the bin folder.

After this, your second instance production is ready to run. If you need more, just repeat the last steps, making sure to pick ports that don’t conflict with the instances already set up.

Perks

With this set up you can now:

  • Create new instances easily with minimum changes. You can actually have one untouched unchanged instance, that you can use to copy from to create others.
  • Update the Tomcat version, just by installing a new distribution and updating the link to current.
  • If you place jars in the libs folder of the HOME installation, they become instantly available to all instances.
  • Instead of duplicating the conf folder, you can actually link to the one in HOME and also share the configuration between all environments. Or just link to the files you want to share.
  • Remove an instance, by just deleting its BASE folder.
  • Also works for TomEE!

Alternatives

If you don’t like this set up, you can try using Docker. Check the following post: Get Into Docker.

Let me know if this was useful to you or if you had any trouble following the blog instructions!

Distribute your applications with Docker Images

posted by Roberto Cortez on

Works on my MachineSince I started this blog, I had the need to develop a couple of sample applications to showcase some of the topics I have been covering. Usually, some kind of Java EE application that needs to be deployed in a Java EE container. Even by providing instructions on how to setup the environment, it can be tricky for a newcomer. A few of my readers don’t have a Java EE container available in their local machine. Some don’t even have Java Development Kit installed. If I could provide the entire environment set up for you and you only need to execute it somehow, wouldn’t that be great? I do think so! Instead of distributing only the application, also distribute the environment needed for the application to run. We can do that using Docker.

A couple of weeks ago, I wrote the post Get into Docker. Now, this post is going to continue to explore one of the most interesting Docker features: the Docker Images. This is the answer to provide my reader with a complete environment with everything ready to run.

Docker Image

A Docker Image is a read only template used to create the Docker containers. Each image is built with a series of layers composing your final image. If you need to distribute something using Ubuntu and Apache, you start with a base Ubuntu image and add Apache on top.

Create a Docker Image file

I’m going to use one my latest application, the World of Warcraft Auction House, to show how we can package it into a Docker Image and distribute it to others. The easiest way is to create a Dockerfile. This is a simple plain text file that contains a set of instructions that tells Docker how to build our image. The instructions that you can use are well defined and straightforward. Check the Dockerfile reference page for a list of possible instructions. Each instruction adds a new layer to your Docker Images. Usually the Dockerfile is named Dockerfile. Place it in a directory of your choice.

Base Image

Every Dockerfile needs to start with a FROM instruction. We need to start from somewhere, so this indicates the base image that we are going to use to build our environment. If you were building a Virtual Machine you also had to start from somewhere, and you have to start by picking up the Operating System that you are going to use. With the Dockerfile it’s no different. Let’s add the following to the Dockerfile:

FROM debian:latest

Our base image will be the latest version of Debian, available here: Docker Hub Debian Repo.

Add what you need

The idea here is to build an environment that checkouts the code, build and execute the World of Warcraft Auction House sample. Can you figure out what you need? The JDK of course, to compile and run and Maven to perform the build. But these are not enough. You also need the Git command line client to checkout the code. For this part you need to know a little bit about Unix shell scripting.

Since we need to install the JDK and Maven, we need to download them into our image from somewhere. You can use the wget command to do it. But wget is not available in our base Debian image so we need to install it first. To run shell commands we use the RUN instruction in the Dockerfile.

Install wget:

Install the JDK:

Install Maven:

We also need to have Java and Maven accessible from anywhere in our image. As you would do to your local machine when setting the environment, you need to set JAVA_HOME and add Maven binary to the PATH. You can do this by using Docker ENV instruction.

Add the application

Now that we have the required environment for the World of Warcraft Auction House, we just need to clone the code and build it:

We also want to expose a port, so you can access the application. You should use the listening http port of the application server. In this case, it’s 8080. You can do this in Docker with the EXPOSE instruction:

I had to use a little trick here. I don’t want to download and install the application server, so I’m using the embedded Wildfly version of the Maven plugin. Now, as I told you before, each instruction of the Dockerfile adds a new layer to the image. In here I’m forcing a start and stop of the server, just for Maven to download the required dependencies and have them available in the image. If I didn’t do this, whenever I wanted to run the image, I would have to download all the server dependencies and the startup of the image would take considerably longer.

Run the application

The final instruction should be a CMD to set the command to be executed when running the image:

In this case we want to make sure we are using the latest code, so we do a git pull and then run the embedded Wildfly server. The deploy configuration has been already set up in Wildfly Maven plugin.

Complete Dockerfile

Build the Dockerfile

To be able to distribute your image, you need to build your Dockerfile. What this is going to do, is to read every instruction, execute it and add a layer to your Docker Images. You only need to do this once, unless you change your Dockerfile. The CMD instruction is not executed in the build, since it’s only used when you are actually running the image and executing the container.

To build the Dockerfile, I use the following command in the directory containing your Dockerfile:

docker build -t radcortez/wow-auctions .

The -t radcortez/wow-auctions is to tag and name the image I’m building. You should use the format user/name. You should use the same user name that you register with Docker Hub.

Pushing the Image

Docker Hub is a Docker Image repository. It’s the same concept of Maven repositories for Java libraries. Download or upload images and you are good to go. The Docker Hub already contains a huge number of images ready to use, from simple Unix distributions, to full blown application servers.

We can now pick the image we build locally and upload it to Docker Hub. This will allow anyone to download and use this image. We can do it like this:

docker push radcortez/wow-auctions

Depending on the image size, this can take a few minutes.

Run the Image

Finally to run the image and the container we execute:

docker run -it --name wow-auctions -p 8080:8080 radcortez/wow-auctions

Since I’ve built the image locally first, this will run the CMDradcortez/wow-auctions. Just by using the above command, the image is going to be downloaded and executed in your environment.

Conclusion

With Docker, is possible to distribute your own applications and have the required environment for the application to run properly created by you. It’s not exactly trivial, since you need some knowledge of Unix, but it’s shouldn’t be a problem.

My main motivation to use Docker here, was to simplify the distribution of my sample applications. It’s not unusual to receive a few reader emails asking for help to set up their environment. Sure, in this way you now have to install Docker too, but that’s the only thing you need. The rest, just leave it to me now!

Related Articles

Remember to check my introductory post about Docker:

Get Into Docker

Get into Docker

posted by Roberto Cortez on

Works on my MachineHave you ever heard about Docker before? Most likely. If not, don’t worry, I’ll try to summarize it for you. Docker is probably one of the hottest technologies at the moment. It has the potential to revolutionize the way we build, deploy and distribute applications. At the same time, it’s already having a huge impact in the development process.

In some cases, the development environments can be so much complicated, that it’s hard to keep the consistency between the different team members. I’m pretty sure that most of us already suffered from the syndrome “Works on my Machine”, right? One way to deal with the problem is to build Virtual Machines (VM) with everything set up so you can distribute them through your team. But VM’s are slow, large and you cannot access them if they are not running.

What is Docker?

Docker LogoShort answer: it’s like a lightweight VM. In practice, it’s not the case, since Docker is different from a regular VM. Docker creates a container for your application, packaged with all of the required dependencies and ready to run. These containers run on a shared Linux kernel, but they are isolated from each other. This means that you don’t need the usual VM operating system, giving a considerable performance boost and shrinking the application size.

Let’s dig a little more into detail:

Docker Image

A Docker Image is a read only template used to create the Docker containers. Each image is built with a series of layers composing your final image. If you need to distribute something using Ubuntu and Apache, you start with a base Ubuntu image and add Apache on top. If you later want to upgrade to a Tomcat instance, you just add another layer to your image. Instead of distributing the entire image as you would with a VM, you just release the update.

Docker Registry

The Docker registry also called Docker Hub is a Docker Image repository. It’s the same concept of Maven repositories for Java libraries. Download or upload images and you are good to go. The Docker Hub already contains a huge number of images ready to use, from simple Unix distributions, to full blown application servers.

Docker Container

A Docker Container is the runtime component of the Docker Image. You can spin multiple containers from the same Docker Image in an isolated context. Docker containers can be run, started, stopped, moved, and deleted.

How do I start?

You need to install Docker of course. Please refer to the installation guides of Docker. They are pretty good and I had no problem installing the software. Make sure you follow the proper guide to your system.

Our first Docker Container

After having Docker installed, you can immediately type in your command line:

docker run -it -p 8080:8080 tomcat

You should see the following message:

Unable to find image ‘tomcat:latest’ locally

And a lot of downloads starting. Like Maven, when you build an application, it downloads the required libraries to run Tomcat, by reaching out to Docker Hub. It takes a while to download. (Great, one more thing to download the Internet. Luckily we can use ZipRebel, to download it quickly).

After everything is downloaded, you should see the Tomcat instance booting up, and you can access it by going to http://localhost:8080 in Linux boxes. For Windows and Mac users is slightly more complicated. Since Docker only works in a Linux environment, to be able to use it in Windows and Mac you need boot2docker (which you should have from the installation guide). This is in fact a VM that runs Docker on Linux completely from memory. To access the Docker containers you need to refer to this VM IP. You can get the IP with the command: boot2docker ip.

Explaining the command:

docker runThe command to create and start a new Docker container.
-itTo run in interactive mode, so you can see the after running the container.
-p 8080:8080This is to map the internal container port to the outside host, usually your machine. Port mapping information can only be set on the container creation. If you don’t specify it, you need to check which port Docker assigned
tomcatName of the image to run. This is linked to the Docker tomcat repository. This holds the instructions, so Docker knows how to run the server.

Remember that if you stop and run again the same command, you are creating and running a new container.

Multiple Containers

You can run multiple Tomcat instances by issuing the following commands:

docker run -d -p 8080:8080 --name tomcat tomcat
docker run -d -p 9090:8080 --name web tomcat

These create two Tomcat containers named tomcat and web. Just remember to change the port mapping and the name. Adding a name is useful to control the container. If not, Docker will randomly generate one for you.

The -d instructs Docker to run the container in the background. You can now control your container with the following commands:

docker psSee a list of all the running Docker containers. Add -a to see all the containers.
docker stop webStops the container named web.
docker start webStarts the container named web.
docker rm webRemove the container named web.
docker logs webShows the container named web logs.

Connecting to the Container

If you execute the command docker exec -it tomcat bash, you will be able to connect to the container shell and explore the environment. You can for instance, verify the running processes with ps -ax.

Interacting with the Container

Let’s add a file to the container:

echo "radcortez" > radcortez

Exit the container, but keep it running. Execute docker diff web. You are going to see a bunch of files related to the tomcat temporary files, plus the file we just added. This command evaluates the file system differences between the running container and the origin image.

Conclusion

We only scratched the surface of Docker capabilities. It’s still soon to tell if Docker will become a mandatory tool. Currently it’s receiving major adoption from big players like Google, Microsoft or Amazon. Docker may end up failing in the end, but it sure opened up an old discussion which doesn’t have a clear answer yet.

Related Articles

Learn how to create, build and distribute your own Docker Images in this follow up post:

Distribute your applications with Docker Images