File size: 6,782 Bytes
3fbe97b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 | #!/bin/bash
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# deploy_azure.sh β One-shot Azure Container Apps deployment for Irminsul
#
# Prerequisites:
# - Azure CLI installed: https://learn.microsoft.com/en-us/cli/azure/install-azure-cli
# - Logged in: az login
# - Subscription active: az account show
#
# Usage:
# export PINECONE_API_KEY=your_key
# export GROQ_API_KEY=your_key
# chmod +x deploy_azure.sh
# ./deploy_azure.sh
#
# What this script does:
# 1. Creates a resource group in East US
# 2. Creates an Azure Container Registry (ACR)
# 3. Builds the Docker image via ACR Tasks (no local Docker build needed)
# 4. Creates a Container Apps environment
# 5. Deploys the container with secrets injected as env vars
# 6. Prints the live HTTPS URL
#
# Cost note:
# This stack (Groq backend, no GPU) runs on a consumption-plan Container App.
# Estimated cost: ~$0/month on free tier (180,000 vCPU-seconds/month free).
# GPU-accelerated inference (local Llama backend) requires NC-series instances
# (~$0.50-1.50/hr) which is not cost-effective for a portfolio project.
# See DEPLOYMENT.md for the full cost analysis.
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
set -e # exit on any error
# ββ Configuration ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
RESOURCE_GROUP="irminsul-rg"
LOCATION="eastus"
ACR_NAME="irminsulacr" # must be globally unique, lowercase alphanumeric
ENVIRONMENT="irminsul-env"
APP_NAME="irminsul"
IMAGE_TAG="latest"
# ββ Validate required secrets ββββββββββββββββββββββββββββββββββββββββββββββββββ
if [[ -z "$PINECONE_API_KEY" ]]; then
echo "ERROR: PINECONE_API_KEY environment variable is not set."
echo " export PINECONE_API_KEY=your_key"
exit 1
fi
if [[ -z "$GROQ_API_KEY" ]]; then
echo "ERROR: GROQ_API_KEY environment variable is not set."
echo " export GROQ_API_KEY=your_key"
exit 1
fi
echo "ββββββββββββββββββββββββββββββββββββββββββββββββββ"
echo " Irminsul β Azure Container Apps Deployment"
echo "ββββββββββββββββββββββββββββββββββββββββββββββββββ"
echo ""
# ββ Step 1: Resource Group βββββββββββββββββββββββββββββββββββββββββββββββββββββ
echo "[1/5] Creating resource group: $RESOURCE_GROUP"
az group create \
--name "$RESOURCE_GROUP" \
--location "$LOCATION" \
--output none
echo " β Resource group ready"
# ββ Step 2: Azure Container Registry ββββββββββββββββββββββββββββββββββββββββββ
echo "[2/5] Creating container registry: $ACR_NAME"
az acr create \
--resource-group "$RESOURCE_GROUP" \
--name "$ACR_NAME" \
--sku Basic \
--admin-enabled true \
--output none
echo " β ACR created"
# ββ Step 3: Build image via ACR Tasks (cloud build β no local Docker needed) βββ
echo "[3/5] Building Docker image via ACR Tasks..."
echo " This uploads your source code to Azure and builds in the cloud."
az acr build \
--registry "$ACR_NAME" \
--image "${APP_NAME}:${IMAGE_TAG}" \
.
echo " β Image built and pushed: ${ACR_NAME}.azurecr.io/${APP_NAME}:${IMAGE_TAG}"
# ββ Step 4: Container Apps Environment ββββββββββββββββββββββββββββββββββββββββ
echo "[4/5] Creating Container Apps environment: $ENVIRONMENT"
az containerapp env create \
--name "$ENVIRONMENT" \
--resource-group "$RESOURCE_GROUP" \
--location "$LOCATION" \
--output none
echo " β Environment ready"
# ββ Step 5: Deploy Container App ββββββββββββββββββββββββββββββββββββββββββββββ
echo "[5/5] Deploying container app: $APP_NAME"
# Get ACR credentials for pulling the image
ACR_LOGIN_SERVER=$(az acr show --name "$ACR_NAME" --query loginServer --output tsv)
ACR_USERNAME=$(az acr credential show --name "$ACR_NAME" --query username --output tsv)
ACR_PASSWORD=$(az acr credential show --name "$ACR_NAME" --query "passwords[0].value" --output tsv)
az containerapp create \
--name "$APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--environment "$ENVIRONMENT" \
--image "${ACR_LOGIN_SERVER}/${APP_NAME}:${IMAGE_TAG}" \
--registry-server "$ACR_LOGIN_SERVER" \
--registry-username "$ACR_USERNAME" \
--registry-password "$ACR_PASSWORD" \
--target-port 8000 \
--ingress external \
--min-replicas 0 \
--max-replicas 3 \
--cpu 1.0 \
--memory 2.0Gi \
--env-vars \
PINECONE_API_KEY=secretref:pinecone-key \
GROQ_API_KEY=secretref:groq-key \
PINECONE_INDEX=llmops-rag \
LLM_BACKEND=groq \
EMBED_MODEL=sentence-transformers/all-MiniLM-L6-v2 \
--secrets \
pinecone-key="$PINECONE_API_KEY" \
groq-key="$GROQ_API_KEY" \
--output none
echo " β Container app deployed"
# ββ Print live URL βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
LIVE_URL=$(az containerapp show \
--name "$APP_NAME" \
--resource-group "$RESOURCE_GROUP" \
--query "properties.configuration.ingress.fqdn" \
--output tsv)
echo ""
echo "ββββββββββββββββββββββββββββββββββββββββββββββββββ"
echo " Deployment complete!"
echo ""
echo " Live URL: https://${LIVE_URL}"
echo " Health: https://${LIVE_URL}/health"
echo " API docs: https://${LIVE_URL}/docs"
echo "ββββββββββββββββββββββββββββββββββββββββββββββββββ"
echo ""
echo " To tear down everything and stop billing:"
echo " az group delete --name $RESOURCE_GROUP --yes --no-wait"
echo ""
|