A production-style cloud project that deploys a containerized FastAPI application to Azure using Terraform, Azure Container Apps, Managed Identity, Key Vault, Blob Storage, Run Pytest and GitHub Actions CI/CD.
This project demonstrates how to build, secure, and deploy a cloud-native application without hardcoding credentials.
It includes:
A FastAPI backend
Docker containerization
Infrastructure as Code (Terraform)
Secure secret management via Azure Key Vault
Managed Identity authentication (no secrets in code)
Azure Blob Storage integration
GitHub Actions CI/CD pipeline
Python / FastAPI
Docker
Terraform
Azure Container Apps
Azure Container Registry (ACR)
Azure Key Vault
Azure Blob Storage
Managed Identity (RBAC)
GitHub Actions (CI/CD)
Terraform provisions the Container App, its environment, and Log Analytics.
Key Vault, Storage, and ACR are created via the Azure CLI and referenced by the app - not yet managed by this Terraform.
RBAC role assignments are applied manually. (Next step: bring these under Terraform.)
- App-to-Azure auth (Key Vault, Blob) uses Managed Identity — no secrets in app code
- Secrets retrieved dynamically from Key Vault at runtime
- Storage access controlled via RBAC role assignments
- Write endpoint protected by an API key
Note: ACR image pull uses the ACR admin credential (a Terraform variable), and the API key is supplied as an environment variable — the two spots that aren't fully passwordless.
Protected endpoints require header: x-api-key: your-key
CI (tests): runs automatically on every push and pull request to main
Deploy (build → push to ACR → update Container App): manual trigger only, via workflow_dispatch in GitHub Actions — a stale Azure credential or transient failure can't turn every commit into a failed pipeline run
Trigger: git push to main
Basic tests included using pytest: pytest ./app Covers: root endpoint, health check, unauthorized access
State is stored remotely in Azure Blob Storage with state locking enabled.
The backend storage account must be created before running terraform init:
az group create --name rg-hello-aca-sg --location southeastasia
az storage account create \
--name tfstatektzmjackie \
--resource-group rg-hello-aca-sg \
--sku Standard_LRS \
--encryption-services blob
az storage container create \
--name tfstate \
--account-name tfstatektzmjackie- App retrieves storage account name from Key Vault
- Uses Managed Identity to authenticate
- Writes blob to container appdata
Container Apps configured with: min_replicas = 0 (Scales to zero when idle)
To avoid charges, delete: Container App, Container App Environment, Log Analytics Workspace
Keep only if needed: ACR, Key Vault, Storage Account
Managed Identity vs secrets-based auth
Terraform vs manual Azure drift issues
RBAC propagation delays
ACR authentication setup
ARM vs AMD64 Docker image issues
Key Vault naming constraints
cd app
pip install -r requirements.txt
uvicorn main:app --reload
docker buildx build --platform linux/amd64 \
-t <acr-name>.azurecr.io/p16-fastapi:<IMAGE> \
--push .
Application Demo
Secure secret retrieval from Azure Key Vault without hardcoded credentials
Successful write to Azure Blob Storage using Managed Identity authentication
Built as part of a hands-on DevOps/cloud engineering journey.