Week 5 - Containers & CI/CD

Intro: Containers and CI/CD

Dependency Management

Docker Fundamentals

Azure Container Registry

Python CI Pipeline

Practice

Assignment: Containerize and Ship

Gotchas & Pitfalls

Slides (PDF)

Career relevance: Week 5

Glossary: Week 5

Going Further

History of Containers and CI/CD

Azure Container Registry

You can build and run images locally, but to deploy them you need a registry. Azure Container Registry (ACR) is a private registry where your team stores and versions container images.

By the end of this chapter, you should be able to log in to a shared ACR instance, tag and push an image, and verify it in the Azure portal.

Concepts

The Azure CLI

This is the first chapter where you use the Azure CLI (az), a command-line tool for managing Azure resources. You installed it in Week 1 as part of your Azure setup.

<aside> 📘 Core program connection: In the Core program Systems week you learned about cloud computing and container registries. Here you apply the same concepts with Azure. Review: Core Program - Cloud Computing

</aside>

The az CLI follows the same command-line patterns you learned in the Core program: flags, subcommands, and stdin/stdout. If the CLI feels unfamiliar, the Core program's CLI chapter is a useful refresher.

<aside> 📘 Core program connection: The Azure CLI is just another command-line tool. The Core program covered CLI fundamentals in Week 1 of the Core program, including how commands, flags, and output work. Review: Core Program - Intro to the CLI

</aside>

Sign in with the HackYourFuture account your teacher gave you. Always pass the HYF tenant ID so you land in the right Microsoft Entra tenant (organization) even if your az CLI already has a personal account configured:

az login --use-device-code --tenant 07a14c4e-d88c-42f7-83b3-13af7e57ff3d

After login, confirm you landed on the HYF subscription:

az account show --query name -o tsv
# expect: Nonprofit grant

If you see a different name, switch to the HYF subscription before continuing:

az account set --subscription "Nonprofit grant"

Your teacher added your account to the HYF-Students Entra group during onboarding. That group has the AcrPush role on hyfregistry, which gives you both push and pull access. You do not need to set anything up yourself.

<aside> 💡 You will use az commands more extensively in Week 6. For now, you only need az login, az acr login, and one az acr verification step.

</aside>

You are not expected to know Azure yet: this chapter asks for exactly one cloud action, pushing an image you already built, and Week 6 is where you learn the broader az toolkit and deploy that image, one new piece at a time.

What a registry does

A registry stores container images so they can be pulled from other machines, CI runners, or cloud services. Without a registry, the only way to get an image onto another machine is to build it there from source, which defeats the reproducibility goal.

Docker Hub is the default public registry: anyone can pull public images. ACR is a private registry tied to your Azure subscription: only authenticated identities can push or pull. That is why your CI runner needs credentials before it can push an image, and why your Azure services need credentials before they can pull one. Your laptop, the CI runner, and the production cloud service all authenticate to the same ACR instance and work from the same image.

The full image name combines all three: hyfregistry.azurecr.io/weather-pipeline:1.0

Your shared registry

Your teacher has created a shared ACR instance for the class. You will receive the registry name (e.g. hyfregistry). Open the Azure portal and find it under "Container registries" to confirm you have access.

Log in and push an image

Before you can push, authenticate Docker with the shared registry:

# Log in (uses your Azure credentials)
az acr login --name hyfregistry

# Quick sanity check: list the repositories already in the registry.
# A list (even empty) means your token works. A 401 means auth failed.
az acr repository list --name hyfregistry -o tsv

This assumes you still have the weather-pipeline:1.0 image you built in Docker Fundamentals. Run docker images to confirm it exists (and to find the exact name:tag you built); if docker tag later fails with "No such image", rebuild it with docker build -t weather-pipeline:1.0 . from your pipeline folder first.

<aside> ⚠️ The registry is shared with your whole cohort. Everyone uses the same hyfregistry instance, so if two students push weather-pipeline:1.0, the second push silently overwrites the first one's tag (ACR does not error). Prefix the image name with your GitHub handle, for example alice-weather-pipeline, so each student gets their own repository in the registry and the portal listing stays readable. Replace <your-handle> below with the lowercase form of your handle (Docker image names must be lowercase: Alice becomes alice).

</aside>

Tag your local image with the registry prefix and push:

# Tag for ACR (replace <your-handle> with your GitHub username)
docker tag weather-pipeline:1.0 hyfregistry.azurecr.io/<your-handle>-weather-pipeline:1.0

# Push to ACR
docker push hyfregistry.azurecr.io/<your-handle>-weather-pipeline:1.0

<aside> 💡 If docker push returns unauthorized: authentication required, the most likely cause is that your account is not in the HYF-Students Entra group. Ask your teacher to add you (they need your Azure email or object ID). A stale az acr login token is the second most likely cause: re-run az acr login --name hyfregistry and try again.

</aside>

A successful push streams each image layer to the registry and prints the final image digest.

<aside> ⌨️ Hands on: Push your Docker Fundamentals image to the shared registry. Then go to the Azure portal, open the registry, and find your image under "Repositories."

</aside>

Seeing your image in the portal confirms the push worked. This is the same image that CI will push automatically in the next chapter. In a proper CI pipeline, the push step only runs after linting and testing pass, so the image in the registry always reflects code that has been verified.

<aside> 📘 Core program connection: In Week 2 of the Data Track you wrote pytest tests for your pipeline logic (Week 2 - Testing with pytest). Those same tests are what the CI pipeline runs before it builds and pushes the image to ACR.

</aside>

Tagging strategy

Use meaningful tags, not just latest:

<aside> ⚠️ latest is just a tag name. It does not automatically point to the newest image. If two people push latest a day apart, only the last push wins. Use explicit tags.

</aside>

The commit SHA comes from Git, which you have been using since the Core program. Each git commit produces a unique hash; CI exposes it as an environment variable so Docker can tag the image with the exact commit it was built from.

<aside> 📘 Core program connection: Git commit hashes are the identifier you tag images with in CI. You first worked with commits and SHAs in the Core program Git introduction. Review: Core Program - Intro to Git

</aside>

Understanding the registry URL

The full image reference follows this pattern:

<registry>.azurecr.io/<image>:<tag>

For example: hyfregistry.azurecr.io/weather-pipeline:1.0

Your CI workflows will construct this string to tag and push images automatically.

This extends the build_image_tag exercise from the previous chapter: here you produce the full Azure Container Registry URL form, with the .azurecr.io suffix baked into the registry host.

<aside> ⌨️ Hands on: Write a function build_acr_url(registry_name, image, tag) that returns the full ACR image reference in the format <registry>.azurecr.io/<image>:<tag>.

</aside>

<aside> 🚀 Try it in the widget: Build ACR URL exercise

</aside>

This URL format is what docker tag and docker push expect when targeting ACR.

<aside> 💡 Using AI to help: If you are unsure about az acr commands, paste the error message into an LLM and ask for the fix. (⚠️ Ensure no PII or sensitive company data is included!) Verify the suggestion against the ACR docs before running it.

</aside>

Image formats are standardized so the same image runs across tools and clouds.

<aside> 🤓 Curious Geek: The OCI image standard

The Open Container Initiative (OCI) defines a standard image format so images built with Docker also work on containerd, Podman, and other runtimes. That is why your image is portable across tools and clouds.

For how the OCI split Docker into runc and containerd in 2015, see the optional History of Containers and CI/CD page.

</aside>

Exercises

  1. Log in to the shared ACR and push an image to it.
  2. Find your image in the Azure portal and note the digest.
  3. Tag the same image as dev and prod and push both. Confirm they share the same digest.
  4. Explain why latest is unreliable for production deployments.

Knowledge Check

<aside> 🚀 Try it in the widget: Interactive Quiz: Azure Container Registry

</aside>

https://lasse.be/simple-hyf-teach-widget/mcq.html?bank=week_5_ch4_azure_container_registry&embed=1

Extra reading

<aside> 📚 For advanced ACR topics (geo-replication, retention policies, vulnerability scanning with Defender for Containers), see the optional Going Further page.

</aside>

When you are ready to practice the full push-and-tag sequence, Exercise 7 walks through it against the shared registry.

<aside> ⌨️ Hands on: Practice with Exercise 7: Image Tagging Strategy, where you tag the same image with multiple identifiers and verify that all tags point to the same underlying digest in ACR.

</aside>


Next up: Python CI Pipeline, where you automate everything you just did by hand: a GitHub Actions workflow that lints, tests, builds, and pushes the image to this registry on every commit.