title | description | author | ms.author | ms.topic | ms.date |
---|---|---|---|---|---|
Migrate Tomcat applications to Tomcat on Azure App Service |
This guide describes what you should be aware of when you want to migrate an existing Tomcat application to run on Azure App Service using Tomcat. |
yevster |
yebronsh |
conceptual |
1/20/2020 |
This guide describes what you should be aware of when you want to migrate an existing Tomcat application to run on Azure App Service using Tomcat 8.5 or 9.0.
If you can't meet any of the pre-migration requirements, see the following companion migration guides:
- Migrate Tomcat applications to containers on Azure Kubernetes Service
- Migrate Tomcat Applications to Azure Virtual Machines (planned)
App Service offers specific versions of Tomcat on specific versions of Java. To ensure compatibility, migrate your application to one of the supported versions of Tomcat and Java in its current environment before you proceed with any of the remaining steps. Be sure to fully test the resulting configuration. Use the latest stable release of your Linux distribution in such tests.
[!INCLUDE note-obtain-your-current-java-version]
To obtain your current Tomcat version, sign in to your production server and run the following command:
${CATALINA_HOME}/bin/version.sh
To obtain the current version used by Azure App Service, download Tomcat 8.5 or Tomcat 9, depending on which version you plan to use in Azure App Service.
[!INCLUDE inventory-external-resources]
[!INCLUDE inventory-secrets]
[!INCLUDE inventory-certificates]
[!INCLUDE inventory-persistence-usage]
For files that are frequently written and read by your application (such as temporary data files), or static files that are visible only to your application, you can mount Azure Storage into the App Service file system. For more information, see Serve content from Azure Storage in App Service on Linux.
To identify the session persistence manager in use, inspect the context.xml files in your application and Tomcat configuration. Look for the <Manager>
element, and then note the value of the className
attribute.
Tomcat's built-in PersistentManager implementations, such as StandardManager or FileStore aren't designed for use with a distributed, scaled platform such as App Service. Because App Service may load balance among several instances and transparently restart any instance at any time, persisting mutable state to a file system isn't recommended.
If session persistence is required, you'll need to use an alternate PersistentManager
implementation that will write to an external data store, such as Pivotal Session Manager with Redis Cache. For more information, see Use Redis as a session cache with Tomcat.
Certain production scenarios may require additional changes or impose additional limitations. While such scenarios can be infrequent, it is important to ensure that they are either inapplicable to your application or correctly resolved.
Scheduled jobs, such as Quartz Scheduler tasks or cron jobs, can't be used with App Service. App Service will not prevent you from deploying an application containing scheduled tasks internally. However, if your application is scaled out, the same scheduled job may run more than once per scheduled period. This situation can lead to unintended consequences.
Inventory any scheduled jobs, inside or outside the application server.
If your application contains any code with dependencies on the host OS, then you'll need to refactor it to remove those dependencies. For example, you may need to replace any use of /
or \
in file system paths with File.Separator
or Paths.get
.
Tomcat clustering isn't supported on Azure App Service. Instead, you can configure and manage scaling and load balancing through Azure App Service without Tomcat-specific functionality. You can persist session state to an alternate location to make it available across replicas. For more information, see Identify session persistence mechanism.
To determine whether your application uses clustering, look for the <Cluster>
element inside the <Host>
or <Engine>
elements in the server.xml file.
You will need to migrate elsewhere or eliminate any processes running outside of Application Server, such as monitoring daemons.
App Service supports only a single HTTP connector. If your application requires additional connectors, such as the AJP connector, don't use App Service.
To identify HTTP connectors used by your application, look for <Connector>
elements inside the server.xml file in your Tomcat configuration.
MemoryRealm requires a persisted XML file. On Azure AppService, you will need to upload this file to the /home directory or a subdirectory thereof or to mounted storage. You will have to modify the pathName
parameter accordingly.
To determine whether MemoryRealm
is currently used, inspect your server.xml and context.xml files and search for <Realm>
elements where the className
attribute is set to org.apache.catalina.realm.MemoryRealm
.
App Service performs session offloading outside of the Tomcat runtime. Therefore, you can't use SSL session tracking. Use a different session tracking mode instead (COOKIE
or URL
). If you need SSL session tracking, don't use App Service.
If you use AccessLogValve, you should set the directory
parameter to /home/LogFiles
or a subdirectory thereof.
In the pre-migration you'll likely have identified secrets and external dependencies, such as datasources, in server.xml and context.xml files. For each item thus identified, replace any username, password, connection string or URL with an environment variable.
For example, suppose the context.xml file contains the following element:
<Resource
name="jdbc/dbconnection"
type="javax.sql.DataSource"
url="jdbc:postgresql://postgresdb.contoso.com/wickedsecret?ssl=true"
driverClassName="org.postgresql.Driver"
username="postgres"
password="t00secure2gue$$"
/>
In this case, you could change it as shown in the following example:
<Resource
name="jdbc/dbconnection"
type="javax.sql.DataSource"
url="${postgresdb.connectionString}"
driverClassName="org.postgresql.Driver"
username="${postgresdb.username}"
password="${postgresdb.password}"
/>
From the list of available service plans at App Service pricing, select the plan whose specifications meet or exceed those of the current production hardware.
Note
If you plan to run staging/canary deployments or use deployment slots, the App Service plan must include that additional capacity. We recommend using Premium or higher plans for Java applications. For more information, see Set up staging environments in Azure App Service.
Then, create the App Service plan. For more information, see Manage an App Service plan in Azure.
You'll need to create a Web App on your App Service Plan (choosing a version of Tomcat as the runtime stack) for every WAR file deployed to your Tomcat server.
Note
While it's possible to deploy multiple WAR files to a single web app, this is highly undesirable. Deploying multiple WAR files to a single web app prevents each application from scaling according to its own usage demands. It also adds complexity to subsequent deployment pipelines. If multiple applications need to be available on a single URL, consider using a routing solution such as Azure Application Gateway.
If your application is built from a Maven POM file, use the Webapp plugin for Maven to create the Web App and deploy your application.
If you can't use the Maven plugin, you'll need to provision the Web App through other mechanisms, such as:
Once the Web App has been created, use one of the available deployment mechanisms to deploy your application.
If your application requires specific runtime options, use the most appropriate mechanism to specify them.
Use Application Settings to store any secrets specific to your application. If you intend to use the same secret(s) among multiple applications or require fine-grained access policies and audit capabilities, use Azure Key Vault instead.
[!INCLUDE configure-custom-domain-and-ssl]
[!INCLUDE import-backend-certificates]
Follow these steps to migrate data sources.
Migrate any additional server-level classpath dependencies by following the same steps as for data source JAR files.
Migrate any additional Shared server-level JDNI resources.
Note
If you're following the recommended architecture of one WAR per webapp, consider migrating server-level classpath libraries and JNDI resources into your application. This will significantly simplify component governance and change management.
Upon completing the preceding section, you should have your customizable server configuration in /home/tomcat/conf.
Complete the migration by copying any additional configuration (such as realms, JASPIC)
[!INCLUDE migrate-scheduled-jobs]
Finally, you'll need to restart your Web App to apply all configuration changes. Upon completion of the restart, verify that your application is running correctly.
Now that you have your application migrated to Azure App Service you should verify that it works as you expect. Once you've done that we have some recommendations for you that can make your application more Cloud native.
-
If you opted to use the /home directory for file storage, consider replacing it with Azure Storage.
-
If you have configuration in the /home directory which contains connection strings, SSL keys, and other secret information, consider using a combination of Azure Key Vault and/or parameter injection with application settings where possible.
-
Consider using Deployment Slots for reliable deployments with zero downtime.
-
Design and implement a DevOps strategy. In order to maintain reliability while increasing your development velocity, consider automating deployments and testing with Azure Pipelines. If using Deployment Slots, you can automate deployment to a slot and the subsequent slot swap.
-
Design and implement a business continuity and disaster recovery strategy. For mission-critical applications, consider a multi-region deployment architecture.