Week 5 - Containers & CI/CD

Introduction to Containers and CI/CD

Dependency Management

Docker Fundamentals

Azure Container Registry

Python CI Pipeline

Week 5 Gotchas & Pitfalls

Practice

Week 5 Assignment: Containerize and Ship a Data Pipeline

Week 5 Lesson Plan

🛠️ Practice

These exercises let you practice Docker, CI, and dependency management concepts from this week.

<aside> 📝 These exercises are optional. Use them to reinforce the concepts from this week before starting the assignment.

</aside>

Exercise 1: Minimal Pipeline to Container

Concepts: Dockerfile basics, environment variables.

Create a minimal pipeline script in src/pipeline.py:

import os

api_key = os.environ.get("API_KEY", "missing")
print(f"API key present: {api_key != 'missing'}")

Instructions:

  1. Write a Dockerfile that runs this script.
  2. Build an image tagged pipeline-practice:1.0.
  3. Run it with API_KEY=demo and confirm the output changes.

Exercise 2: Cache-Friendly Dockerfile

Concepts: Docker layers and caching with requirements.txt.

Instructions:

  1. Create a requirements.txt file with requests==2.31.0.
  2. Write a Dockerfile that copies requirements.txt first and installs dependencies before copying the rest of the source. You can use the script above as code. Build the docker image.
  3. Adjust the code a little bit so that it triggers a partial rebuild (add a whitespace or newline for example). Build the image again and observe that the second build is faster.

Exercise 3: Cache-Friendly Dockerfile with uv

Concepts: Docker layers and locked installs with uv.

Instructions:

  1. Create a minimal pyproject.toml with requests==2.31.0.
  2. Generate and commit uv.lock.
  3. Write a Dockerfile that copies pyproject.toml and uv.lock first, installs uv, and runs uv sync --frozen --no-dev before copying the rest of the source.
  4. Build the image once.
  5. Edit only the source code and build again. Confirm that the dependency install layer stays cached.
  6. Change pyproject.toml, regenerate uv.lock, and build again. Confirm that the dependency layer now rebuilds.

Exercise 4: Compare both Docker approaches

Concepts: requirements.txt vs uv in Docker.

Instructions:

  1. Compare your two Dockerfiles side by side.
  2. Identify which files each one copies before dependency installation.
  3. Explain why uv sync --frozen is stricter than a plain dependency install from requirements.txt.
  4. Decide which approach you would use for a new project and which approach you would keep in an existing codebase.

Exercise 5: CI Smoke Test

Concepts: GitHub Actions, testing.

Instructions:

  1. Create a tests/test_smoke.py that asserts True.
  2. Add a GitHub Actions workflow that runs pytest -q.
  3. Break the test and confirm CI fails.

Exercise 6: Environment Variable Patterns

Concepts: -e, --env-file, ARG vs ENV.

Instructions:

  1. Create a .env file with API_KEY=demo and LOG_LEVEL=DEBUG.
  2. Run your container from Exercise 1 with --env-file .env and confirm both values are read.
  3. Add an ARG BUILD_SHA to your Dockerfile and pass it with --build-arg BUILD_SHA=abc123. Print it during the build.
  4. Explain why ARG values are not available at runtime.

Exercise 7: Image Tagging Strategy

Concepts: Version tags.

Instructions:

  1. Tag the same image as dev, staging, and prod.
  2. Run docker images and confirm all three tags exist for the same Image ID.
  3. Explain why having separate tags is useful even before you push them to a registry.

The HackYourFuture curriculum is licensed under CC BY-NC-SA 4.0 *https://hackyourfuture.net/*

CC BY-NC-SA 4.0 Icons

Built with ❤️ by the HackYourFuture community · Thank you, contributors

Found a mistake or have a suggestion? Let us know in the feedback form.