Azure Linux Web Apps are great for Python and Node.js applications, but the Terraform configuration has some gotchas. Here's how to get it right.
Python with Gunicorn
For a Python Flask/FastAPI app:
resource "azurerm_linux_web_app" "python_app" {
name = "app-python-example"
resource_group_name = azurerm_resource_group.this.name
location = azurerm_resource_group.this.location
service_plan_id = azurerm_service_plan.this.id
site_config {
application_stack {
python_version = "3.11"
}
app_command_line = "gunicorn --workers 4 --threads 2 --bind 0.0.0.0:8000 app:app"
}
app_settings = {
"SCM_DO_BUILD_DURING_DEPLOYMENT" = "true"
"WEBSITES_PORT" = "8000"
}
}
Key Points
app_command_line - This is your startup command. For Gunicorn:
--workers 4- Number of worker processes (adjust based on plan size)--threads 2- Threads per worker--bind 0.0.0.0:8000- Listen on all interfaces, port 8000app:app- Module:application (your Flask/FastAPI app object)
WEBSITES_PORT - Must match the port in your startup command.
SCM_DO_BUILD_DURING_DEPLOYMENT - Runs pip install -r requirements.txt during deployment.
Python with Uvicorn (FastAPI)
For async FastAPI apps, use Uvicorn:
site_config {
application_stack {
python_version = "3.11"
}
app_command_line = "uvicorn main:app --host 0.0.0.0 --port 8000 --workers 4"
}
Or combine with Gunicorn for better process management:
app_command_line = "gunicorn main:app --workers 4 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:8000"
Node.js Configuration
resource "azurerm_linux_web_app" "node_app" {
name = "app-node-example"
resource_group_name = azurerm_resource_group.this.name
location = azurerm_resource_group.this.location
service_plan_id = azurerm_service_plan.this.id
site_config {
application_stack {
node_version = "18-lts"
}
app_command_line = "npm start"
}
app_settings = {
"WEBSITE_NODE_DEFAULT_VERSION" = "~18"
"SCM_DO_BUILD_DURING_DEPLOYMENT" = "true"
}
}
For PM2 process management:
app_command_line = "pm2 start ecosystem.config.js --no-daemon"
Common Issues
App not starting - Check the startup command matches your application structure. Use Log Stream in the portal to see errors.
Port mismatch - Ensure WEBSITES_PORT matches your app's listen port.
Dependencies not installed - Set SCM_DO_BUILD_DURING_DEPLOYMENT to true, or use a deployment slot with build enabled.
Wrong Python/Node version - Check available versions with az webapp list-runtimes --os linux.
VNET Integration
If your app needs to access private resources:
resource "azurerm_app_service_virtual_network_swift_connection" "this" {
app_service_id = azurerm_linux_web_app.python_app.id
subnet_id = azurerm_subnet.app_integration.id
}
The subnet must be delegated to Microsoft.Web/serverFarms.
Need help deploying web applications to Azure? Get in touch - we help teams build and deploy cloud applications.