About Rama Krishnan

Ramki is a Application Developer working in the C-DAC, Pune. He has Extensive Design and Development experience in Java, Java Server Faces, Servlets, Java Persistent API (Hibernate), CDI, EJB and experience in applying Design Patterns of JavaEE Architecture.

Multiple Tomcat Instances on Single Machine

In this post we will see how to run multiple tomcat instances on a single machine and under a single user account.

We first see the tomcat directory structure, where each folder has the following purpose:

bin -  contains all binary and script files for running tomcat.
lib – contains all shared libraries used for tomcat
conf - contains configuration information like which port tomcat can bind, etc.
logs – contains all log files
temp – this folder is used by Tomcat for temporary files
webapps – this folder is very important, we put here all the application war files
work – if an application contains JSPs, then each JSP is translated and converted into a servlet and is stored here
When we run Tomcat, it uses 5 environment variables. They are:
  • CATALINA_HOME
  • CATALINA_BASE
  • CATALINA_TMPDIR
  • JRE_HOME/JAVA_HOME
  • CLASSPATH
In the above list, CATALINA_HOME and JAVA_HOME are mandatory environment variables. All others are optional and can be calculated using CATALINA_HOME.
CATALINA_HOME – this environment variable should point to tomcat base folder, where tomcat binary are  installed/extracted. so based on CATALINA_HOME we can get bin and lib folder
CATALINA_BASE – If we not specified then CATALINA_HOME value is set. This variable pointed to configuration and webapps folder. Based on this variable server uses conf, logs, temp, webapps, work folders.

A usual way to run Tomcat is to only set the CATALINA_HOME environment variable and run the startup.sh script file. The startup.sh file automatically calculates and assigns the values of other variables which we have not set.

The startup.sh file sets the environment variable and  then calls catalina.sh. This file reads CATALINA_BASE value, attaches conf i.e $CATALINA_BASE/conf folder and gets server.xml. This file is the heart of Tomcat’s configuration. It contains all configuration information, like shutdown port, connector post, host name, application folder, etc. For example, Tomcat usually uses 8080 as a connector port, so we can access it at http://localhost:8080/.

If we set the $CATALINA_BASE explicitly, then Tomcat uses our variable to search and get the server.xml file from our target place, i.e what we specified in CATALINA_BASE. 
This trick can be used to run multiple Tomcat instances in a single machine. We don’t need to change the CATALINA_HOME value. We just need to change the CATALINA_BASE value before start/shutdown Tomcat.

Create one folder named “tomcat-instance1” and copy conf, logs, temp, webapps, work folder from CATALINA_HOME folder and change conf/server.xml file in tomcat-instance1. We need to change these ports: shutdown port, connector port, ajp port and redirect port.

Shutdown port – This port is used for shutting down Tomcat. When we call the shutdown.sh script, it sends a signal to shutdown port. This port is where the Tomcat Java process listens. If such signal is received, the process then cleans up and exits by itself.
Connector port -This port is the actual port that exposes the application to an outside client. 
ajp port – This port may be used by a web server (e.g. Apache httpd server) to communicate with Tomcat. This port is also used when we setup a load balanced server.
Redirect port – If the Connector is supporting non-SSL requests and a request is received for which a security constraint requires SSL, Catalina will automatically redirect the request to this port. 

Let’s see the sample server.xml file:

<server port="8005" shutdown="SHUTDOWN">
	.....
	<connector
		connectiontimeout="20000"port="8080"
		protocol="org.apache.coyote.http11.Http11NioProtocol"
		redirectport="8443" />
	<connector port="8009" protocol="AJP/1.3" redirectport="8443" />
</server>

So, we change these ports to different numbers, because once a port is binded, then an other process can’t bind it again. In tomcat-instance1/conf/server.xml file I configured server port =8105, connector port = 8181, ajp port = 8109.

<server port="8105" shutdown="SHUTDOWN">
	.....
	<connector
		connectiontimeout="20000" port="8181"
		protocol="org.apache.coyote.http11.Http11NioProtocol"
		redirectport="81443" />
	<connector port="8109" protocol="AJP/1.3" redirectport="81443" />
</server>

Now we can create two script files for starting up and shutting down the tomcat-instance1.

startup-instance1.sh

export CATALINA_BASE= /home/ramki/tomcat-instance1
cd $CATALINA_HOME/bin
./startup.sh

shutdown-instance1.sh

export CATALINA_BASE= /home/ramki/tomcat-instance1
cd $CATALINA_HOME/bin
./shutdown.sh

Here we explicitly set the CATALINA_BASE variable and point it to the new tomcat-instance1. Then we go to the CATALINA_HOME/bin folder because all binary files for running tomcat are still present there. Then we use the startup/shutdown cripts.

Based on the above technique, we can create many instance folders and change the conf/server.xml file port values and run that instance with their own newly created script files.

Reference: Running Multiple Tomcat Instances on Single Machine from our JCG partner Rama at the Ramkitech blog (original text was modified for readability reasons).

Related Articles :
Related Whitepaper:

Java Essential Training

Author David Gassner explores Java SE (Standard Edition), the language used to build mobile apps for Android devices, enterprise server applications, and more!

The course demonstrates how to install both Java and the Eclipse IDE and dives into the particulars of programming. The course also explains the fundamentals of Java, from creating simple variables, assigning values, and declaring methods to working with strings, arrays, and subclasses; reading and writing to text files; and implementing object oriented programming concepts. Exercise files are included with the course.

Get it Now!  

11 Responses to "Multiple Tomcat Instances on Single Machine"

  1. Nikola Tošić says:

    One comment: also, if using java debugging port, you should change debugger port in different scripts.
    This did not work for me, until i set $JAVA_OPTS variable to use:
    -Xdebug -Xrunjdwp:transport=dt_socket,address=1045
    in other instance instead of
    -Xdebug -Xrunjdwp:transport=dt_socket,address=1044

    as debugging options.

  2. Jerald Sebastian says:

    This is very useful. However there is no mention about where the two new script files (shutdown-instance1.sh and shutdown-instance1.sh) can go. Obviously there will not be any issue for the tomcat to start up. But if the applications are looking for files relative to working directory there could be problems. Application that works in the very first instance of tomcat, would fail in the second tomcat instance. So it is recommended to have the new script files in a folder named ‘bin’.

  3. Jerald Sebastian says:

    One more thing. Please remember to remove all tomcat related applications (manager, docs, examples, default context etc) as required for your business. Some one in the team that sets up Tomcat instances for us, seems to blindly refer the steps in this blog and left out the default context :) With that the main domain points to the default tomcat page which has links to tomcat and oracle :)

  4. good trick to make multiple instance without multiple copies of tomcat

  5. João Martins says:

    Hi,
    i tried this and almoust everything works, although when i shutdown the server, it hangs in this line:

    INFO: Destroying ProtocolHandler ["http-bio-8183"] and if i start it this is what i get:

    INFO: Initializing ProtocolHandler ["http-bio-8183"]
    Mar 31, 2014 4:17:01 PM org.apache.coyote.AbstractProtocol init
    SEVERE: Failed to initialize end point associated with ProtocolHandler ["http-bio-8183"]
    java.net.BindException: Address already in use :8183
    at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:391)
    at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:554)
    at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:409)
    at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:956)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:815)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:594)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:619)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:449)
    Caused by: java.net.BindException: Address already in use
    at java.net.PlainSocketImpl.socketBind(Native Method)
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
    at java.net.ServerSocket.bind(ServerSocket.java:376)
    at java.net.ServerSocket.(ServerSocket.java:237)
    at java.net.ServerSocket.(ServerSocket.java:181)
    at org.apache.tomcat.util.net.DefaultServerSocketFactory.createSocket(DefaultServerSocketFactory.java:49)
    at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:378)
    … 17 more

    Mar 31, 2014 4:17:01 PM org.apache.catalina.core.StandardService initInternal
    SEVERE: Failed to initialize connector [Connector[HTTP/1.1-8183]]
    org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-8183]]
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
    at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:815)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:594)
    at org.apache.catalina.startup.Catalina.load(Catalina.java:619)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:449)
    Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:958)
    at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
    … 12 more
    Caused by: java.net.BindException: Address already in use :8183
    at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:391)
    at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:554)
    at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:409)
    at org.apache.coyote.http11.AbstractHttp11JsseProtocol.init(AbstractHttp11JsseProtocol.java:119)
    at org.apache.catalina.connector.Connector.initInternal(Connector.java:956)
    … 13 more
    Caused by: java.net.BindException: Address already in use
    at java.net.PlainSocketImpl.socketBind(Native Method)
    at java.net.AbstractPlainSocketImpl.bind(AbstractPlainSocketImpl.java:376)
    at java.net.ServerSocket.bind(ServerSocket.java:376)
    at java.net.ServerSocket.(ServerSocket.java:237)
    at java.net.ServerSocket.(ServerSocket.java:181)
    at org.apache.tomcat.util.net.DefaultServerSocketFactory.createSocket(DefaultServerSocketFactory.java:49)
    at org.apache.tomcat.util.net.JIoEndpoint.bind(JIoEndpoint.java:378)
    … 17 more

    Mar 31, 2014 4:17:01 PM org.apache.catalina.startup.Catalina load
    INFO: Initialization processed in 791 ms
    Mar 31, 2014 4:17:01 PM org.apache.catalina.core.StandardService startInternal
    INFO: Starting service Catalina
    Mar 31, 2014 4:17:01 PM org.apache.catalina.core.StandardEngine startInternal
    INFO: Starting Servlet Engine: Apache Tomcat/7.0.26
    Mar 31, 2014 4:17:01 PM org.apache.catalina.startup.HostConfig deployWAR
    INFO: Deploying web application archive /home/remember/remembermeJM/webapps/RememberMeServer.war
    Mar 31, 2014 4:17:05 PM org.apache.catalina.startup.HostConfig deployWAR
    INFO: Deploying web application archive /home/remember/remembermeJM/webapps/axis2.war
    [INFO] Clustering has been disabled
    [INFO] Deploying module: metadataExchange-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/mex-1.6.2.mar
    [INFO] Deploying module: addressing-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/addressing-1.6.2.mar
    [INFO] Deploying module: jaxws-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/axis2-jaxws-mar-1.6.2.mar
    [INFO] Deploying module: mtompolicy-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/mtompolicy-1.6.2.mar
    [INFO] Deploying module: soapmonitor-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/soapmonitor-1.6.2.mar
    [INFO] Deploying module: ping-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/ping-1.6.2.mar
    [INFO] Deploying module: script-1.6.2 – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/modules/scripting-1.6.2.mar
    [INFO] Deploying Web service: PictureWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/PictureWS.aar
    [INFO] Deploying Web service: LocationWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/LocationWS.aar
    [INFO] Deploying Web service: RegistrationIdWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/RegistrationIdWS.aar
    [INFO] Deploying Web service: version-1.6.2.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/version-1.6.2.aar
    [INFO] Deploying Web service: AccelerometerWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/AccelerometerWS.aar
    [INFO] Deploying Web service: AmplitudeWS.aar – file:/home/remember/remembermeJM/webapps/axis2/WEB-INF/services/AmplitudeWS.aar
    Mar 31, 2014 4:17:09 PM org.apache.catalina.startup.Catalina start
    INFO: Server startup in 7887 ms

    I have another instance running. But i have to have it running, because they are different applications. Can someone help me

    • Ramki says:

      the problem is ur using port 8183, but its already used by some process. check the netstat -tlpn command.

      change the port to different one. and make sure all are unique ports (unused).

      • João Martins says:

        But this also happens in one instance i have with port 8181 and before this instance was working properly is this some kind of problem where there is a proccess running in this ports that weren’t shutdown and still running?

Leave a Reply


+ 8 = seventeen



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.

Sign up for our Newsletter

20,709 insiders are already enjoying weekly updates and complimentary whitepapers! Join them now to gain exclusive access to the latest news in the Java world, as well as insights about Android, Scala, Groovy and other related technologies.

As an extra bonus, by joining you will get our brand new e-books, published by Java Code Geeks and their JCG partners for your reading pleasure! Enter your info and stay on top of things,

  • Fresh trends
  • Cases and examples
  • Research and insights
  • Two complimentary e-books