Deploy and configure a Tomcat, JBoss, or Java SE app in Azure App Service
სტატია
This article shows you the most common deployment and runtime configuration for Java apps in App Service. If you've never used Azure App Service, you should read through the Java quickstart first. General questions about using App Service that aren't specific to Java development are answered in the App Service FAQ.
Azure App Service runs Java web applications on a fully managed service in three variants:
Java SE - Can run an app deployed as a JAR package that contains an embedded server (such as Spring Boot, Dropwizard, Quarkus, or one with an embedded Tomcat or Jetty server).
Tomcat - The built-in Tomcat server can run an app deployed as a WAR package.
JBoss EAP - Supported for Linux apps in the Free, Premium v3, and Isolated v2 pricing tiers only. The built-in JBoss EAP server can run an app deployed as a WAR or EAR package.
This command adds an azure-webapp-maven-plugin plugin and related configuration by prompting you to select an existing Azure Web App or create a new one. During configuration, it attempts to detect whether your application should be deployed to Java SE, Tomcat, or (Linux only) JBoss EAP. Then you can deploy your Java app to Azure using the following command:
plugins {
id "com.microsoft.azure.azurewebapp" version "1.10.0"
}
Configure your web app details. The corresponding Azure resources are created if they don't exist.
Here's a sample configuration, for details, refer to this document.
groovy
azurewebapp {
subscription = '<your subscription id>'
resourceGroup = '<your resource group>'
appName = '<your app name>'
pricingTier = '<price tier like 'P1v2'>'
region = '<region like 'westus'>'
runtime {
os = 'Linux'
webContainer = 'Tomcat 10.0'// or 'Java SE' if you want to run an executable jar
javaVersion = 'Java 17'
}
appSettings {
<key> = <value>
}
auth {
type = 'azure_cli'// support azure_cli, oauth2, device_code and service_principal
}
}
Deploy with one command.
shell
gradle azureWebAppDeploy
IDEs
Azure provides seamless Java App Service development experience in popular Java IDEs, including:
To deploy .jar files to Java SE, use the /api/publish endpoint of the Kudu site. For more information on this API, see this documentation.
Note
Your .jar application must be named app.jar for App Service to identify and run your application. The Maven plugin does this for you automatically during deployment. If you don't wish to rename your JAR to app.jar, you can upload a shell script with the command to run your .jar app. Paste the absolute path to this script in the Startup File textbox in the Configuration section of the portal. The startup script doesn't run from the directory into which it's placed. Therefore, always use absolute paths to reference files in your startup script (for example: java -jar /home/myapp/myapp.jar).
To deploy .war files to Tomcat, use the /api/wardeploy/ endpoint to POST your archive file. For more information on this API, see this documentation.
To deploy .war files to JBoss, use the /api/wardeploy/ endpoint to POST your archive file. For more information on this API, see this documentation.
To deploy .ear files, use FTP. Your .ear application is deployed to the context root defined in your application's configuration. For example, if the context root of your app is <context-root>myapp</context-root>, then you can browse the site at the /myapp path: http://my-app-name.azurewebsites.net/myapp. If you want your web app to be served in the root path, ensure that your app sets the context root to the root path: <context-root>/</context-root>. For more information, see Setting the context root of a web application.
Don't deploy your .war or .jar using FTP. The FTP tool is designed to upload startup scripts, dependencies, or other runtime files. It's not the optimal choice for deploying web apps.
Rewrite or redirect URL
To rewrite or redirect URL, use one of the available URL rewriters, such as UrlRewriteFilter.
Performance reports, traffic visualizations, and health checkups are available for each app through the Azure portal. For more information, see Azure App Service diagnostics overview.
You can access the console logs generated from inside the container.
To turn on container logging, run the following command:
Azure CLI
az webapp log config --name<app-name>--resource-group<resource-group-name>--docker-container-logging filesystem
Replace <app-name> and <resource-group-name> with the names appropriate for your web app.
After you turn on container logging, run the following command to see the log stream:
Azure CLI
az webapp log tail --name<app-name>--resource-group<resource-group-name>
If you don't see console logs immediately, check again in 30 seconds.
To stop log streaming at any time, type Ctrl+C.
You can also inspect the log files in a browser at https://<app-name>.scm.azurewebsites.net/api/logs/docker.
To access the console logs generated from inside your application code in App Service, turn on diagnostics logging by running the following command in the Cloud Shell:
Azure CLI
az webapp log config --resource-group<resource-group-name>--name<app-name>--docker-container-logging filesystem --level Verbose
Possible values for --level are: Error, Warning, Info, and Verbose. Each subsequent level includes the previous level. For example: Error includes only error messages, and Verbose includes all messages.
Once diagnostic logging is turned on, run the following command to see the log stream:
Azure CLI
az webapp log tail --resource-group<resource-group-name>--name<app-name>
If you don't see console logs immediately, check again in 30 seconds.
Note
You can also inspect the log files from the browser at https://<app-name>.scm.azurewebsites.net/api/logs/docker.
If you're not yet authenticated, you're required to authenticate with your Azure subscription to connect. Once authenticated, you see an in-browser shell, where you can run commands inside your container.
Note
Any changes you make outside the /home directory are stored in the container itself and don't persist beyond an app restart.
The built-in Java images are based on the Alpine Linux operating system. Use the apk package manager to install any troubleshooting tools or commands.
Java Profiler
All Java runtimes on Azure App Service come with the JDK Flight Recorder for profiling Java workloads. You can use it to record JVM, system, and application events and troubleshoot problems in your applications.
All Java runtimes on App Service come with the Java Flight Recorder. You can use it to record JVM, system, and application events and troubleshoot problems in your Java applications.
SSH into your App Service and run the jcmd command to see a list of all the Java processes running. In addition to jcmd itself, you should see your Java application running with a process ID number (pid).
shell
078990bbcd11:/home# jcmd
Picked up JAVA_TOOL_OPTIONS: -Djava.net.preferIPv4Stack=true
147 sun.tools.jcmd.JCmd
116 /home/site/wwwroot/app.jar
Execute the following command to start a 30-second recording of the JVM. It profiles the JVM and creates a JFR file named jfr_example.jfr in the home directory. (Replace 116 with the pid of your Java app.)
During the 30-second interval, you can validate the recording is taking place by running jcmd 116 JFR.check. The command shows all recordings for the given Java process.
Continuous Recording
You can use Java Flight Recorder to continuously profile your Java application with minimal impact on runtime performance. To do so, run the following Azure CLI command to create an App Setting named JAVA_OPTS with the necessary configuration. The contents of the JAVA_OPTS App Setting are passed to the java command when your app is started.
Azure CLI
az webapp config appsettings set -g<your_resource_group>-n<your_app_name>--settings JAVA_OPTS=-XX:StartFlightRecording=disk=true,name=continuous_recording,dumponexit=true,maxsize=1024m,maxage=1d
Once the recording starts, you can dump the current recording data at any time using the JFR.dump command.
To take a timed recording, you need the PID (Process ID) of the Java application. To find the PID, open a browser to your web app's SCM site at https://<your-site-name>.scm.azurewebsites.net/ProcessExplorer/. This page shows the running processes in your web app. Find the process named "java" in the table and copy the corresponding PID (Process ID).
Next, open the Debug Console in the top toolbar of the SCM site and run the following command. Replace <pid> with the process ID you copied earlier. This command starts a 30-second profiler recording of your Java application and generates a file named timed_recording_example.jfr in the C:\home directory.
Enable application logging through the Azure portal or Azure CLI to configure App Service to write your application's standard console output and standard console error streams to the local filesystem or Azure Blob Storage. If you need longer retention, configure the application to write output to a Blob storage container.
Your Java and Tomcat app logs can be found in the /home/LogFiles/Application/ directory.
Azure Blob Storage logging for Linux based apps can only be configured using Azure Monitor.
Enable application logging through the Azure portal or Azure CLI to configure App Service to write your application's standard console output and standard console error streams to the local filesystem or Azure Blob Storage. Logging to the local App Service filesystem instance is disabled 12 hours after you enable it. If you need longer retention, configure the application to write output to a Blob storage container.
Your Java and Tomcat app logs can be found in the /home/LogFiles/Application/ directory.
Due to known vulnerability CVE-2021-44228, be sure to use Log4j version 2.16 or later.
Customization and tuning
Azure App Service supports out of the box tuning and customization through the Azure portal and CLI. Review the following articles for non-Java-specific web app configuration:
Set the app setting JAVA_COPY_ALL to true to copy your app contents to the local worker from the shared file system. This setting helps address file-locking issues.
Set Java runtime options
To set allocated memory or other JVM runtime options, create an app setting named JAVA_OPTS with the options. App Service passes this setting as an environment variable to the Java runtime when it starts.
In the Azure portal, under Application Settings for the web app, create a new app setting named JAVA_OPTS that includes other settings, such as -Xms512m -Xmx1204m.
In the Azure portal, under Application Settings for the web app, create a new app setting named CATALINA_OPTS that includes other settings, such as -Xms512m -Xmx1204m.
To configure the app setting from the Maven plugin, add setting/value tags in the Azure plugin section. The following example sets a specific minimum and maximum Java heap size:
You don't need to create a web.config file when using Tomcat on Windows App Service.
Developers running a single application with one deployment slot in their App Service plan can use the following options:
B1 and S1 instances: -Xms1024m -Xmx1024m
B2 and S2 instances: -Xms3072m -Xmx3072m
B3 and S3 instances: -Xms6144m -Xmx6144m
P1v2 instances: -Xms3072m -Xmx3072m
P2v2 instances: -Xms6144m -Xmx6144m
P3v2 instances: -Xms12800m -Xmx12800m
P1v3 instances: -Xms6656m -Xmx6656m
P2v3 instances: -Xms14848m -Xmx14848m
P3v3 instances: -Xms30720m -Xmx30720m
I1 instances: -Xms3072m -Xmx3072m
I2 instances: -Xms6144m -Xmx6144m
I3 instances: -Xms12800m -Xmx12800m
I1v2 instances: -Xms6656m -Xmx6656m
I2v2 instances: -Xms14848m -Xmx14848m
I3v2 instances: -Xms30720m -Xmx30720m
When tuning application heap settings, review your App Service plan details and take into account multiple applications and deployment slot needs to find the optimal allocation of memory.
Turn on web sockets
Turn on support for web sockets in the Azure portal in the Application settings for the application. You need to restart the application for the setting to take effect.
Turn on web socket support using the Azure CLI with the following command:
Azure CLI
az webapp config set --name<app-name>--resource-group<resource-group-name>--web-sockets-enabledtrue
Then restart your application:
Azure CLI
az webapp stop --name<app-name>--resource-group<resource-group-name>az webapp start --name<app-name>--resource-group<resource-group-name>
Set default character encoding
In the Azure portal, under Application Settings for the web app, create a new app setting named JAVA_OPTS with value -Dfile.encoding=UTF-8.
Alternatively, you can configure the app setting using the App Service Maven plugin. Add the setting name and value tags in the plugin configuration:
To improve performance of Tomcat applications, you can compile your JSP files before deploying to App Service. You can use the Maven plugin provided by Apache Sling, or using this Ant build file.
robots933456 in logs
You may see the following message in the container logs:
You can safely ignore this message. /robots933456.txt is a dummy URL path that App Service uses to check if the container is capable of serving requests. A 404 response simply indicates that the path doesn't exist, but it lets App Service know that the container is healthy and ready to respond to requests.
Choosing a Java runtime version
App Service allows users to choose the major version of the JVM, such as Java 8 or Java 11, and the patch version, such as 1.8.0_232 or 11.0.5. You can also choose to have the patch version automatically updated as new minor versions become available. In most cases, production apps should use pinned patch JVM versions. This prevents unanticipated outages during a patch version autoupdate. All Java web apps use 64-bit JVMs, and it's not configurable.
If you're using Tomcat, you can choose to pin the patch version of Tomcat. On Windows, you can pin the patch versions of the JVM and Tomcat independently. On Linux, you can pin the patch version of Tomcat; the patch version of the JVM is also pinned but isn't separately configurable.
If you choose to pin the minor version, you need to periodically update the JVM minor version on the app. To ensure that your application runs on the newer minor version, create a staging slot and increment the minor version on the staging slot. Once you confirm the application runs correctly on the new minor version, you can swap the staging and production slots.
Run JBoss CLI
In your JBoss app's SSH session, you can run the JBoss CLI with the following command:
$JBOSS_HOME/bin/jboss-cli.sh --connect
Depending on where JBoss is in the server lifecycle, you might not be able to connect. Wait a few minutes and try again. This approach is useful for quick checks of your current server state (for example, to see if a data source is properly configured).
App Service supports clustering for JBoss EAP versions 7.4.1 and greater. To enable clustering, your web app must be integrated with a virtual network. When the web app is integrated with a virtual network, it restarts, and the JBoss EAP installation automatically starts up with a clustered configuration. When you run multiple instances with autoscaling, the JBoss EAP instances communicate with each other over the subnet specified in the virtual network integration. You can disable clustering by creating an app setting named WEBSITE_DISABLE_CLUSTERING with any value.
Note
If you're enabling your virtual network integration with an ARM template, you need to manually set the property vnetPrivatePorts to a value of 2. If you enable virtual network integration from the CLI or Portal, this property is set for you automatically.
When clustering is enabled, the JBoss EAP instances use the FILE_PING JGroups discovery protocol to discover new instances and persist the cluster information like the cluster members, their identifiers, and their IP addresses. On App Service, these files are under /home/clusterinfo/. The first EAP instance to start obtains read/write permissions on the cluster membership file. Other instances read the file, find the primary node, and coordinate with that node to be included in the cluster and added to the file.
The Premium V3 and Isolated V2 App Service Plan types can optionally be distributed across Availability Zones to improve resiliency and reliability for your business-critical workloads. This architecture is also known as zone redundancy. The JBoss EAP clustering feature is compatible with the zone redundancy feature.
Autoscale Rules
When configuring autoscale rules for horizontal scaling, it's important to remove instances incrementally (one at a time) to ensure each removed instance can transfer its activity (such as handling a database transaction) to another member of the cluster. When configuring your autoscale rules in the Portal to scale down, use the following options:
Operation: "Decrease count by"
Cool down: "5 minutes" or greater
Instance count: 1
You don't need to incrementally add instances (scaling out), you can add multiple instances to the cluster at a time.
App Service plans
JBoss EAP is available in the following pricing tiers: F1,
P0v3, P1mv3, P2mv3, P3mv3, P4mv3, and P5mv3.
JBoss server lifecycle
A JBoss EAP app in App Service goes through five distinct phases before actually launching the server.
See respective sections below for details as well as opportunities to customize it (such as through app settings).
1. Environment setup phase
The SSH service is started to enable secure SSH sessions with the container.
The Keystore of the Java runtime is updated with any public and private certificates defined in Azure portal.
Public certificates are provided by the platform in the /var/ssl/certs directory, and they're loaded to $JRE_HOME/lib/security/cacerts.
Private certificates are provided by the platform in the /var/ssl/private directory, and they're loaded to $JRE_HOME/lib/security/client.jks.
If any certificates are loaded in the Java keystore in this step, the properties javax.net.ssl.keyStore, javax.net.ssl.keyStorePassword and javax.net.ssl.keyStoreType are added to the JAVA_TOOL_OPTIONS environment variable.
Some initial JVM configuration is determined such as logging directories and Java memory heap parameters:
If you provide the –Xms or –Xmx flags for memory in the app setting JAVA_OPTS, these values override the ones provided by the platform.
If you configure the app setting WEBSITES_CONTAINER_STOP_TIME_LIMIT, the value is passed to the runtime property org.wildfly.sigterm.suspend.timeout, which controls the maximum shutdown wait time (in seconds) when JBoss is being stopped.
If the app is integrated with a virtual network, the App Service runtime passes a list of ports to be used for inter-server communication in the environment variable WEBSITE_PRIVATE_PORTS and launch JBoss using the clustering configuration. Otherwise, the standalone configuration is used.
For the clustering configuration, the server configuration file standalone-azure-full-ha.xml is used.
For the standalone configuration, the server configuration file standalone-full.xml is used.
2. Server launch phase
If JBoss is launched in the clustering configuration:
Each JBoss instance receives an internal identifier between 0 and the number of instances that the app is scaled out to.
If some files are found in the transaction store path for this server instance (by using its internal identifier), it means this server instance is taking the place of an identical service instance that crashed previously and left uncommitted transactions behind. The server is configured to resume the work on these transactions.
Regardless if JBoss starting in the clustering or standalone configuration, if the server version is 7.4 or above and the runtime uses Java 17, then the configuration is updated to enable the Elytron subsystem for security.
If you configure the app setting WEBSITE_JBOSS_OPTS, the value is passed to the JBoss launcher script. This setting can be used to provide paths to property files and more flags that influence the startup of JBoss.
3. Server configuration phase
At the start of this phase, App Service first waits for both the JBoss server and the admin interface to be ready to receive requests before continuing. This can take a few more seconds if Application Insights is enabled.
When both JBoss Server and the admin interface are ready, App Service does the following:
Adds the JBoss module azure.appservice, which provides utility classes for logging and integration with App Service.
Updates the console logger to use a colorless mode so that log files aren't full of color escaping sequences.
Sets up the integration with Azure Monitor logs.
Updates the binding IP addresses of the WSDL and management interfaces.
Adds the JBoss module azure.appservice.easyauth for integration with App Service authentication and Microsoft Entra ID.
Updates the logging configuration of access logs and the name and rotation of the main server log file.
Unless the app setting WEBSITE_SKIP_AUTOCONFIGURE_DATABASE is defined, App Service autodetects JDBC URLs in the App Service app settings. If valid JDBC URLs exist for PostgreSQL, MySQL, MariaDB, Oracle, SQL Server, or Azure SQL Database, it adds the corresponding driver(s) to the server and adds a data source for each of the JDBC URL and sets the JNDI name for each data source to java:jboss/env/jdbc/<app-setting-name>_DS, where <app-setting-name> is the name of the app setting.
If the clustering configuration is enabled, the console logger to be configured is checked.
If there are JAR files deployed to the /home/site/libs directory, a new global module is created with all of these JAR files.
At the end of the phase, App Service runs the custom startup script, if one exists. The search logic for the custom startup script as follows:
If you configured a startup command (in the Azure portal, with Azure CLI, etc.), run it; otherwise,
If the path /home/site/scripts/startup.sh exists, use it; otherwise,
If the path /home/startup.sh exists, use it.
The custom startup command or script runs as the root user (no need for sudo), so they can install Linux packages or launch the JBoss CLI to perform more JBoss install/customization commands (creating datasources, installing resource adapters), etc. For information on Ubuntu package management commands, see the Ubuntu Server documentation. For JBoss CLI commands, see the JBoss Management CLI Guide.
4. App deployment phase
The startup script deploys apps to JBoss by looking in the following locations, in order of precedence:
If you configured the app setting WEBSITE_JAVA_WAR_FILE_NAME, deploy the file designated by it.
If /home/site/wwwroot/app.war exists, deploy it.
If any other EAR and WAR files exist in /home/site/wwwroot, deploy them.
If /home/site/wwwroot/webapps exists, deploy the files and directories in it. WAR files are deployed as applications themselves, and directories are deployed as "exploded" (uncompressed) web apps.
If any standalone JSP pages exist in /home/site/wwwroot, copy them to the web server root and deploy them as one web app.
If no deployable files are found yet, deploy the default welcome page (parking page) in the root context.
5. Server reload phase
Once the deployment steps are complete, the JBoss server is reloaded to apply any changes that require a server reload.
After the server reloads, the application(s) deployed to JBoss EAP server should be ready to respond to requests.
The server runs until the App Service app is stopped or restarted. You can manually stop or restart the App Service app, or you trigger a restart when you deploy files or make configuration changes to the App Service app.
If the JBoss server exits abnormally in the clustering configuration, a final function called emit_alert_tx_store_not_empty is executed. The function checks if the JBoss process left a nonempty transaction store file in disk; if so, an error is logged in the console: Error: finishing server with non-empty store for node XXXX. When a new server instance is started, it looks for these nonempty transaction store files to resume the work (see 2. Server launch phase).
Tomcat baseline configuration
Note
This section applies to Linux only.
Java developers can customize the server settings, troubleshoot issues, and deploy applications to Tomcat with confidence if they know about the server.xml file and configuration details of Tomcat. Possible customizations include:
Customizing Tomcat configuration: By understanding the server.xml file and Tomcat's configuration details, you can fine-tune the server settings to match the needs of their applications.
Debugging: When an application is deployed on a Tomcat server, developers need to know the server configuration to debug any issues that might arise. This includes checking the server logs, examining the configuration files, and identifying any errors that might be occurring.
Troubleshooting Tomcat issues: Inevitably, Java developers encounter issues with their Tomcat server, such as performance problems or configuration errors. By understanding the server.xml file and Tomcat's configuration details, developers can quickly diagnose and troubleshoot these issues, which can save time and effort.
Deploying applications to Tomcat: To deploy a Java web application to Tomcat, developers need to know how to configure the server.xml file and other Tomcat settings. Understanding these details is essential for deploying applications successfully and ensuring that they run smoothly on the server.
When you create an app with built-in Tomcat to host your Java workload (a WAR file or a JAR file), there are certain settings that you get out of the box for Tomcat configuration. You can refer to the Official Apache Tomcat Documentation for detailed information, including the default configuration for Tomcat Web Server.
Additionally, there are certain transformations that are further applied on top of the server.xml for Tomcat distribution upon start. These are transformations to the Connector, Host, and Valve settings.
The latest versions of Tomcat have server.xml (8.5.58 and 9.0.38 onward). Older versions of Tomcat don't use transforms and might have different behavior as a result.
შემოუერთდით Meetup სერიას, რათა შექმნათ მასშტაბური AI გადაწყვეტილებები რეალურ სამყაროში გამოყენების შემთხვევებზე დაყრდნობით თანამემამულე დეველოპერებთან და ექსპერტებთან.
Mulai di sini dan pelajari cara membuat, memigrasikan, dan menskalakan aplikasi Java di Azure menggunakan layanan Azure. Gunakan alat dan kerangka kerja yang Anda kenal dan sukai - Musim Semi, Tomcat, WildFly, JBoss, WebLogic, WebSphere, Maven, Gradle, IntelliJ, Eclipse, Jenkins, Terraform, dan banyak lagi.