LAB 01 – Container image & Azure Container Registry¶
Story: CloudCart is a small online-shop backend. Your team is moving it from VMs to AKS. Step one: package the API as a secure container image and store it in a private registry.
| Duration | ~30 min |
| Creates | resource group, Azure Container Registry (Basic) |
| Tools | Azure CLI, (optional) Docker |
💡 Use Azure Cloud Shell (Bash) if you don't have the tools locally – it has
az,kubectl,helm,gitandenvsubstpre-installed.
Step 1 – Prepare the shell¶
git clone <this repository> aks-labs && cd aks-labs
az login # skip in Cloud Shell
az account set --subscription "<your subscription>"
source env.sh # prints RG, CLUSTER, ACR ... - run it in every new shell
Step 2 – Resource group and registry¶
az group create -n $RG -l $LOCATION --tags env=training owner=$PREFIX
az acr create -g $RG -n $ACR --sku Basic
az acr show -n $ACR --query loginServer -o tsv
✅ Checkpoint: the login server acrlab<…>.azurecr.io is printed.
Step 3 – Read the Dockerfile¶
Open app/Dockerfile and app/server.js. Note:
- multi-stage build – dependencies installed in a build stage, runtime stage stays small
- pinned base image
node:22-alpine(an LTS release) instead oflatest USER 1000:1000– the container doesn't run as root. Use a numeric UID: with a user name Kubernetes can't verifyrunAsNonRootand refuses to start the pod (CreateContainerConfigError)/healthzand/readyzendpoints – used by Kubernetes probes in LAB02
Step 4 – Build in Azure (no Docker needed)¶
ACR Tasks builds the image in Azure from your local folder:
Build a second version for later labs (rolling updates, canary):
(The code is the same – the version shown by the API comes from the APP_VERSION environment variable set in the Deployment. In real life every tag is a new build.)
✅ Checkpoint: tags 1.0 and 2.0.
Step 5 (optional) – The same with Docker¶
cd app
docker build -t cloudcart:local .
docker run --rm -d -p 8080:8080 --name cc cloudcart:local
curl -s localhost:8080 | head
docker exec cc id # uid=1000(node) - not root
docker stop cc
az acr login -n $ACR
docker tag cloudcart:local $ACR.azurecr.io/cloudcart:local
docker push $ACR.azurecr.io/cloudcart:local
cd ..
Step 6 – Inspect the image¶
az acr manifest list-metadata -r $ACR -n cloudcart -o table
az acr repository show -n $ACR --image cloudcart:1.0
Discuss: how big is the image? How would you scan it for vulnerabilities? (Microsoft Defender for Containers scans ACR images; Trivy in CI.)
Bonus¶
- Add an
org.opencontainers.image.sourcelabel to the Dockerfile and rebuild. az acr task create– rebuild automatically when the base imagenode:22-alpinegets a security update.
Troubleshooting¶
| Symptom | Likely cause |
|---|---|
The registry name … is not available |
ACR names are global – delete .lab-suffix, source env.sh again |
MissingSubscriptionRegistration |
az provider register -n Microsoft.ContainerRegistry |
unauthorized on docker push |
run az acr login -n $ACR first |
Files for this lab: Think-Cube/aks-labs/labs/LAB01-containers-acr