Packaging & Deployment
The FastAPI service from PY-13 needs a home: Docker images, Azure pipelines, and secrets that never touch a config file. The final mile of Stage 8.
▶ Watch this reelWhat you'll learn
- Dockerizing Python
- CI/CD in Azure DevOps
- Azure deploy targets
- Key Vault & managed identity
Remember this
- Docker done right: multi-stage, slim pinned bases, locked deps, non-root, health-checked, scanned, labeled
- Pipelines gate quality, not just code: eval suites block promotion; App Service / Container Apps / Functions matched to workload shape
- Key Vault + managed identity: secrets fetched by platform vouching — never in code, config, or pipeline variables; rotation without deployment
Docker
- Multi-stage (no toolchain in runtime) · slim base PINNED by digest · locked deps (uv.lock --frozen) · non-root · HEALTHCHECK · scan + OCI labels.
Azure DevOps pipelines
- Build → EvalGate (golden set, faithfulness, agent regressions) → Scan (image CVEs, deps, secrets) → Deploy with env approvals.
- Fast PR gates + nightly full suites; everything as YAML in the repo.
Azure targets
- App Service: steady stateless APIs. Container Apps: queue/event-driven agents, scale-to-zero. Functions: event glue.
- Slots for blue-green + shadow eval before swap.
Key Vault & managed identity
- Secrets fetched via DefaultAzureCredential — no credential in code/config/pipeline.
- Rotation = Key Vault operation; access policies reviewable; audit of every read.
Code: The pipeline definition — the whole reel in YAML
# azure-pipelines.yml — build, gate, scan, deploy
trigger: [main]
stages:
- stage: Build
jobs:
- script: |
pip install uv && uv sync --frozen
uv run ruff check --fix . && uv run black --check .
uv run pytest tests/unit -q # PY-22 suites + Fakes
displayName: lint + unit tests
- script: docker build -t $(acr)/app:$(Build.SourceVersion) .
displayName: build image (SHA-tagged)
- stage: EvalGate # the AI difference
dependsOn: Build
jobs:
- script: uv run pytest tests/evals -q # golden set, faithfulness,
displayName: eval gates # agent regressions (AG-18)
- stage: Scan
dependsOn: EvalGate
jobs:
- script: trivy image --severity HIGH,CRITICAL --exit-code 1 $(acr)/app:$(Build.SourceVersion)
displayName: image CVE gate
- stage: DeployProd
dependsOn: Scan
condition: succeeded()
jobs:
- deployment: swap
environment: production # approval gate here
strategy: runOnce:
deploy:
steps:
- script: az webapp deployment slot swap -g $(rg) -n $(app) --slot staging --target-slot production