add initial azure container app deployment scaffolding#19
Conversation
There was a problem hiding this comment.
Pull request overview
Adds initial deployment scaffolding for running the app stack on Azure Container Apps, plus CI to build container images on PRs and branch pushes.
Changes:
- Introduces a GitHub Actions workflow to build the repo’s container images on
pull_requestandpushtomain/develop. - Adds an Azure Container Apps Bicep template for a single-replica multi-container app (nginx + agent + MongoDB + vector DB + Redis) plus environment resources.
- Adds a staging parameters file with environment names, registry settings, LLM/Langfuse settings, and rate-limit configuration.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 10 comments.
| File | Description |
|---|---|
infra/parameters/staging.parameters.json |
Staging parameter scaffold for the Container Apps deployment. |
infra/bicep/container-app.bicep |
Main IaC scaffold for managed environment, storage, secrets, and multi-container Container App. |
.github/workflows/build-containers.yml |
CI workflow to build the project’s Docker images on PRs and pushes. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| name: 'nginx' | ||
| image: nginxImage | ||
| resources: { | ||
| cpu: '0.5' |
There was a problem hiding this comment.
resources.cpu is provided as a quoted string (e.g. '0.5'). In the Container Apps ARM schema this field is numeric; passing a string can cause template validation/deployment failures. Use a number literal (e.g. 0.5) for CPU across all container resource blocks.
| cpu: '0.5' | |
| cpu: 0.5 |
There was a problem hiding this comment.
This is wrong - bicep breaks on non-integers if not casted to string.
| file: ${{ matrix.dockerfile }} | ||
| platforms: linux/amd64 | ||
| push: false | ||
| load: false |
There was a problem hiding this comment.
This job runs on pushes to main/develop, but docker/build-push-action is configured with push: false, so images are never published. That contradicts the PR description and will block any deployment flow that expects fresh images on branch pushes. Either enable pushing (and add registry login) or adjust the workflow/PR description to reflect build-only validation.
| platforms: linux/amd64 | ||
| push: false | ||
| load: false | ||
| tags: chatguru/${{ matrix.image_name }}:${{ github.sha }} |
There was a problem hiding this comment.
The image tag is set to chatguru/${{ matrix.image_name }}:${{ github.sha }} which won’t match the ACR-based image references in the Bicep template (e.g. ${acrServer}/chatguru-agent:${imageTag}) or the imageTag value in the staging parameters. Align the tagging/publishing scheme so the tag you deploy is actually built and pushed to the registry you reference.
| tags: chatguru/${{ matrix.image_name }}:${{ github.sha }} | |
| tags: ${{ matrix.image_name }}:${{ github.sha }} |
| - image_name: vector-db | ||
| dockerfile: docker/Dockerfile.db |
There was a problem hiding this comment.
The matrix includes building a vector-db image, but the new Container Apps Bicep template doesn’t deploy/use it (it deploys mongo-vector-db instead). If SQLite mode isn’t part of this deployment scaffold, removing vector-db from the matrix will reduce CI time; otherwise, consider adding it to the Bicep template so the built artifact is exercised.
| - image_name: vector-db | |
| dockerfile: docker/Dockerfile.db |
| @description('Trust forwarded headers from Front Door / proxy') | ||
| param rateLimitTrustProxy bool = true |
There was a problem hiding this comment.
rateLimitTrustProxy defaults to true, which makes the app trust X-Forwarded-For/X-Real-IP for client IP extraction. If this Container App is exposed directly to the internet (no trusted reverse proxy in front yet), clients can spoof these headers to evade or grief rate limiting. Consider defaulting this to false and only enabling it in env-specific parameters when a trusted proxy (e.g. Front Door) is actually in place.
| @description('Trust forwarded headers from Front Door / proxy') | |
| param rateLimitTrustProxy bool = true | |
| @description('Trust forwarded headers from a trusted reverse proxy such as Front Door; leave disabled for direct internet exposure') | |
| param rateLimitTrustProxy bool = false |
| resources: { | ||
| cpu: '1.0' | ||
| memory: '2Gi' | ||
| } |
There was a problem hiding this comment.
Unlike the nginx container, the chatguru-agent container has no readiness/liveness probe configured. Since the API exposes /health (and docker-compose already uses it for healthchecks), adding a probe here would prevent the revision from serving traffic while the agent is still starting up or unhealthy, reducing 502s during deployments/restarts.
| } | |
| } | |
| probes: [ | |
| { | |
| type: 'Readiness' | |
| httpGet: { | |
| path: '/health' | |
| port: 8000 | |
| } | |
| initialDelaySeconds: 10 | |
| periodSeconds: 10 | |
| } | |
| { | |
| type: 'Liveness' | |
| httpGet: { | |
| path: '/health' | |
| port: 8000 | |
| } | |
| initialDelaySeconds: 20 | |
| periodSeconds: 10 | |
| } | |
| ] |
| name: 'mongo-vector-db' | ||
| image: mongoVectorImage | ||
| resources: { | ||
| cpu: '0.5' | ||
| memory: '1Gi' |
There was a problem hiding this comment.
The mongo-vector-db container has no health probe configured, even though the service exposes /health. Adding a readiness/liveness probe would make dependency failures (e.g. MongoDB not ready yet) visible to the platform and improve rollout reliability.
| param imageTag string = 'latest' | ||
|
|
||
| var useManagedIdentityForAcr = !empty(acrPullIdentityResourceId) | ||
| var nginxImage = '${acrServer}/chatguru-nginx:${imageTag}' |
There was a problem hiding this comment.
nginxImage is set to ${acrServer}/chatguru-nginx:${imageTag}, but this repo doesn’t appear to build/publish a chatguru-nginx image (the workflow builds frontend, and docker/Dockerfile.frontend already produces an nginx runtime image). As-is, the Container App will fail to pull the referenced nginx image. Consider either switching the template to deploy the frontend image as the nginx container, or add/build/push a dedicated chatguru-nginx image consistently across the workflow + template.
| var nginxImage = '${acrServer}/chatguru-nginx:${imageTag}' | |
| var nginxImage = '${acrServer}/frontend:${imageTag}' |
| "value": "example.azurecr.io" | ||
| }, | ||
| "acrPullIdentityResourceId": { | ||
| "value": "" |
There was a problem hiding this comment.
acrPullIdentityResourceId is empty in this staging parameters file, but the template only supports ACR pulls via managed identity (no username/password registry credentials are configured). With acrServer pointing at an ACR, deployments using these parameters will fail to pull images. Set a real user-assigned identity resource ID here (or change the template to support registry credentials).
| "value": "" | |
| "value": "/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/rg-chatguru-staging/providers/Microsoft.ManagedIdentity/userAssignedIdentities/uami-chatguru-staging-acrpull" |
Co-authored-by: Copilot <[email protected]>
Summary
main/developIncluded In This Change
chatguru-agent,vector-db,mongo-vector-db, andfrontendFollow-Up Work
nginximage and configuration to serve built frontend assets and proxy backend/WebSocket traffic