# Deploy to Azure App Service

<Badge text="🧪 Preview" variant="note" size="large" class="mb-1" />

Use `aspire deploy` to deploy Aspire applications to Azure App Service. Aspire provisions the App Service plan, Azure Container Registry, managed identity, and the App Service websites for supported web-facing app resources in the App Service environment.

<LearnMore>
  Start with [Deploy to Azure](/deployment/azure/) for the shared Azure
  deployment model and target selection.
</LearnMore>

## Prerequisites

- [Aspire prerequisites](/get-started/prerequisites/)
- [Aspire CLI](/get-started/install-cli/) installed
- For local deployment with the default credential source, [Azure CLI](https://learn.microsoft.com/cli/azure/install-azure-cli) installed and available on your `PATH`
- An active Azure account and subscription

By default, local deployment uses Azure CLI credentials. Authenticate with Azure CLI before deploying:

```bash title="Authenticate with Azure CLI"
az login
```

## Configure your AppHost for Azure App Service

Add Azure App Service support to your AppHost:

```bash title="Aspire CLI — Add Azure App Service"
aspire add azure-appservice
```

The Aspire CLI adds the [📦 Aspire.Hosting.Azure.AppService](https://www.nuget.org/packages/Aspire.Hosting.Azure.AppService) integration to your AppHost. If prompted, select the matching package result.

Then add the App Service environment in your AppHost and a supported web app or API resource. App Service environments automatically target supported project resources and Dockerfile-backed web containers:

```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureAppServiceEnvironment("app-service-env");

builder.AddDockerfile("web", "./web")
    .WithHttpEndpoint(port: 8080, targetPort: 8080, name: "http")
    .WithExternalHttpEndpoints();

builder.Build().Run();

```
```typescript title="apphost.ts"
import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

await builder.addAzureAppServiceEnvironment("app-service-env");

await builder
    .addDockerfile("web", "./web")
    .withHttpEndpoint({ port: 8080, targetPort: 8080, name: "http" })
    .withExternalHttpEndpoints();

await builder.build().run();
```

For a standard App Service deployment, you only need the environment and a supported app resource. Use `PublishAsAzureAppServiceWebsite` only when you want to customize the generated website or deployment slot.

## How Aspire maps your app to Azure App Service

### Supported app workloads

App Service environments automatically target:

- project resources for web apps and APIs
- Dockerfile-backed web containers with a supported public HTTP or HTTPS endpoint

Use managed services for backing infrastructure such as databases, caches, and brokers. App Service websites aren't deployment targets for those workloads.

If one AppHost uses multiple Azure environments, assign each supported resource to the environment you want it to use.

### Default mapping

Start with the common case:

| AppHost endpoint shape              | Azure App Service result    |
| ----------------------------------- | --------------------------- |
| One external HTTP or HTTPS endpoint | One public website endpoint |

App Service routes public traffic to the app's target port, even if the app listens on a development port such as `8080`.

### Constraints

Azure App Service uses a public website model:

- only external `http` and `https` endpoints are supported
- only one distinct external target port is supported for each deployed app
- internal-only endpoints, multi-port public apps, and arbitrary infrastructure containers such as Redis or databases don't fit this deployment model

### Image publishing and identity

During `aspire deploy`, Aspire:

- provisions or attaches an Azure Container Registry
- builds container images for supported resources
- pushes those images to the registry
- creates a user-assigned managed identity
- grants the deployed websites permission to pull images

This lets App Service pull deployed images without manual registry credentials.

### Health checks

App Service exposes one health check path per website. If you configure multiple probes, Aspire prefers the liveness probe and uses that path for the App Service health check.

## Customize generated App Service websites

Use `PublishAsAzureAppServiceWebsite` when you want to customize the generated website or deployment slot. It isn't required for a standard App Service deployment.

```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureAppServiceEnvironment("app-service-env");

builder.AddProject<Projects.Api>("api")
    .PublishAsAzureAppServiceWebsite((infrastructure, website) =>
    {
        website.AppSettings.Add("ASPNETCORE_ENVIRONMENT", new AppServiceConfigurationSetting
        {
            Name = "ASPNETCORE_ENVIRONMENT",
            Value = "Production"
        });

        website.Tags.Add("Environment", "Production");
    });

builder.Build().Run();

```
```typescript title="apphost.ts"
import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

await builder.addAzureAppServiceEnvironment("app-service-env");

await builder
    .addProject("api", "../Api/Api.csproj", "https")
    .publishAsAzureAppServiceWebsite({
        configure: async (_infrastructure, _website) => {
            // Customize the generated production website here.
        }
    });

await builder.build().run();
```

### Customize deployment slots separately

When you use deployment slots, production website customizations and slot customizations are configured separately.

```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureAppServiceEnvironment("app-service-env")
    .WithDeploymentSlot("staging");

builder.AddProject<Projects.Api>("api")
    .PublishAsAzureAppServiceWebsite(
        configure: (infrastructure, website) =>
        {
            website.Tags.Add("Environment", "Production");
        },
        configureSlot: (infrastructure, slot) =>
        {
            slot.Tags.Add("Environment", "Staging");
        });

builder.Build().Run();

```
```typescript title="apphost.ts"
import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

await builder.addAzureAppServiceEnvironment("app-service-env")
    .withDeploymentSlot("staging");

await builder
    .addProject("api", "../Api/Api.csproj", "https")
    .publishAsAzureAppServiceWebsite({
        configureSlot: async (_infrastructure, _slot) => {
            // Customize the generated deployment slot here.
        }
    });

await builder.build().run();
```

### Environment-variable name validation

Azure App Service application settings accept only letters, numbers, and underscores. If a connection name contains dashes and you intentionally want to bypass App Service name validation for that website, call `SkipEnvironmentVariableNameChecks()` after `PublishAsAzureAppServiceWebsite`.

```csharp title="AppHost.cs"
builder.AddProject<Projects.Api>("api")
    .PublishAsAzureAppServiceWebsite()
    .SkipEnvironmentVariableNameChecks();
```
```typescript title="apphost.ts"
await builder
    .addProject("api", "../Api/Api.csproj", "https")
    .publishAsAzureAppServiceWebsite()
    .skipEnvironmentVariableNameChecks();
```
<LearnMore>
  For general Azure resource customization such as naming, existing resources,
  role assignments, and outputs, see [Customize Azure
  resources](/integrations/cloud/azure/customize-resources/). For App
  Service-specific hosting details, see [Azure App Service Hosting
  integration](/integrations/cloud/azure/azure-app-service/azure-app-service-host/).
</LearnMore>

## Deploy with aspire deploy

Once your AppHost is configured, deploy it with:

```bash title="Deploy to Azure App Service"
aspire deploy
```

Aspire can prompt for missing Azure settings and AppHost parameters during an interactive deploy, then provisions and deploys the App Service resources behind the scenes.

<LearnMore>
For Azure authentication, shared Azure settings, and `Parameters__*` inputs, see [Deploy to Azure](/deployment/azure/) and [Environments](/deployment/environments/#how-parameter-values-are-resolved).
</LearnMore>

## Monitoring and diagnostics

### Aspire Dashboard

The Azure App Service environment includes the Aspire Dashboard by default, so you can inspect logs, traces, metrics, and topology for the deployed compute resources after deployment. Managed Azure backing services aren't shown as dashboard resources there. If you don't want to deploy it, disable it on the environment:

```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureAppServiceEnvironment("app-service-env")
    .WithDashboard(false);

```
```typescript title="apphost.ts"
import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

const appServiceEnv = await builder.addAzureAppServiceEnvironment("app-service-env");
await appServiceEnv.withDashboard(false);
```

### Application Insights

Enable Azure Application Insights on the App Service environment when you want Aspire to provision monitoring resources and flow the connection string into your deployed websites:

```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureAppServiceEnvironment("app-service-env")
    .WithAzureApplicationInsights();

```
```typescript title="apphost.ts"
import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

const appServiceEnv = await builder.addAzureAppServiceEnvironment("app-service-env");
await appServiceEnv.withAzureApplicationInsights();
```

<LearnMore>
  For existing Application Insights resources and advanced configuration, see
  [Azure App Service Hosting
  integration](/integrations/cloud/azure/azure-app-service/azure-app-service-host/).
</LearnMore>

## Deployment slots

Use deployment slots when you want to deploy the websites in your environment into a staging slot before swapping into production:

```csharp title="AppHost.cs"
var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureAppServiceEnvironment("app-service-env")
    .WithDeploymentSlot("staging");

```
```typescript title="apphost.ts"
import { createBuilder } from './.modules/aspire.js';

const builder = await createBuilder();

const appServiceEnv = await builder.addAzureAppServiceEnvironment("app-service-env");
await appServiceEnv.withDeploymentSlot("staging");
```

<LearnMore>
  For existing plans, advanced customization, and deployment slot behavior, see
  [Azure App Service Hosting
  integration](/integrations/cloud/azure/azure-app-service/azure-app-service-host/).
</LearnMore>

## Deployment considerations

:::caution
Azure App Service application settings accept only letters, numbers, and underscores. If a connection name contains dashes, review the App Service hosting integration guidance for the environment-variable validation workaround before deployment.
:::

<LearnMore>
  For environment-variable validation details and advanced App Service
  customization, see [Azure App Service Hosting
  integration](/integrations/cloud/azure/azure-app-service/azure-app-service-host/).
</LearnMore>

## See also

- [Deploy to Azure](/deployment/azure/)
- [Azure App Service Hosting integration](/integrations/cloud/azure/azure-app-service/azure-app-service-host/)
- [Azure security best practices](/deployment/azure/azure-security-best-practices/)
- [App Service overview](https://learn.microsoft.com/azure/app-service/overview)
- [Configure a custom container for Azure App Service](https://learn.microsoft.com/azure/app-service/configure-custom-container#configure-port-number)