Azure AI Hub LogoAzure AI Hub
03 - Container Deployment

02 - Runtime & App Settings

Learn how to configure startup commands, port routing, persistent SMB storage, always-on, automated health checks, environment variables, connection strings, and Key Vault references.

Configuring Container Runtime Behavior

Once your container is deployed, you control how App Service executes, routes, persists, and monitors your container using 5 runtime settings.

1. Custom Startup Commands (--startup-file)

App Service executes containers using the default CMD defined in your Dockerfile. You can override CMD (while keeping ENTRYPOINT intact) when you need custom runtime flags, initialization tasks, or database migrations before launching the server.

Why: Overrides default container startup arguments or runs initialization scripts prior to server launch.

# Simple startup override
az webapp config set \
  -g container-learning \
  -n inference-api-test \
  --startup-file "gunicorn --bind=0.0.0.0:8000 --workers=4 app:application"

# Multi-command shell execution (running migrations first)
az webapp config set \
  -g container-learning \
  -n inference-api-test \
  --startup-file "/bin/bash -c 'python migrate.py && gunicorn app:application'"

2. Port Routing & TLS Termination (WEBSITES_PORT)

App Service automatically routes incoming HTTP/HTTPS traffic to port 80 or 8080 inside custom containers. If your application listens on a non-standard port (e.g. 8000, 3000, 5000), set WEBSITES_PORT.

Why: Directs the Azure front-end load balancer to forward HTTP traffic to your container's exact listening port.

az webapp config appsettings set \
  -g container-learning \
  -n inference-api-test \
  --settings WEBSITES_PORT=8000

Azure App Service terminates TLS at the platform load balancer level. This means your container receives unencrypted HTTP traffic internally on WEBSITES_PORT even when clients connect via HTTPS. Only one HTTP port can be exposed per container.

Common Framework Default Ports:

  • Node.js (Express): Port 3000 (WEBSITES_PORT=3000)
  • Python (Gunicorn / FastAPI / Flask): Port 8000 or 5000 (WEBSITES_PORT=8000)
  • Java (Spring Boot): Port 8080 (WEBSITES_PORT=8080)
  • ASP.NET Core: Port 80 (Default, no setting required)

3. Persistent Storage (WEBSITES_ENABLE_APP_SERVICE_STORAGE)

By default, custom container file systems on Linux are ephemeral (any files written to disk are destroyed when the container restarts or scales). Setting WEBSITES_ENABLE_APP_SERVICE_STORAGE=true mounts a persistent SMB share at /home.

Why: Retains application uploads, state files, and log files across container restarts and shares them across scaled instances.

az webapp config appsettings set \
  -g container-learning \
  -n inference-api-test \
  --settings WEBSITES_ENABLE_APP_SERVICE_STORAGE=true

Testing Persistent Storage via API Endpoint:

# Get App URL
APP_URL=$(az webapp show -g container-learning -n inference-api-test --query defaultHostName -o tsv)

# Submit document to processing endpoint
curl -X POST "https://$APP_URL/process" \
  -H "Content-Type: text/plain" \
  --data-binary @document.txt

# Verify saved document persists under /home
curl "https://$APP_URL/documents"

4. Always-On (--always-on true)

By default, inactive Web Apps enter a sleep state after ~20 minutes of no traffic. The next incoming request triggers a cold start (pulling/starting the container, which can take 15–60 seconds).

Why: Keeps the container pre-warmed in server RAM, eliminating cold start latency for production workloads.

az webapp config set \
  -g container-learning \
  -n inference-api-test \
  --always-on true

Note: Always-On requires the Basic (B1) pricing tier or higher.


5. Automated Health Checks (healthCheckPath)

App Service can probe your container's health every 60 seconds by sending HTTP GET requests to a specified route (e.g. /health). If an instance returns 10 consecutive failed pings (5xx error or timeout), App Service removes it from the load balancer rotation and restarts the container.

Why: Automatically detects deadlocks, database connection loss, or crashed threads and recovers your Web App without manual intervention.

az webapp config set \
  -g container-learning \
  -n inference-api-test \
  --generic-configurations '{"healthCheckPath": "/health"}'

Configuring Application Settings & Secrets

Application settings allow passing configuration values and secrets into your container at runtime without hardcoding them in the Docker image. App Service injects app settings as standard environment variables when the container starts.

1. Setting Environment Variables

All app settings are encrypted at rest by Azure before being injected into the container environment.

Why: Sets environment-specific configurations (such as storage names or log levels) injected into the container at startup.

az webapp config appsettings set \
  -g container-learning \
  -n inference-api-test \
  --settings \
    STORAGE_ACCOUNT_NAME=mystorageaccount \
    LOG_LEVEL=INFO \
    MAX_DOCUMENT_SIZE_MB=50

Accessing Environment Variables in Python:

import os

storage_account = os.environ.get('STORAGE_ACCOUNT_NAME')
log_level = os.environ.get('LOG_LEVEL', 'WARNING')
max_size = int(os.environ.get('MAX_DOCUMENT_SIZE_MB', 10))

For Linux containers, nested configuration keys that use colons (:) in .NET must use double underscores (__). For example, ConnectionStrings:DefaultConnection becomes ConnectionStrings__DefaultConnection.


2. Database Connection Strings

App Service supports specialized connection string configurations that automatically append database type prefixes:

  • SQL Server: SQLCONNSTR_
  • SQL Azure: SQLAZURECONNSTR_
  • MySQL: MYSQLCONNSTR_
  • PostgreSQL: POSTGRESQLCONNSTR_
  • Custom: CUSTOMCONNSTR_
az webapp config connection-string set \
  -g container-learning \
  -n inference-api-test \
  --connection-string-type SQLAzure \
  --settings DefaultConnection="Server=myserver.database.windows.net;Database=mydb;..."

(Note: For Python and Node.js applications, standard App Settings are generally simpler and preferred over connection string type prefixes).


3. Bulk Importing & Exporting Settings (settings.json)

When managing many environment variables, export settings to JSON, edit them locally, and bulk import them.

Why: Allows versioning, backup, and batch application of app settings via JSON files.

# Export current settings to JSON
az webapp config appsettings list \
  -g container-learning \
  -n inference-api-test \
  --output json > settings.json

# Bulk import updated settings from JSON file
az webapp config appsettings set \
  -g container-learning \
  -n inference-api-test \
  --settings @settings.json

4. Slot Settings (Sticky Settings)

When using deployment slots (e.g., staging vs production), certain settings should stay with the slot rather than swap when promoting code.

Why: Keeps environment-specific URLs, database targets, or feature flags bound to a specific deployment slot during slot swaps.

az webapp config appsettings set \
  -g container-learning \
  -n inference-api-test \
  --slot staging \
  --slot-settings \
    ENVIRONMENT=staging \
    API_ENDPOINT=https://api-staging.example.com

5. Azure Key Vault References

For production secrets (API keys, database passwords), reference values stored in Azure Key Vault directly in your App Settings. App Service resolves the secret using a Managed Identity and passes the decrypted value as a standard environment variable to your container.

Why: Centralizes secret management, enables automated secret rotation, and eliminates plaintext passwords from configuration files.

az webapp config appsettings set \
  -g container-learning \
  -n inference-api-test \
  --settings \
    API_KEY="@Microsoft.KeyVault(SecretUri=https://myvault.vault.azure.net/secrets/api-key)"

On this page