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 ""