# Shared Azure Container Registry Setup Guide for using a shared Azure Container Registry across multiple applications. ## 🎯 Why Share ACR? **Benefits:** - ✅ **Cost Savings**: One ACR for all applications (€5-20/month vs multiple ACRs) - ✅ **Centralized Management**: All images in one place - ✅ **Easier Collaboration**: Teams can share images - ✅ **Better Resource Utilization**: More efficient use of storage **How it works:** - ACR is shared, but each application uses a **unique repository name** - Repository name (`cmdb-insight`) separates your app from others - Images are organized by application: `acr.azurecr.io/app-name/service:tag` ## 📦 ACR Structure ``` zuyderlandacr.azurecr.io/ ├── cmdb-insight/ ← This application │ ├── backend:latest │ ├── backend:v1.0.0 │ ├── frontend:latest │ └── frontend:v1.0.0 ├── other-app/ ← Another application │ ├── api:latest │ └── web:latest └── shared-services/ ← Shared base images ├── nginx:latest └── node:20-alpine ``` ## 🔧 Setup Options ### Option 1: Use Existing ACR (Recommended) If you already have an ACR for other applications: ```bash # Set your existing ACR details ACR_NAME="your-existing-acr" ACR_RESOURCE_GROUP="rg-shared-services" # Or wherever your ACR is # Verify it exists az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP # Get login server ACR_LOGIN_SERVER=$(az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP --query loginServer --output tsv) echo "ACR Login Server: $ACR_LOGIN_SERVER" ``` **That's it!** Your images will be stored as: - `your-existing-acr.azurecr.io/cmdb-insight/backend:latest` - `your-existing-acr.azurecr.io/cmdb-insight/frontend:latest` ### Option 2: Create New Shared ACR If you don't have an ACR yet, create one that can be shared: ```bash # Set variables ACR_NAME="zuyderlandacr" # Recommended: company name + "acr" ACR_RESOURCE_GROUP="rg-shared-services" # Shared resource group LOCATION="westeurope" SKU="Standard" # Recommended for shared ACR # Create resource group for shared services az group create --name $ACR_RESOURCE_GROUP --location $LOCATION # Create ACR az acr create \ --resource-group $ACR_RESOURCE_GROUP \ --name $ACR_NAME \ --sku $SKU \ --admin-enabled true # Verify az acr show --name $ACR_NAME --resource-group $ACR_RESOURCE_GROUP ``` ## 🚀 Using Shared ACR ### Build and Push Images ```bash # Set ACR name export ACR_NAME="zuyderlandacr" export REPO_NAME="cmdb-insight" # This is your app identifier # Build and push (repository name separates your app) ./scripts/build-and-push-azure.sh # Images will be: # - zuyderlandacr.azurecr.io/cmdb-insight/backend:latest # - zuyderlandacr.azurecr.io/cmdb-insight/frontend:latest ``` ### Configure App Services ```bash # Backend App Service az webapp config container set \ --name cmdb-backend-prod \ --resource-group rg-cmdb-insight-prod \ --docker-custom-image-name "zuyderlandacr.azurecr.io/cmdb-insight/backend:latest" \ --docker-registry-server-url "https://zuyderlandacr.azurecr.io" # Frontend App Service az webapp config container set \ --name cmdb-frontend-prod \ --resource-group rg-cmdb-insight-prod \ --docker-custom-image-name "zuyderlandacr.azurecr.io/cmdb-insight/frontend:latest" \ --docker-registry-server-url "https://zuyderlandacr.azurecr.io" ``` ### Update Pipeline Variables In `azure-pipelines.yml`: ```yaml variables: acrName: 'yourcompanyacr' # Shared ACR name repositoryName: 'cmdb-insight' # Your app repository name # ... other variables ``` ## 🔐 Permissions ### Grant App Services Access to Shared ACR ```bash # Get App Service Managed Identity BACKEND_PRINCIPAL_ID=$(az webapp identity show \ --name cmdb-backend-prod \ --resource-group rg-cmdb-insight-prod \ --query principalId --output tsv) # Get ACR Resource ID (from shared resource group) ACR_ID=$(az acr show \ --name zuyderlandacr \ --resource-group rg-shared-services \ --query id --output tsv) # Grant AcrPull permission az role assignment create \ --assignee $BACKEND_PRINCIPAL_ID \ --role AcrPull \ --scope $ACR_ID ``` ## 📊 Managing Multiple Applications ### List All Repositories ```bash # See all applications in ACR az acr repository list --name zuyderlandacr # Output: # cmdb-insight # other-app # shared-services ``` ### List Images for This App ```bash # Backend images az acr repository show-tags \ --name zuyderlandacr \ --repository cmdb-insight/backend # Frontend images az acr repository show-tags \ --name zuyderlandacr \ --repository cmdb-insight/frontend ``` ### Clean Up Old Images ```bash # Delete old tags (keep last 10) az acr repository show-tags \ --name zuyderlandacr \ --repository cmdb-insight/backend \ --orderby time_desc \ --query '[10:].name' \ --output tsv | \ xargs -I {} az acr repository delete \ --name zuyderlandacr \ --image cmdb-insight/backend:{} \ --yes ``` ## 💰 Cost Optimization ### Shared ACR Costs | SKU | Storage | Cost | Best For | |-----|---------|------|----------| | Basic | 10GB | €5/month | Small teams, few apps | | Standard | 100GB | €20/month | **Recommended for shared ACR** | | Premium | 500GB | €50/month | Large organizations | **Recommendation**: Use **Standard** SKU for shared ACR: - Enough storage for multiple applications - Geo-replication available - Good balance of cost and features ### Cost Savings Example **Without sharing:** - App 1 ACR: €20/month - App 2 ACR: €20/month - App 3 ACR: €20/month - **Total: €60/month** **With shared ACR:** - Shared ACR (Standard): €20/month - **Total: €20/month** - **Savings: €40/month (67%)** ## 🎯 Best Practices ### 1. Naming Convention Use consistent repository naming: - `app-name/service:tag` (e.g., `cmdb-insight/backend:latest`) - Avoid generic names like `backend`, `frontend` - Include app identifier in repository name ### 2. Resource Group Organization **Option A: Separate Resource Groups** ``` rg-shared-services/ └── ACR (shared) rg-cmdb-insight-prod/ └── App-specific resources ``` **Option B: Single Resource Group** ``` rg-production/ ├── ACR ├── App 1 resources ├── App 2 resources └── App 3 resources ``` ### 3. Access Control - Use **Managed Identity** for App Services (recommended) - Grant **AcrPull** role (not AcrPush) to App Services - Use **Service Principals** for CI/CD pipelines - Consider **Azure RBAC** for fine-grained access ### 4. Image Tagging Strategy ```bash # Use semantic versioning cmdb-insight/backend:v1.0.0 cmdb-insight/backend:v1.0.1 cmdb-insight/backend:latest # Use build IDs for CI/CD cmdb-insight/backend:12345 cmdb-insight/backend:latest ``` ## 🔄 Migration from Dedicated ACR If you have a dedicated ACR and want to migrate to shared: ```bash # 1. Tag images with new repository name docker tag oldacr.azurecr.io/backend:latest newacr.azurecr.io/cmdb-insight/backend:latest docker tag oldacr.azurecr.io/frontend:latest newacr.azurecr.io/cmdb-insight/frontend:latest # 2. Push to shared ACR docker push newacr.azurecr.io/cmdb-insight/backend:latest docker push newacr.azurecr.io/cmdb-insight/frontend:latest # 3. Update App Services az webapp config container set \ --name cmdb-backend-prod \ --resource-group rg-cmdb-insight-prod \ --docker-custom-image-name "newacr.azurecr.io/cmdb-insight/backend:latest" # 4. Update pipeline variables # 5. Test deployment # 6. Delete old ACR (after verification) ``` ## 📚 Related Documentation - **`AZURE-NEW-SUBSCRIPTION-SETUP.md`** - Complete Azure setup guide - **`AZURE-CONTAINER-REGISTRY.md`** - ACR setup and usage - **`AZURE-PIPELINE-DEPLOYMENT.md`** - Automated deployment ## ✅ Checklist - [ ] Decide: Use existing ACR or create new shared ACR - [ ] Verify ACR exists or create new one - [ ] Update pipeline variables with ACR name - [ ] Grant App Services access to ACR - [ ] Build and push images with repository name `cmdb-insight` - [ ] Configure App Services to use shared ACR - [ ] Test deployment - [ ] Document ACR name for team --- **💡 Remember**: The repository name (`cmdb-insight`) is what separates your application from others in the shared ACR!