Deploying Web Applications in App Service with Terraform
Introduction
Azure App Service is a fully managed platform-as-a-service (PaaS) offering that enables developers to build, deploy, and scale web applications effortlessly. With App Service, you can host various types of applications, including ASP.NET, PHP, Node.js, Python, and more. The azurerm_app_service resource in Terraform allows you to define and manage Azure App Service resources via Infrastructure as Code (IaC).
Infrastructure as Code is vital for modern cloud development as it allows teams to define their infrastructure in a declarative manner, automate deployments, and maintain consistency across environments. In this tutorial, we will explore how to set up web applications in Azure App Service using Terraform, focusing on key components such as App Service Plans, deployment slots, and environment variables.
Use Cases for Azure App Service include hosting websites, web APIs, and mobile backends, making it an integral part of cloud-based applications.
Prerequisites
To follow along with this tutorial, ensure you have the following:
Terraform CLI installed on your local machine. You can download it from Terraform's official site.
An Azure subscription. If you don’t have one, you can create a free account here.
Azure CLI installed and configured. You can install it by following the instructions here.
A service principal set up to allow Terraform to authenticate with Azure. You can create one using the following command:
az ad sp create-for-rbac --name "<your-service-principal-name>" --role Contributor --scopes /subscriptions/<your-subscription-id>
Fundamental Concepts
Before diving into the code, let's cover some fundamental concepts:
- App Service Plan: Defines the region, pricing tier, and resources for your App Service apps. All apps in the same plan share the same resources.
- Deployment Slot: A live app instance running in the same App Service Plan as the production app. Slots allow you to stage and validate changes before swapping them into production.
- Environment Variables: Key-value pairs available to your application, allowing you to configure settings without hardcoding them into the application.
Resource Syntax
The basic syntax for defining an Azure App Service in Terraform is as follows:
resource "azurerm_app_service" "example" {
name = "<app-service-name>"
location = "<location>"
resource_group_name = "<resource-group-name>"
app_service_plan_id = azurerm_app_service_plan.example.id
site_config {
always_on = true
dotnet_framework_version = "v4.0"
app_settings = {
"ASPNETCORE_ENVIRONMENT" = "Production"
}
}
}
Arguments Table
| Argument | Description |
|---|---|
name |
The name of the App Service. |
location |
The Azure region where the resource will be deployed. |
resource_group_name |
The name of the resource group to which the resource belongs. |
app_service_plan_id |
The ID of the App Service Plan that the App Service will use. |
site_config |
Configuration options for the App Service site. |
Practical Examples
Example 1: Basic App Service without Slots
resource "azurerm_resource_group" "example" {
name = "myResourceGroup"
location = "East US"
}
resource "azurerm_app_service_plan" "example" {
name = "example-app-service-plan"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
sku {
tier = "Standard"
size = "S1"
}
}
resource "azurerm_app_service" "example" {
name = "myUniqueAppServiceName"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
app_service_plan_id = azurerm_app_service_plan.example.id
site_config {
always_on = true
app_settings = {
"ASPNETCORE_ENVIRONMENT" = "Production"
}
}
}
Example 2: App Service with Deployment Slot
resource "azurerm_app_service_slot" "example_slot" {
name = "staging"
app_service_name = azurerm_app_service.example.name
resource_group_name = azurerm_resource_group.example.name
app_settings = {
"ASPNETCORE_ENVIRONMENT" = "Staging"
}
}
Example 3: Adding Environment Variables
resource "azurerm_app_service" "example" {
name = "myAppServiceWithEnv"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
app_service_plan_id = azurerm_app_service_plan.example.id
site_config {
app_settings = {
"DATABASE_CONNECTION_STRING" = "your_connection_string_here"
"API_KEY" = "your_api_key_here"
}
}
}
Example 4: Swap Slots
resource "azurerm_app_service_slot" "production" {
name = "production"
app_service_name = azurerm_app_service.example.name
resource_group_name = azurerm_resource_group.example.name
}
resource "azurerm_app_service_slot_swap" "swap" {
app_service_name = azurerm_app_service.example.name
resource_group_name = azurerm_resource_group.example.name
source_slot_name = azurerm_app_service_slot.example_slot.name
target_slot_name = azurerm_app_service_slot.production.name
}
Example 5: Integrate CI/CD with GitHub
resource "azurerm_app_service_source_control" "example" {
app_service_id = azurerm_app_service.example.id
repo_url = "https://github.com/your/repo.git"
branch = "main"
github_action {
repository = "your/repo"
token = "your_github_token"
}
}
Example 6: Custom Domain Configuration
resource "azurerm_app_service_custom_domain" "example" {
app_service_id = azurerm_app_service.example.id
custom_domain = "www.yourcustomdomain.com"
}
Example 7: SSL Binding for Custom Domain
resource "azurerm_app_service_certificate" "example" {
name = "myCertificate"
resource_group_name = azurerm_resource_group.example.name
location = azurerm_resource_group.example.location
key_vault_secret_id = "https://your_key_vault.vault.azure.net/secrets/your_secret_name"
}
Example 8: Scale App Service Plan
resource "azurerm_app_service_plan" "example" {
name = "example-app-service-plan"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
sku {
tier = "PremiumV2"
size = "P1v2"
}
}
Real-World Use Cases
Scenario 1: E-Commerce Application
In this case, a developer wants to deploy an e-commerce platform with a staging environment for testing new features. They can set up an App Service Plan with multiple slots for different environments (staging, production) and use GitHub Actions for CI/CD.
Scenario 2: API Hosting
A company needs to host a RESTful API using Azure App Service. They can define the service, configure environment variables for sensitive information, and utilize deployment slots to deploy new versions without downtime.
Scenario 3: Multi-Region Deployment
For high availability, a business may want to deploy the same application across multiple regions. Using multiple App Service Plans, they can configure geo-replication and route traffic using Azure Traffic Manager.
Best Practices
- Use Deployment Slots: Always deploy to a staging slot first and swap to production to minimize downtime and validate changes.
- Implement Environment Variables: Avoid hardcoding sensitive data in your application by using environment variables.
- Resource Naming Conventions: Use consistent naming conventions for easy identification and management of resources.
- Version Control Your Terraform Configurations: Store your Terraform configurations in a version control system like Git for easy tracking and collaboration.
- Use Output Variables: Define output variables to expose important information, such as URLs and resource IDs, for easy access after deployment.
Common Errors
Error: "The name is already in use."
- Cause: The App Service name must be unique across Azure.
- Solution: Choose a different name for your App Service.
Error: "Insufficient resources in the location."
- Cause: The selected pricing tier is not available in the chosen region.
- Solution: Change the region or select a different pricing tier.
Error: "Invalid resource ID."
- Cause: The resource ID provided is incorrect or does not exist.
- Solution: Verify the resource ID and ensure that the resource is created before referencing it.
Error: "Deployment failed."
- Cause: Configuration errors in the HCL file.
- Solution: Review the Terraform plan output for detailed error messages and correct any issues.
Related Resources
| Resource | Description |
|---|---|
| Terraform Azure Provider | Official documentation for the Azure Provider in Terraform. |
| Azure App Service Documentation | Comprehensive guide to Azure App Service features and capabilities. |
| Terraform Best Practices | Recommendations for using Terraform effectively in your projects. |
Complete Infrastructure Script
Here’s a complete Terraform configuration to deploy an Azure App Service with a staging slot:
provider "azurerm" {
features {}
}
resource "azurerm_resource_group" "example" {
name = "myResourceGroup"
location = "East US"
}
resource "azurerm_app_service_plan" "example" {
name = "example-app-service-plan"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
sku {
tier = "Standard"
size = "S1"
}
}
resource "azurerm_app_service" "example" {
name = "myUniqueAppServiceName"
location = azurerm_resource_group.example.location
resource_group_name = azurerm_resource_group.example.name
app_service_plan_id = azurerm_app_service_plan.example.id
site_config {
always_on = true
app_settings = {
"ASPNETCORE_ENVIRONMENT" = "Production"
}
}
}
resource "azurerm_app_service_slot" "example_slot" {
name = "staging"
app_service_name = azurerm_app_service.example.name
resource_group_name = azurerm_resource_group.example.name
app_settings = {
"ASPNETCORE_ENVIRONMENT" = "Staging"
}
}
To deploy this configuration, run the following commands in your terminal:
terraform init
terraform plan
terraform apply
Conclusion
In this tutorial, we explored how to deploy web applications using Azure App Service and Terraform. We covered key features such as App Service Plans, deployment slots, and environment variables. By using Terraform for your infrastructure management, you can ensure consistent deployments and effortless scalability.
Next Steps
- Explore how to integrate Azure App Service with other Azure services like Azure SQL Database or Blob Storage.
- Implement CI/CD pipelines with GitHub Actions or Azure DevOps for automated deployments.