Overview

This guide walks you through deploying CaseBender on Azure using pre-built Docker images with Azure Container Apps and managed services.

Prerequisites

  1. Azure Account
  2. Azure CLI installed
  3. Docker installed

Step 1: Initial Setup

Install and Configure Azure CLI

# Using Homebrew
brew install azure-cli

# Login to Azure

az login

# Configure Docker for ACR

az acr login --name casebenderacr

Initialize Project

# Set variables
RESOURCE_GROUP="casebender-rg"
LOCATION="eastus"

# Create resource group
az group create --name $RESOURCE_GROUP --location $LOCATION

# Enable required services
az provider register --namespace Microsoft.ContainerRegistry
az provider register --namespace Microsoft.App
az provider register --namespace Microsoft.Storage

Step 2: Set Up Azure Infrastructure

Create Storage Account

# Create storage account
az storage account create \
  --name casebenderstorage \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION \
  --sku Standard_LRS \
  --encryption-services blob

# Create blob container
az storage container create \
  --name casebender \
  --account-name casebenderstorage \
  --auth-mode key \
  --public-access off

# Get storage account key
STORAGE_KEY=$(az storage account keys list \
  --account-name casebenderstorage \
  --resource-group $RESOURCE_GROUP \
  --query '[0].value' -o tsv)

# Create managed identity for storage access
az identity create \
  --name casebender-storage-identity \
  --resource-group $RESOURCE_GROUP

# Get managed identity ID
IDENTITY_ID=$(az identity show \
  --name casebender-storage-identity \
  --resource-group $RESOURCE_GROUP \
  --query id -o tsv)

# Assign Storage Blob Data Contributor role
az role assignment create \
  --assignee-object-id $(az identity show --name casebender-storage-identity --resource-group $RESOURCE_GROUP --query principalId -o tsv) \
  --role "Storage Blob Data Contributor" \
  --scope $(az storage account show --name casebenderstorage --resource-group $RESOURCE_GROUP --query id -o tsv)

Set Up Azure Database for PostgreSQL

# Create PostgreSQL server
az postgres flexible-server create \
  --resource-group $RESOURCE_GROUP \
  --name casebender-db \
  --admin-user superadmin \
  --admin-password <your-secure-password> \
  --sku-name Standard_B2s \
  --storage-size 32 \
  --version 14

# Create database
az postgres flexible-server db create \
  --resource-group $RESOURCE_GROUP \
  --server-name casebender-db \
  --database-name casebender

Set Up Azure Cache for Redis

# Create Redis cache
az redis create \
  --resource-group $RESOURCE_GROUP \
  --name casebender-redis \
  --sku Basic \
  --vm-size c0 \
  --location $LOCATION

Step 3: Create and Configure Container Registry

# Create Azure Container Registry
az acr create \
  --resource-group $RESOURCE_GROUP \
  --name casebenderacr \
  --sku Standard \
  --admin-enabled true

# Get registry credentials
ACR_USERNAME=$(az acr credential show --name casebenderacr --query username -o tsv)
ACR_PASSWORD=$(az acr credential show --name casebenderacr --query "passwords[0].value" -o tsv)

# Pull CaseBender images
docker pull casebender/casebender:latest
docker pull casebender/workflow-processor:latest
docker pull casebender/misp-processor:latest

# Tag images for ACR
docker tag casebender/casebender:latest casebenderacr.azurecr.io/casebender/app:latest
docker tag casebender/workflow-processor:latest casebenderacr.azurecr.io/casebender/workflow-processor:latest
docker tag casebender/misp-processor:latest casebenderacr.azurecr.io/casebender/misp-processor:latest

# Push images to ACR
docker push casebenderacr.azurecr.io/casebender/app:latest
docker push casebenderacr.azurecr.io/casebender/workflow-processor:latest
docker push casebenderacr.azurecr.io/casebender/misp-processor:latest

Step 4: Deploy Services

Create Container Apps Environment

# Create Container Apps environment
az containerapp env create \
  --name casebender-env \
  --resource-group $RESOURCE_GROUP \
  --location $LOCATION

# Create main application
az containerapp create \
  --name casebender-app \
  --resource-group $RESOURCE_GROUP \
  --environment casebender-env \
  --image casebenderacr.azurecr.io/casebender/app:latest \
  --target-port 3000 \
  --ingress external \
  --registry-server casebenderacr.azurecr.io \
  --registry-username $ACR_USERNAME \
  --registry-password $ACR_PASSWORD \
  --user-assigned-identity $IDENTITY_ID \
  --env-vars \
    AUTH_SECRET=<your-auth-secret> \
    AUTH_SALT=<your-auth-salt> \
    POSTGRES_PRISMA_URL="postgresql://superadmin:<password>@casebender-db.postgres.database.azure.com:5432/casebender" \
    REDIS_URL="redis://casebender-redis.redis.cache.windows.net:6380?ssl=true&password=<redis-key>" \
    AZURE_STORAGE_ACCOUNT="casebenderstorage" \
    AZURE_STORAGE_CONTAINER="casebender" \
    AZURE_STORAGE_CONNECTION_STRING="DefaultEndpointsProtocol=https;AccountName=casebenderstorage;AccountKey=${STORAGE_KEY};EndpointSuffix=core.windows.net"

# Create workflow processor
az containerapp create \
  --name workflow-processor \
  --resource-group $RESOURCE_GROUP \
  --environment casebender-env \
  --image casebenderacr.azurecr.io/casebender/workflow-processor:latest \
  --registry-server casebenderacr.azurecr.io \
  --registry-username $ACR_USERNAME \
  --registry-password $ACR_PASSWORD \
  --min-replicas 1 \
  --max-replicas 1 \
  --env-vars \
    POSTGRES_PRISMA_URL="postgresql://superadmin:<password>@casebender-db.postgres.database.azure.com:5432/casebender" \
    REDIS_URL="redis://casebender-redis.redis.cache.windows.net:6380?ssl=true&password=<redis-key>"

# Create MISP processor
az containerapp create \
  --name misp-processor \
  --resource-group $RESOURCE_GROUP \
  --environment casebender-env \
  --image casebenderacr.azurecr.io/casebender/misp-processor:latest \
  --registry-server casebenderacr.azurecr.io \
  --registry-username $ACR_USERNAME \
  --registry-password $ACR_PASSWORD \
  --min-replicas 1 \
  --max-replicas 1 \
  --env-vars \
    POSTGRES_PRISMA_URL="postgresql://superadmin:<password>@casebender-db.postgres.database.azure.com:5432/casebender" \
    REDIS_URL="redis://casebender-redis.redis.cache.windows.net:6380?ssl=true&password=<redis-key>"

Step 5: Set Up Azure Front Door

# Create Front Door profile
az afd profile create \
  --profile-name casebender-afd \
  --resource-group $RESOURCE_GROUP \
  --sku Standard_AzureFrontDoor

# Create endpoint
az afd endpoint create \
  --endpoint-name casebender \
  --profile-name casebender-afd \
  --resource-group $RESOURCE_GROUP

# Create origin group
az afd origin-group create \
  --origin-group-name casebender-origin-group \
  --profile-name casebender-afd \
  --resource-group $RESOURCE_GROUP \
  --probe-path "/" \
  --probe-protocol Http \
  --probe-request-type GET

# Add origin
az afd origin create \
  --origin-group-name casebender-origin-group \
  --origin-name casebender-origin \
  --profile-name casebender-afd \
  --resource-group $RESOURCE_GROUP \
  --host-name <your-container-app-url> \
  --origin-host-header <your-container-app-url> \
  --priority 1 \
  --weight 1000 \
  --enabled-state Enabled

Step 6: Configure Custom Domain (Optional)

# Add custom domain to Front Door
az afd custom-domain create \
  --custom-domain-name casebender-domain \
  --host-name your-domain.com \
  --profile-name casebender-afd \
  --resource-group $RESOURCE_GROUP \
  --minimum-tls-version TLS12

# Enable HTTPS
az afd custom-domain enable-https \
  --custom-domain-name casebender-domain \
  --profile-name casebender-afd \
  --resource-group $RESOURCE_GROUP

Monitoring and Maintenance

Set Up Application Insights

# Create Application Insights
az monitor app-insights component create \
  --app casebender-insights \
  --location $LOCATION \
  --resource-group $RESOURCE_GROUP \
  --application-type web

# Get instrumentation key
az monitor app-insights component show \
  --app casebender-insights \
  --resource-group $RESOURCE_GROUP \
  --query instrumentationKey \
  --output tsv

Configure Alerts

# Create action group
az monitor action-group create \
  --name casebender-alerts \
  --resource-group $RESOURCE_GROUP \
  --action email admin email@yourdomain.com

# Create alert rule
az monitor metrics alert create \
  --name "high-cpu-usage" \
  --resource-group $RESOURCE_GROUP \
  --scopes <container-app-resource-id> \
  --condition "avg CPU > 80" \
  --window-size 5m \
  --evaluation-frequency 1m \
  --action <action-group-id>

View Logs

# View container app logs
az containerapp logs show \
  --name casebender-app \
  --resource-group $RESOURCE_GROUP \
  --follow

Scaling Configuration

# Configure scaling rules
az containerapp update \
  --name casebender-app \
  --resource-group $RESOURCE_GROUP \
  --min-replicas 1 \
  --max-replicas 10 \
  --scale-rule-name http-rule \
  --scale-rule-type http \
  --scale-rule-http-concurrency 50

Backup and Disaster Recovery

Configure Database Backups

# Enable automated backups
az postgres flexible-server update \
  --resource-group $RESOURCE_GROUP \
  --name casebender-db \
  --backup-retention 7

Configure Geo-Replication

# Create secondary region resources
az postgres flexible-server replica create \
  --name casebender-db-secondary \
  --source-server casebender-db \
  --resource-group $RESOURCE_GROUP \
  --location westus

Security Best Practices

  1. Enable Azure Defender for all services
  2. Implement Azure Private Link
  3. Use Managed Identities
  4. Regular security assessments
  5. Enable diagnostic logging

Cost Optimization

  1. Use consumption plan for Container Apps
  2. Implement auto-scaling rules
  3. Choose appropriate service tiers
  4. Monitor usage patterns
  5. Use Azure Reserved Instances

Next Steps

  • Set up CI/CD with Azure DevOps
  • Implement comprehensive monitoring
  • Configure disaster recovery
  • Review security compliance