ICCC - Azure Container Registry

09 April 2019 - Azure, Container, Docker, CLI, Registry

Introduction

Today, I do a talk about Azure Container Registry at the Intelligent Cloud Conference in Copenhagen. In this post you find my material (scripts) and a recording of my session.

Recording

Prerequisites

In order to follow along, you need the following prerequisites:

  1. Linux environment with
  2. Azure Subscription in which you are administrator (get one for free)

I recommend using Visual Studio Code and its Azure CLI Plugin to work with the script mentioned in this lab.

Script

Preparation

# Some variables that we are going to need
SUBSCRIPTION="Microsoft Azure Sponsorship"
WHTARGET="https://webhook.site/..."
LOCATION="westeurope"
LOCATION2="northeurope"
RG="icc19"
REG="icc19reg"
KV="icc19vault"
SP="icc19sp"
EVENT_SITE="icc19web"
APP_ENDPOINT="https://icc19web.azurewebsites.net/api/updates"
GHUSR="rstropek"
# GHPAT="your-github-personal-access-token"
GHREPO="https://github.com/rstropek/acr-image-refresh-demo"
TASK="icc19task"

# Log in and select correct account
az login
az account set --subscription "$SUBSCRIPTION"

# Create resource groups if it does not exist yet
if [ $(az group exists --name "$RG") == 'false' ]
then
    az group create --name "$RG" --location "$LOCATION"
fi

# Create Keyvault to store service principal's password
if ! az keyvault show --resource-group "$RG" --name "$KV"
then
    az keyvault create --resource-group "$RG" --name "$KV"
    # To delete: az keyvault delete --resource-group "$RG" --name "$KV"
fi

Create Registry

# Create Azure Container Registry if it does not exist yet
if [ $(az acr check-name --name "$REG" --query nameAvailable) == 'true' ]
then
    # Use premium to enable geo-replication
    az acr create --resource-group "$RG" --name "$REG" --location $LOCATION \
        --sku "premium" --admin-enabled

    # Replication ACR to second data center
    az acr replication create --resource-group "$RG" --registry "$REG" \
        --location $LOCATION2

    # NOTE that ACR in Azure VNets is currently in preview, we will
    #      not go into that in this demo. For details see
    #      https://docs.microsoft.com/de-de/azure/container-registry/container-registry-vnet
fi
# Get ID of ACR
ACRID=$(az acr show --name "$REG" --resource-group "$RG" --query "id" -o tsv)

Auth

# You could use the following command to get the password of the admin account:
az acr credential show --name "$REG" --query "passwords[0].value"
# Prefer service principals (as shown below) for production scenarios

# Log in with individual account of developer (for e.g. pushing containers using docker cli)
az acr login --name "$REG"

# Create a service principal if it does not exist yet
if [ $(az ad sp list --display-name "$SP" | jq length) == '0' ]
then
    # Put service principal's password in Azure KeyVault
    az keyvault secret set --vault-name $KV --name $REG-PWD \
        --value $(az ad sp create-for-rbac --name "$SP" --query password -o tsv)

    # You could use the following command to delete the service principal:
    # az ad sp delete --id "$SPAPPID"
fi
# Get ID of service principal
SPAPPID=$(az ad sp list --display-name "$SP" --query "[].appId" -o tsv)

# Assign service principal the Contributor role so it can push images
if [ $(az role assignment list --assignee "$SPAPPID" --role Contributor --scope "$ACRID" | jq length) == '0' ]
then
    az role assignment create --assignee "$SPAPPID" --role Contributor --scope "$ACRID"
fi

Push and Build Images

# Use usual docker login with service principal to authenticate at ACR with Docker CLI
docker login -u $SPAPPID \
    -p $(az keyvault secret show --vault-name $KV --name $REG-PWD --query value -o tsv) \
    $REG.azurecr.io

# Push an image to ACR with Docker CLI
docker tag nginx:alpine $REG.azurecr.io/tiny-web:latest
docker push $REG.azurecr.io/tiny-web:latest

# Use ACR quick task to build an image in the cloud
az acr build --registry "$REG" --image website:v2 .

# Inspect storage limits
az acr show-usage --resource-group "$RG" --name "$REG" --output table

# You could use the following statement to delete the image from ACR:
# az acr repository delete --name "$REG" --image $IMG:v1

# Get a list of repositories and tags in the registry
az acr repository list --name $REG
az acr repository show-tags --repository website --name $REG

Integration Scenarios

# Create a webhook so we get notified about container pushes
if ! az acr webhook show --registry "$REG" --name "webhook1$REG"
then
    az acr webhook create --registry "$REG" --name "webhook1$REG" --actions push --uri $WHTARGET

    # After creating the webhook, trigger a push or build to ACR and see how the webhook is triggered
fi

# Demo demo website that displays events happening in EventGrid
if output=$(az appservice plan show --resource-group "$RG" --name "$EVENT_SITE-plan") && [ -z "$output" ]
then
    az group deployment create --resource-group "$RG" \
        --template-uri "https://raw.githubusercontent.com/Azure-Samples/azure-event-grid-viewer/master/azuredeploy.json" \
        --parameters siteName=$EVENT_SITE hostingPlanName=$EVENT_SITE-plan
fi

# Register EventGrid provider if not already registered
if [ $(az provider show --namespace Microsoft.EventGrid --query "registrationState" --output tsv) != "Registered" ]
then
    az provider register --namespace Microsoft.EventGrid
fi

# Add EventGrid subscription if not already exists
if ! az eventgrid event-subscription show --name event-sub-acr --source-resource-id $ACRID
then
    az eventgrid event-subscription create --name event-sub-acr --source-resource-id $ACRID --endpoint $APP_ENDPOINT
    # az eventgrid event-subscription delete --name event-sub-acr --resource-id $ACRID
fi

# After creating the subscription, trigger a push or build to ACR and see how the EventGrid message is sent

Tasks

# Create a task that listens to change in GitHub and rebuilds images if necessary
if ! az acr task show --registry "$REG" --name "$TASK"
then
    az acr task create --registry "$REG" --name "$TASK" --image $TASK:latest \
        --context $GHREPO --branch master --file Dockerfile --git-access-token $GHPAT
    # az acr task delete --registry "$REG" --name "$TASK"
fi

# Use the following command to manually trigger the task
az acr task run --registry "$REG" --name "$TASK"

# Use the following command to see a list of task runs
az acr task list-runs --registry "$REG" --output table