Python Appservice Deploy
MicrosoftOfficialCreated by Microsoft
- Skill
- Workflow
- Cloud and DevOps
- MIT
- Low risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
This skill provides a structured, idempotent workflow for deploying Python applications (Flask, Django, FastAPI) to Azure App Service on Linux. It handles the creation of necessary Azure resources—including Resource Groups, App Service Plans (P0v3), and Web Apps—while enforcing best practices like server-side builds and proper startup configuration. The process includes automated normalization of shell scripts to ensure compatibility and provides a reliable path for both standard CLI-based deployments and those utilizing Azure Developer CLI (azd) configurations.
What it does
- Automatically creates or validates Azure Resource Groups, App Service Plans, and Web Apps.
- Configures server-side builds via SCM_DO_BUILD_DURING_DEPLOYMENT.
- Normalizes Linux shell scripts to prevent line-ending issues during deployment.
- Sets appropriate startup commands for FastAPI applications.
- Packages the application code into a clean ZIP archive, excluding unnecessary files.
- Supports both standard Azure CLI and azd-based deployment workflows.
When to use it
- When you need to deploy a Python Flask, Django, or FastAPI application to Azure App Service Linux.
- When you want to automate the provisioning of the required Azure infrastructure alongside the code deployment.
- When you need a repeatable, error-checked deployment process for Python web apps.
- When you are working with a standard Python project structure and require a reliable deployment pipeline.
Advantages
- Reduces manual configuration by deriving sensible defaults for resource names and regions.
- Ensures cross-platform compatibility by normalizing line endings in scripts.
- Prevents common deployment failures through pre-packaging validation.
- Provides a consistent, idempotent approach to resource creation.
- Integrates seamlessly with existing Azure CLI and azd workflows.
Usage examples
- “Deploy my Flask app to Azure App Service.”
- The agent will prompt for an app name, then automatically create the necessary Resource Group, P0v3 Linux App Service Plan, and Web App, finally deploying the code.
- “Deploy my FastAPI project to Azure.”
- The agent will configure the Web App with the required uvicorn startup command and deploy the code to an Azure App Service Linux instance.
Install
Download the skill as a ZIP:
https://mp-staging.autogineer.com/agent-skills/microsoft/python-appservice-deploy/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip python-appservice-deploy.zip -d .agents/skills
Documentation by Microsoft
Python on Azure App Service — Code Deploy
Deploys Python (Flask, Django, FastAPI, generic) code to Azure App Service Linux (P0v3, Python 3.14). Creates RG + Plan + Web App if missing. Hand off to azure-prepare for VNet, Key Vault, databases, or IaC.
MCP tools used: mcp_azure_mcp_subscription_list, mcp_azure_mcp_group_list, mcp_azure_mcp_appservice, mcp_azure_mcp_azd (when azure.yaml is present).
Workflow
Prerequisite: Verify the latest stable Azure CLI; update with approval and recheck if needed.
Resolve context — smart defaults, minimal prompts. Only the app name is interactive; RG (
<app>-rg), Plan (<app>-plan), region (currentazdefault oreastus2), subscription are derived. create-app.md §1.Detect framework (advisory, never blocks). detect.md.
Choose path —
azure.yamlhost: appservice → deploy-azd.md; else deploy-azcli.md.Ensure RG → Plan (
P0v3 --is-linux) → Web App (--runtime "PYTHON:3.14") exist. Before creating a plan, invokeazure-quotasto check quota availability. On transient ARM errors, follow transient-retry.md. create-app.md.Set startup — Flask/Django: none (Oryx auto-detects). FastAPI: always
python -m uvicorn main:app --host 0.0.0.0. Other: warn. startup-commands.md.Set
SCM_DO_BUILD_DURING_DEPLOYMENT=true.Deploy —
azd deployoraz webapp deploy --type zip --track-status false --enriched-errors true.STOP. Print the post-deploy message (post-deploy-message.md) and end the turn.
Hard rules
LINUX SCRIPTS — normalize selected shell/startup files to LF, then verify no CR bytes remain. Stop on normalization, validation or packaging failure; deploy only a fresh package.
DJANGO REMOTE BUILDS — require
STATIC_ROOTand successful system/collectstaticchecks before packaging.⛔ NO POST-DEPLOY VERIFICATION — after deploy returns, do not run
az webapp log tail,curl,Invoke-WebRequest, or any health probe. App Service needs 2–3 min to warm; a quiet log or early 5xx is not failure.⛔ SHELL SAFETY — for
--runtimealways use"PYTHON:3.14"(colon). Never"PYTHON|3.14"(pipe is a shell operator).⛔ NEVER
az webapp up— deprecated. Use Step 7 commands.✅ URL FORMAT — present endpoints as
https://...URLs.
Error Handling
See errors.md for the full symptom → cause → fix matrix. Quick triage: missing plan/app → re-run Step 4; container ping timeout on 8000 → fix startup (Step 5); ModuleNotFoundError after deploy → ensure Step 6 ran, redeploy.
Files
- ATTRIBUTION.mdAdded by AutoGineer1004 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md3.2 KiB
- references/create-app.md6.2 KiB
- references/deploy-azcli.md6.8 KiB
- references/deploy-azd.md3.4 KiB
- references/detect.md3.6 KiB
- references/errors.md3.8 KiB
- references/post-deploy-message.md4.4 KiB
- references/startup-commands.md4.3 KiB
- references/transient-retry.md2.3 KiB
- scripts/generate-app-name.ps1Script1.7 KiB
- scripts/generate-app-name.shScript1.8 KiB
- scripts/retry-az-create.ps1Script2.1 KiB
- scripts/retry-az-create.shScript1.9 KiB
references/startup-commands.md
Startup Commands by Framework
Linux App Service (Oryx) auto-detects Flask and Django — no startup command is needed for these. FastAPI does NOT rely on Oryx auto-detection in this skill: we always set an explicit uvicorn startup command so the behavior is identical on every supported Python runtime (3.12, 3.13, 3.14, …). This skill also sets a startup command (or emits a manual hint) for non-Flask/Django/FastAPI frameworks.
Flask — no startup command needed
Azure App Service (Oryx) auto-detects Flask and starts it correctly. Do not run az webapp config set --startup-file for Flask apps.
Django — no startup command needed
Azure App Service (Oryx) auto-detects Django by finding wsgi.py and starts gunicorn against <project>.wsgi:application automatically. Do not run az webapp config set --startup-file for Django apps.
Make sure the project has:
requirements.txtcontainingdjango(and ideallygunicorn; Oryx provides one if missing)<project>/wsgi.pyat a path Oryx can discover (the default Django layout works out of the box)ALLOWED_HOSTSincludes<app>.azurewebsites.net(or*for first-deploy validation — tighten later)
FastAPI — always set the uvicorn startup command
The skill sets the startup command unconditionally for FastAPI, regardless of the Python runtime version. Oryx FastAPI auto-detection is not relied on — an explicit startup command always works and avoids version-dependent surprises:
az webapp config set -n <app> -g <rg> \
--startup-file "python -m uvicorn main:app --host 0.0.0.0"az webapp config set -n <app> -g <rg> `
--startup-file "python -m uvicorn main:app --host 0.0.0.0"Replace main:app with the discovered entry point if different (e.g., app.main:app, src.api:app). The --host 0.0.0.0 flag is mandatory — uvicorn defaults to 127.0.0.1, which causes App Service container-ping timeouts.
Make sure requirements.txt contains both fastapi and uvicorn (or uvicorn[standard]).
Not auto-configured — warn & deploy anyway
When the detected framework is wsgi-generic, asgi-generic, or unknown, deploy the code without setting a startup command and surface this message to the user:
⚠️ This skill auto-configures Flask, Django, and FastAPI only. The app has been deployed, but App Service may not start it until you set a startup command. Choose the matching example below and run it:
Generic WSGI
az webapp config set -n <app> -g <rg> \
--startup-file "gunicorn --bind=0.0.0.0 --timeout 600 <module>:<callable>"az webapp config set -n <app> -g <rg> `
--startup-file "gunicorn --bind=0.0.0.0 --timeout 600 <module>:<callable>"Generic ASGI
az webapp config set -n <app> -g <rg> \
--startup-file "python -m uvicorn <module>:<callable> --host 0.0.0.0 --port 8000"az webapp config set -n <app> -g <rg> `
--startup-file "python -m uvicorn <module>:<callable> --host 0.0.0.0 --port 8000"Django override (only if auto-detection fails)
Oryx auto-detection covers the standard Django layout. Set this manually only if the project uses a non-standard layout and the auto-detected startup doesn't find your WSGI app:
az webapp config set -n <app> -g <rg> \
--startup-file "gunicorn --bind=0.0.0.0 --timeout 600 <project>.wsgi"az webapp config set -n <app> -g <rg> `
--startup-file "gunicorn --bind=0.0.0.0 --timeout 600 <project>.wsgi"Diagnosing a wrong startup command
# Current value
az webapp config show -n <app> -g <rg> --query linuxFxVersion -o tsv
az webapp config show -n <app> -g <rg> --query appCommandLine -o tsv
# Live logs
az webapp log tail -n <app> -g <rg>Look for:
Container <app>_<...> didn't respond to HTTP pings on port: 8000→ app didn't bind to 0.0.0.0 (or 0.0.0.0:8000)ModuleNotFoundError→ wrong<module>:<callable>in startup command, or build didn't install depsgunicorn: command not found/uvicorn: command not found→ addgunicorn/uvicorntorequirements.txt
Why --host 0.0.0.0 matters
App Service forwards traffic to the container on the port the runtime listens on (8000 by default). The startup command must bind to 0.0.0.0 so the platform's ping reaches it — binding to 127.0.0.1 causes ping timeouts.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Needs: Needs Python
Security
What our scanner noticed· Low risk
- Instructions that use the network
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills · .github/plugins/azure-skills/skills/python-appservice-deploy · commit 0696600
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from .github/plugins/azure-skills/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- microsoft/azure-skills
AutoGineer is not affiliated with or endorsed by Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download python-appservice-deploy.zip