In Apache Tomcat, you can set a environment variable called CATALINA_BASE which lets you apply a different set of configurations/environments quickly.
Typically an application reads a configuration file. For example
application.exe -c config.xml
But because Tomcat reads multiple files for its settings (i.e. server.xml, web.xml, catalina.properties, conf folder, etc), it achieves the same effect by using CATALINA_BASE, basically we’re telling Tomcat which folder contains our set of configuration files to override the default values.
This mechanism also allows us to upgrade Tomcat easily, since our configuration values are in another folder.
Example scenario
- Downloaded and extracted Tomcat version 9 at /system/server/tomcat-9
- Downloaded and extracted Tomcat version 10 at /system/server/tomcat-10
There is a symlink /system/server/tomcat that points to /system/server/tomcat-9.
We have
- a server.xml that listens on port 8080 in /system/base/tomcat-8080/conf/server.xml
- a server.xml that listens on port 8090 in /system/base/tomcat-8090/conf/server.xml
# tree /system/base
/system/base
├── tomcat-8080
│ ├── conf
│ │ └── server.xml
│ ├── logs <- need to create this empty folder
│ └── temp <- need to create this empty folder
└── tomcat-8090
├── conf
│ └── server.xml
├── logs <- need to create this empty folder
└── temp <- need to create this empty folder
So, the executables are in 1 place, /system/server/tomcat (which currently points to tomcat-9). With 1 set of executables, we can run 2 Tomcat instances by doing this
# CATALINA_BASE=/system/base/tomcat-8080 /system/server/tomcat/bin/startup.sh
# CATALINA_BASE=/system/base/tomcat-8090 /system/server/tomcat/bin/startup.sh
So we are telling Tomcat which folder to read configuration files from by passing an environment variable called CATALINA_BASE.
If we later want to upgrade to Tomcat 10, we can just simply change the symlink /system/server/tomcat from pointing to /system/server/tomcat-9 to /system/server/tomcat-10. We do not need to copy files or modify files in Tomcat 10’s conf folder, since our configuration are in /system/base.
Start
Remember to also change the shutdown port so they are different if you planning to run more than 1 instance in a server.
# CATALINA_BASE=/system/base/tomcat-8080 /system/server/tomcat/bin/startup.sh
Using CATALINA_BASE: /system/base/tomcat-8080
Using CATALINA_HOME: /system/server/tomcat
Using CATALINA_TMPDIR: /system/base/tomcat-8080/temp
Using JRE_HOME: /system/jdk
Using CLASSPATH: /system/server/tomcat/bin/bootstrap.jar:/system/server/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
# netstat -nutap|grep 8080
tcp6 0 0 :::8080 :::* LISTEN 1485/java
# CATALINA_BASE=/system/base/tomcat-8090 /system/server/tomcat/bin/startup.sh
Using CATALINA_BASE: /system/base/tomcat-8090
Using CATALINA_HOME: /system/server/tomcat
Using CATALINA_TMPDIR: /system/base/tomcat-8090/temp
Using JRE_HOME: /system/jdk
Using CLASSPATH: /system/server/tomcat/bin/bootstrap.jar:/system/server/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
Tomcat started.
# netstat -nutap|grep 8090
tcp6 0 0 :::8090 :::* LISTEN 1730/java
Stop
# CATALINA_BASE=/system/base/tomcat-8080 /system/server/tomcat/bin/shutdown.sh
Using CATALINA_BASE: /system/base/tomcat-8080
Using CATALINA_HOME: /system/server/tomcat
Using CATALINA_TMPDIR: /system/base/tomcat-8080/temp
Using JRE_HOME: /system/jdk
Using CLASSPATH: /system/server/tomcat/bin/bootstrap.jar:/system/server/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
# CATALINA_BASE=/system/base/tomcat-8090 /system/server/tomcat/bin/shutdown.sh
Using CATALINA_BASE: /system/base/tomcat-8090
Using CATALINA_HOME: /system/server/tomcat
Using CATALINA_TMPDIR: /system/base/tomcat-8090/temp
Using JRE_HOME: /system/jdk
Using CLASSPATH: /system/server/tomcat/bin/bootstrap.jar:/system/server/tomcat/bin/tomcat-juli.jar
Using CATALINA_OPTS:
After startup, Tomcat will create more folders.
/system/base
├── tomcat-8080
│ ├── conf
│ │ ├── Catalina
│ │ │ └── default
│ │ └── server.xml
│ ├── logs
│ │ ├── catalina.out
│ │ └── default
│ │ └── access_log.2023-10-15.txt
│ ├── temp
│ └── work
│ └── Catalina
│ └── default
│ └── ROOT
└── tomcat-8090
├── conf
│ ├── Catalina
│ │ └── default
│ └── server.xml
├── logs
│ ├── catalina.out
│ └── default
│ └── access_log.2023-10-15.txt
├── temp
└── work
└── Catalina
└── default
└── ROOT
Server.xml files for this example
# cat /system/base/tomcat-8080/conf/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8081" shutdown="TERMINATE">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<Service name="Catalina">
<Connector port="8080" protocol="HTTP/1.1"
maxThreads="200"
connectionTimeout="20000"
redirectPort="443"
compression="on"
compressionMinSize="2048"
compressibleMimeType="text/html,text/xml,text/plain,text/css,application/json,application/javascript" />
<Engine name="Catalina" defaultHost="default">
<Host name="default" autoDeploy="false" appBase="/system/site/default">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs/default" prefix="access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b %{User-Agent}i" />
</Host>
</Engine>
</Service>
</Server>
e# cat /system/base/tomcat-8090/conf/server.xml
<?xml version="1.0" encoding="UTF-8"?>
<Server port="8091" shutdown="TERMINATE">
<Listener className="org.apache.catalina.startup.VersionLoggerListener" />
<Listener className="org.apache.catalina.core.AprLifecycleListener" SSLEngine="on" />
<Listener className="org.apache.catalina.core.JreMemoryLeakPreventionListener" />
<Listener className="org.apache.catalina.mbeans.GlobalResourcesLifecycleListener" />
<Listener className="org.apache.catalina.core.ThreadLocalLeakPreventionListener" />
<Service name="Catalina">
<Connector port="8090" protocol="HTTP/1.1"
maxThreads="200"
connectionTimeout="20000"
redirectPort="443"
compression="on"
compressionMinSize="2048"
compressibleMimeType="text/html,text/xml,text/plain,text/css,application/json,application/javascript" />
<Engine name="Catalina" defaultHost="default">
<Host name="default" autoDeploy="false" appBase="/system/site/default">
<Valve className="org.apache.catalina.valves.AccessLogValve" directory="logs/default" prefix="access_log" suffix=".txt" pattern="%h %l %u %t "%r" %s %b %{User-Agent}i" />
</Host>
</Engine>
</Service>
</Server>