Skip to content

Read the app's port from its container in the web and function app call scripts - #127

Merged
paolosalvatori merged 5 commits into
mainfrom
fix/web-app-call-scripts-published-port
Oct 6, 2026
Merged

paolosalvatori merged 5 commits into
mainfrom
fix/web-app-call-scripts-published-port

Conversation

@paolosalvatori

@paolosalvatori paolosalvatori commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Motivation

With the port behavior of the emulator in localstack-pro#9262, a web app listens on the port its WEBSITES_PORT app setting names, which is 8000 in several samples. The call scripts reached the app in its container on a hard-coded port (80, or 8000 in some samples), so web-app-cosmosdb-mongodb-api/python, which sets 8000 but asked for 80, failed its host-port and container-IP calls, and every other call script only worked while its hard-coded port matched its deployment.

Testing every deployment method also showed that the call scripts picked the first app the CLI listed, and that web-app-sql-database served no HTTPS on port 8443 after a Bicep deployment or in Python, so the certificate check of its call-web-app.sh failed.

Fixes SMF-932

Changes

  • Port. The 16 call scripts of the web app and function app samples read the port the app's container publishes (get_docker_container_app_port) and use it for the host-port lookup and the container-IP call. The web app READMEs tell readers to read the published port with docker port.
  • Which app to call. The call scripts take the app name as their first argument, or from WEB_APP_NAME / FUNCTION_APP_NAME, and read the resource group from that app. Without a name they call the only app in the subscription, and stop with a message asking for the name when several are deployed.
  • Names. The deploy, call and validate scripts take PREFIX and SUFFIX from the environment, defaulting to local and test as before, so several deployments can share one emulator. The function-app-storage-http/dotnet Bicep deployment passes them to its template and names its resource group with the prefix.
  • SQL Database HTTPS. The Bicep deployments set CERT_NAME, grant the web app certificates/get, and deploy.sh creates the certificate in Key Vault before deploying the code (Bicep cannot create a Key Vault certificate). The Python app starts its HTTPS listener on 8443 from gunicorn.conf.py (when_ready), since App Service runs it with gunicorn and the if __name__ == '__main__' branch never runs there.
  • Workflow. The readiness loop and the retry step of run-samples.yml remove the stopped emulator container and wait for it to be gone before starting a new one. The retry used to fail with container named "localstack-main" already exists.

Tests

Every web app and function app sample with every deployment method, against the emulator image built from main after localstack-pro#9262 (localstack/localstack-azure:latest, 2026.10.0.dev43), each deployment with a random PREFIX and SUFFIX, followed by the sample's own call script against its own app (by name) and, for the last batches, by validate.sh:

Samples Methods Result
web-app-app-configuration, -cosmosdb-mongodb-api, -mysql-flexible-server, -postgresql-flexible-server (.NET and Python) scripts, Bicep, Terraform port 8000, all four call paths succeed
web-app-managed-identity (.NET and Python) user-assigned, system-assigned, Bicep, Terraform port 80, all four call paths succeed
web-app-cosmosdb-nosql-api (.NET and Python) scripts port 80, all four call paths succeed
web-app-sql-database (.NET and Python) scripts, Bicep, Terraform all four call paths, the HTTPS certificate check on 8443 and validate.sh succeed
web-app-custom-image (.NET and Python) scripts, Bicep, Terraform the app answers its call
function-app-service-bus, function-app-storage-http (.NET) scripts, Bicep, Terraform the triggers answer
api-management-function-app (Python) scripts, Bicep, Terraform call-api.sh and validate.sh succeed
function-app-front-door (Python) scripts call-front-door.sh and validate.sh succeed
function-app-managed-identity (Python) user-assigned, system-assigned, Bicep, Terraform test.sh and validate.sh succeed

The custom-image deployments and the Bicep and Terraform deployments of the two .NET function apps ran against the emulator built from the localstack-pro#9262 branch, the rest against the image above.

Notes

If a Terraform deployment fails with expected "object_id" to be a valid UUID, got any-app, the Azure CLI is reusing an access token minted by an older emulator version, which carried the app id as oid and never expired. Run az logout --username any-app and log in again: the current emulator issues the service principal's object id.

Related

🤖 Generated with Claude Code

https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm

…PREFIX and SUFFIX from the environment

The call scripts looked up the host port mapped to container port 80 and called the container IP on port 80 (or on a hard-coded 8000). The emulator serves an app on the port its WEBSITES_PORT app setting names, 8000 in several samples, so the host-port and container-IP calls of web-app-cosmosdb-mongodb-api/python failed, and every other script was one setting change away from the same failure. The scripts now read the port the app's container publishes, and the READMEs no longer tell readers to look for port 80.

The deploy, call and validate scripts take PREFIX and SUFFIX from the environment, defaulting to local and test as before, so several deployments of the same sample can run side by side on one emulator and a redeployment does not run into the soft-deleted Key Vault of the previous one. The function-app-storage-http Bicep deployment now passes them to its template and names its resource group with the prefix.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm
@paolosalvatori
paolosalvatori requested a review from a team as a code owner October 6, 2026 16:41
Copilot AI balanced review requested due to automatic review settings October 6, 2026 16:41

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Sixteen updated call scripts still select the first app globally, so concurrent PREFIX/SUFFIX deployments can be called incorrectly.

Review effort: Balanced
Findings: 16 Medium severity

Open (16)
What changed in this PR

Updates Azure web/function app samples to discover container ports dynamically and support environment-defined resource naming.

Changes:

  • Detects published application ports instead of assuming ports 80 or 8000.
  • Adds PREFIX/SUFFIX environment overrides across deployment and validation scripts.
  • Updates documentation and the storage-function Bicep deployment.
File Description
samples/​web-app-sql-database/​python/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-sql-database/​python/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-sql-database/​python/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-sql-database/​python/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-sql-database/​python/​README.md Updates port instructions.
samples/​web-app-sql-database/​python/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-sql-database/​dotnet/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-sql-database/​dotnet/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-sql-database/​dotnet/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-sql-database/​dotnet/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-sql-database/​dotnet/​README.md Updates port instructions.
samples/​web-app-sql-database/​dotnet/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-postgresql-flexible-server/​python/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-postgresql-flexible-server/​python/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-postgresql-flexible-server/​python/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-postgresql-flexible-server/​python/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-postgresql-flexible-server/​python/​README.md Updates port instructions.
samples/​web-app-postgresql-flexible-server/​python/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-postgresql-flexible-server/​dotnet/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-postgresql-flexible-server/​dotnet/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-postgresql-flexible-server/​dotnet/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-postgresql-flexible-server/​dotnet/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-postgresql-flexible-server/​dotnet/​README.md Updates port instructions.
samples/​web-app-postgresql-flexible-server/​dotnet/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-mysql-flexible-server/​python/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-mysql-flexible-server/​python/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-mysql-flexible-server/​python/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-mysql-flexible-server/​python/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-mysql-flexible-server/​python/​README.md Updates port instructions.
samples/​web-app-mysql-flexible-server/​python/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-mysql-flexible-server/​dotnet/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-mysql-flexible-server/​dotnet/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-mysql-flexible-server/​dotnet/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-mysql-flexible-server/​dotnet/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-mysql-flexible-server/​dotnet/​README.md Updates port instructions.
samples/​web-app-mysql-flexible-server/​dotnet/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-managed-identity/​python/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-managed-identity/​python/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-managed-identity/​python/​scripts/​user-assigned.sh Adds naming overrides.
samples/​web-app-managed-identity/​python/​scripts/​system-assigned.sh Adds naming overrides.
samples/​web-app-managed-identity/​python/​scripts/​cli.sh Adds naming overrides.
samples/​web-app-managed-identity/​python/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-managed-identity/​python/​scripts/​api.sh Adds naming overrides.
samples/​web-app-managed-identity/​python/​README.md Updates port instructions.
samples/​web-app-managed-identity/​python/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-managed-identity/​dotnet/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-managed-identity/​dotnet/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-managed-identity/​dotnet/​scripts/​user-assigned.sh Adds naming overrides.
samples/​web-app-managed-identity/​dotnet/​scripts/​system-assigned.sh Adds naming overrides.
samples/​web-app-managed-identity/​dotnet/​scripts/​cli.sh Adds naming overrides.
samples/​web-app-managed-identity/​dotnet/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-managed-identity/​dotnet/​scripts/​api.sh Adds naming overrides.
samples/​web-app-managed-identity/​dotnet/​README.md Updates port instructions.
samples/​web-app-managed-identity/​dotnet/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-custom-image/​python/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-custom-image/​python/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-custom-image/​python/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-custom-image/​python/​scripts/​call-web-app.sh Targets environment-selected resources.
samples/​web-app-custom-image/​python/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-custom-image/​dotnet/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-custom-image/​dotnet/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-custom-image/​dotnet/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-custom-image/​dotnet/​scripts/​call-web-app.sh Targets environment-selected resources.
samples/​web-app-custom-image/​dotnet/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-cosmosdb-nosql-api/​python/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-cosmosdb-nosql-api/​python/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-cosmosdb-nosql-api/​python/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-cosmosdb-nosql-api/​python/​README.md Updates port instructions.
samples/​web-app-cosmosdb-nosql-api/​dotnet/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-cosmosdb-nosql-api/​dotnet/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-cosmosdb-nosql-api/​dotnet/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-cosmosdb-nosql-api/​dotnet/​README.md Updates port instructions.
samples/​web-app-cosmosdb-mongodb-api/​python/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-cosmosdb-mongodb-api/​python/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-cosmosdb-mongodb-api/​python/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-cosmosdb-mongodb-api/​python/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-cosmosdb-mongodb-api/​python/​README.md Updates port instructions.
samples/​web-app-cosmosdb-mongodb-api/​python/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-cosmosdb-mongodb-api/​dotnet/​terraform/​deploy.sh Adds naming overrides.
samples/​web-app-cosmosdb-mongodb-api/​dotnet/​scripts/​validate.sh Adds naming overrides.
samples/​web-app-cosmosdb-mongodb-api/​dotnet/​scripts/​deploy.sh Adds naming overrides.
samples/​web-app-cosmosdb-mongodb-api/​dotnet/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-cosmosdb-mongodb-api/​dotnet/​README.md Updates port instructions.
samples/​web-app-cosmosdb-mongodb-api/​dotnet/​bicep/​deploy.sh Adds naming overrides.
samples/​web-app-app-configuration/​python/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-app-configuration/​python/​README.md Updates port instructions.
samples/​web-app-app-configuration/​dotnet/​scripts/​call-web-app.sh Discovers the container port.
samples/​web-app-app-configuration/​dotnet/​README.md Updates port instructions.
samples/​function-app-storage-http/​dotnet/​terraform/​deploy.sh Adds naming overrides.
samples/​function-app-storage-http/​dotnet/​scripts/​deploy.sh Adds naming overrides.
samples/​function-app-storage-http/​dotnet/​scripts/​call-http-triggers.sh Discovers the container port.
samples/​function-app-storage-http/​dotnet/​bicep/​deploy.sh Passes naming parameters to Bicep.
samples/​function-app-service-bus/​dotnet/​terraform/​deploy.sh Adds naming overrides.
samples/​function-app-service-bus/​dotnet/​scripts/​validate.sh Adds naming overrides.
samples/​function-app-service-bus/​dotnet/​scripts/​deploy.sh Adds naming overrides.
samples/​function-app-service-bus/​dotnet/​scripts/​call-http-trigger.sh Discovers the container port.
samples/​function-app-service-bus/​dotnet/​README.md Updates example output.
samples/​function-app-service-bus/​dotnet/​bicep/​deploy.sh Adds naming overrides.
samples/​function-app-managed-identity/​python/​terraform/​deploy.sh Adds naming overrides.
samples/​function-app-managed-identity/​python/​scripts/​validate.sh Adds naming overrides.
samples/​function-app-managed-identity/​python/​scripts/​user-managed-identity.sh Adds naming overrides.
samples/​function-app-managed-identity/​python/​scripts/​test.sh Adds naming overrides.
samples/​function-app-managed-identity/​python/​scripts/​system-managed-identity.sh Adds naming overrides.
samples/​function-app-managed-identity/​python/​bicep/​deploy.sh Adds naming overrides.
samples/​function-app-front-door/​python/​scripts/​validate.sh Adds naming overrides.
samples/​function-app-front-door/​python/​scripts/​deploy.sh Adds naming overrides.
samples/​function-app-front-door/​python/​scripts/​cleanup.sh Adds a prefix override.
samples/​function-app-front-door/​python/​scripts/​call-front-door.sh Targets environment-selected resources.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread samples/web-app-app-configuration/dotnet/scripts/call-web-app.sh
Comment thread samples/web-app-app-configuration/python/scripts/call-web-app.sh
Comment thread samples/web-app-cosmosdb-mongodb-api/dotnet/scripts/call-web-app.sh
Comment thread samples/web-app-sql-database/dotnet/scripts/call-web-app.sh
Comment thread samples/web-app-sql-database/python/scripts/call-web-app.sh
paolosalvatori and others added 2 commits October 6, 2026 19:09
…the first app listed

The call scripts looked up the first web app or function app the Azure CLI listed, so with several deployments on one emulator (which taking PREFIX and SUFFIX from the environment allows) they could read the port from and call another deployment's app. A call script now takes the app name as its first argument, or from WEB_APP_NAME or FUNCTION_APP_NAME, and reads the resource group from that app. Without a name it calls the only app in the subscription, and stops with a message asking for the name when there are several.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm
…e samples workflow

localstack stop does not wait for Docker to remove the container, so the start that followed failed with 'container named "localstack-main" already exists', and the retry of a failed sample never ran. The readiness loop and the retry step now remove the container and wait until it is gone before they start the emulator again.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm
paolosalvatori and others added 2 commits October 6, 2026 20:27
…oyment method

call-web-app.sh checks the certificate the web app serves on port 8443, and it failed in two cases.
The Bicep deployments set no CERT_NAME, created no certificate and gave the web app no certificate permission on the Key Vault, so the app never served HTTPS. main.bicep now sets CERT_NAME and grants certificates/get, and deploy.sh creates the certificate in the Key Vault after the deployment and before the code is deployed (Bicep cannot create a Key Vault certificate).
The Python app started its HTTPS listener only when run as `python app.py`, never under gunicorn, which is how App Service runs it. gunicorn.conf.py now starts that listener once in the gunicorn master when KEYVAULT_URI and CERT_NAME are set.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JPjRV37o1e5vjqHHqtMLQm

This branch was successfully deployed

1 active deployment
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants