-
Notifications
You must be signed in to change notification settings - Fork 344
Add docs on deployment of Ktor apps to Azure App Service #671
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
dfuenzalida
wants to merge
19
commits into
ktorio:main
Choose a base branch
from
dfuenzalida:add-azure-app-service-docs
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
26e4697
Add docs on deployment Ktor apps to Azure App Service
dfuenzalida 35dbe85
Updated doc based on PR feedback: use toIntOrNull when parsing PORT, …
dfuenzalida e79c31b
Simplified language, fixed typo, added language to code blocks
dfuenzalida 6daaa34
Fix Azure CLI URL, added EngineMain suggestion, add dependency on bui…
dfuenzalida aae58af
Fix typo: installed *on* your machine
dfuenzalida aedd773
Improve clarity/style
dfuenzalida 6b50631
Improve clarity/style (2)
dfuenzalida 1f5d3b8
Improve clarity/style (3)
dfuenzalida e7de564
Improve clarity/style (4)
dfuenzalida 1e95077
Improve clarity/style (5)
dfuenzalida c413f00
Improve clarity/style (6)
dfuenzalida a867c3e
Improve clarity/style (6)
dfuenzalida ee6bede
Improve clarity/style (8)
dfuenzalida 4424d62
Improve clarity/style (9)
dfuenzalida 17226b2
Improve clarity/style (10)
dfuenzalida aa67b01
Improve clarity/style (11)
dfuenzalida 4ebe38a
Improve clarity/style (12)
dfuenzalida ede0682
Improve clarity/style (13)
dfuenzalida 473ae3e
Added link to Azure App Service homepage
dfuenzalida File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,195 @@ | ||
[//]: # (title: Azure App Service) | ||
|
||
<show-structure for="chapter" depth="2"/> | ||
|
||
<link-summary>This tutorial shows how to build, configure and deploy your Ktor application to [Azure App Service](https://azure.microsoft.com/products/app-service/).</link-summary> | ||
|
||
This tutorial shows how to build, configure and deploy your Ktor application to [Azure App Service](https://azure.microsoft.com/products/app-service/). | ||
|
||
## Prerequisites {id="prerequisites"} | ||
Before starting this tutorial, you will need the following: | ||
* An Azure account ([Free trial here](https://azure.microsoft.com/en-us/free/)). | ||
* The [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) installed on your machine. | ||
|
||
## Create a sample application {id="create-sample-app"} | ||
|
||
Create a sample application as described in [](server-create-a-new-project.topic). This example shows code and commands based on the following projects: [embedded-server](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/embedded-server) and [engine-main](https://github.com/ktorio/ktor-documentation/tree/%ktor_version%/codeSnippets/snippets/engine-main). | ||
|
||
> The tutorial above provides two ways to configure your application: either by specifying values directly in the code or by using a configuration file. In both cases, the key configuration is the port on which the server listens for incoming requests. | ||
|
||
## Set up the application {id="setup-app"} | ||
|
||
### Step 1: Set up the port {id="port"} | ||
|
||
In Azure App Service, the environment variable `PORT` contains the port number open for incoming requests. Depending on how you created the app in [configure a Ktor server](server-create-and-configure.topic), you'll need to update your code to read this environment variable in one of two places: | ||
|
||
* If you used the example with port configuration **in code**, the `PORT` environment variable can be read with `System.getenv()` and parsed to an integer with `.toIntOrNull()`. Open the file `Application.kt` and change the port number as shown below: | ||
|
||
```kotlin | ||
fun runBasicServer() { | ||
val port = System.getenv("PORT")?.toIntOrNull() ?: 8080 | ||
embeddedServer(Netty, port = port) { | ||
// ... | ||
}.start(wait = true) | ||
} | ||
``` | ||
* If the server configuration is defined **in the config file** `application.conf`, update it to read the `PORT` environment variable as in the following example: | ||
|
||
``` | ||
ktor { | ||
deployment { | ||
port = ${PORT:8080} | ||
} | ||
} | ||
``` | ||
{style="block"} | ||
|
||
### Step 2: Add plugins {id="plugins"} | ||
Open the `build.gradle.kts` file and add the following lines to the `plugins` section: | ||
```kotlin | ||
plugins { | ||
application | ||
kotlin("jvm") | ||
id("io.ktor.plugin") version "%ktor_version%" // ADDED | ||
id("com.microsoft.azure.azurewebapp") version "1.10.0" // ADDED | ||
} | ||
``` | ||
|
||
The `io.ktor.plugin` will provide the task used to create a [fat JAR](server-fatjar.md) and the [Azure WebApp Plugin for Gradle](https://github.com/microsoft/azure-gradle-plugins) will be used to create all the required resources in Azure with ease. | ||
|
||
Make sure a `mainClass` is defined in the `application` section, so that there's a well-defined entry point for your fat JAR: | ||
|
||
```kotlin | ||
application { | ||
mainClass.set("com.example.ApplicationKt") | ||
} | ||
``` | ||
If you created the project with the `engine-main` template, the main class will look like the following: | ||
|
||
```kotlin | ||
application { | ||
mainClass.set("io.ktor.server.netty.EngineMain") | ||
} | ||
``` | ||
|
||
|
||
### Step 3: Configuration {id="configuration"} | ||
|
||
If you already created a Java web app in App Service that you want to deploy to, you can skip this step. | ||
|
||
Otherwise, add the following entries to `build.gradle.kts` at the end of the file so that the Azure Webapp Plugin creates one for you: | ||
|
||
```kotlin | ||
// Rename the fat JAR to the name that the deploy task expects | ||
ktor { | ||
fatJar { | ||
archiveFileName.set("embedded-server.jar") | ||
} | ||
} | ||
|
||
// Disable the `jar` task that Azure Plugin would normally run | ||
// to deploy the archive created by the `fatJar` task instead | ||
tasks.named("jar") { | ||
enabled = false | ||
} | ||
|
||
// Ensure the deploy task builds the fat JAR first | ||
tasks.named("azureWebAppDeploy") { | ||
dependsOn("buildFatJar") | ||
} | ||
|
||
// Azure Webapp Plugin configuration | ||
azurewebapp { | ||
subscription = "YOUR-SUBSCRIPTION-ID" | ||
resourceGroup = "RESOURCE-GROUP-NAME" | ||
appName = "WEBAPP-NAME" | ||
pricingTier = "YOUR-PLAN" // e.g. "F1", "B1", "P0v3", etc. | ||
region = "YOUR-REGION" // e.g. "westus2" | ||
setRuntime(closureOf<com.microsoft.azure.gradle.configuration.GradleRuntimeConfig> { | ||
os("Linux") // Or "Windows" | ||
webContainer("Java SE") | ||
javaVersion("Java 21") | ||
}) | ||
setAuth(closureOf<com.microsoft.azure.gradle.auth.GradleAuthConfig> { | ||
type = "azure_cli" | ||
}) | ||
} | ||
dfuenzalida marked this conversation as resolved.
Show resolved
Hide resolved
|
||
``` | ||
|
||
For detailed descriptions of the available configuration properties, see [the Webapp Configuration documentation](https://github.com/microsoft/azure-gradle-plugins/wiki/Webapp-Configuration). | ||
|
||
* The values for `pricingTier` (Service Plan) can be found [for Linux](https://azure.microsoft.com/en-us/pricing/details/app-service/linux/) and [for Windows](https://azure.microsoft.com/en-us/pricing/details/app-service/windows/). | ||
* The list of values for `region` can be obtained with the following Azure CLI command: `az account list-locations --query "[].name" --output tsv` or by searching for "App Service" in [the Product Availability table](https://go.microsoft.com/fwlink/?linkid=2300348&clcid=0x409). | ||
|
||
## Deploy the application {id="deploy-app"} | ||
|
||
### To a new web app | ||
|
||
The authentication method used by the Azure Web App Deploy plugin uses the Azure CLI. If you haven't already, log in once with `az login` and follow the instructions. | ||
|
||
Finally, deploy the application by running the `azureWebAppDeploy` task, which is set to build the fat JAR first and then deploy: | ||
|
||
<tabs group="os"> | ||
<tab title="Linux/macOS" group-key="unix"> | ||
<code-block>./gradlew :embedded-server:azureWebAppDeploy</code-block> | ||
</tab> | ||
<tab title="Windows" group-key="windows"> | ||
<code-block>gradlew.bat :embedded-server:azureWebAppDeploy</code-block> | ||
</tab> | ||
</tabs> | ||
|
||
This task will create the resource group, plan, and web app, and then deploy the fat JAR. When the deployment succeeds, you should see output like the following: | ||
|
||
```text | ||
> Task: :embedded-server:azureWebAppDeploy | ||
Auth type: AZURE_CLI | ||
Username: [email protected] | ||
Subscription: Some Subscription(13936cf1-cc18-40be-a0d4-177fe532b3dd) | ||
Start creation Resource Group(resource-group) in region (Some Region) | ||
Resource Group (resource-group) is successfully created. | ||
Start creating App Service plan (asp-your-webapp-name)... | ||
App Service plan (asp-your-webapp-name) is successfully created | ||
Start creating Web App(your-webapp-name)... | ||
Web App(your-webapp-name) is successfully created | ||
Trying to deploy artifact to your-webapp-name... | ||
Deploying (C:\docs\ktor-documentation\codeSnippets\snippets\embedded-server\build\libs\embedded-server.jar)[jar] ... | ||
Application url: https://your-webapp-name.azurewebsites.net | ||
``` | ||
|
||
When the deployment completes, you should be able to see your new web app running at the URL shown above. | ||
|
||
### To an existing web app | ||
|
||
If you already have an existing Java web app in Azure App Service, first build the fat JAR by executing the `buildFatJar` task provided by the [Ktor plugin](#plugins): | ||
|
||
<tabs group="os"> | ||
<tab title="Linux/macOS" group-key="unix"> | ||
<code-block>./gradlew :embedded-server:buildFatJar</code-block> | ||
</tab> | ||
<tab title="Windows" group-key="windows"> | ||
<code-block>gradlew.bat :embedded-server:buildFatJar</code-block> | ||
</tab> | ||
</tabs> | ||
|
||
Then, deploy the fat JAR created earlier using the following command of the Azure CLI: | ||
|
||
```bash | ||
az webapp deploy -g RESOURCE-GROUP-NAME -n WEBAPP-NAME --src-path ./path/to/embedded-server.jar --restart true | ||
``` | ||
|
||
This command will upload the JAR file and restart your web app. After a while, you should see the result of the deployment: | ||
|
||
```text | ||
Deployment type: jar. To override deployment type, please specify the --type parameter. Possible values: war, jar, ear, zip, startup, script, static | ||
Initiating deployment | ||
Deploying from local path: ./snippets/embedded-server/build/libs/embedded-server.jar | ||
Warming up Kudu before deployment. | ||
Warmed up Kudu instance successfully. | ||
Polling the status of sync deployment. Start Time: 2025-09-07 00:07:14.729383+00:00 UTC | ||
Status: Build successful. Time: 5(s) | ||
Status: Starting the site... Time: 23(s) | ||
Status: Starting the site... Time: 41(s) | ||
Status: Site started successfully. Time: 44(s) | ||
Deployment has completed successfully | ||
You can visit your app at: http://your-app-name.some-region.azurewebsites.net | ||
``` |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.