Docker for Software Development: Classroom Bootcamp

An eight-hour classroom bootcamp on Docker, taught on a realistic multi-container application: Smarter’s Django web server, Celery workers and scheduler, MariaDB and Redis, built from one Dockerfile and run with one Compose file. The Dockerfile has twelve stages, from a slim Python 3.14 base to a non-root user whose files are made read-only outside development, and docker-compose.yml runs six services: the Django web server, two Celery workers on separate queues, the Celery scheduler, MariaDB and Redis. The same image plays four roles, the docker-* targets in the Makefile wrap every step, and the same image runs in production on Kubernetes, so nothing students learn is a classroom simplification. The files also have real flaws to find, such as unpinned base images. Students read, run, debug and improve it. See Course Formats and Grading for the standard bootcamp day, the grading scale and the course policies, and Docker for Software Development for an overview of the subject.

At a Glance

Students

Developers and operations engineers who are new to containers, or who use them without understanding them.

Deployment

Each student clones the repository and runs it with Docker Desktop (or Docker Engine on Linux). The first make init downloads and builds several gigabytes, so it must be done before the bootcamp.

Cost

Free. Labs need no model provider calls beyond a single test chat.

Learning Objectives

By the end of the bootcamp, students can:

  1. Explain images, layers, containers, volumes, networks and registries.

  2. Read a multi-stage Dockerfile, and explain what each instruction does and why.

  3. Run and debug a multi-container application with Docker Compose, using exec, logs, stats and inspect.

  4. Explain why one image can run as a web server, a worker and a scheduler, and how configuration reaches it.

  5. Improve an image’s size, build time or security, and measure the result.

Technical Prerequisites

  • Required: the Linux or macOS command line: navigating directories, files and permissions, environment variables, processes, and a text editor.

  • Required: Git: clone and pull.

  • Required: Docker Desktop installed, with at least 8 GB of memory allotted to it, and make init and make run completed from the repository before the bootcamp (see Developer Setup Guide).

  • Required: reading YAML.

  • Helpful: reading Python or another scripting language, and basic networking (ports, DNS, localhost).

Schedule

The files that the lectures refer to are listed in full under Smarter in the Source Code.

Block

Min

Content

1

45

Lecture 1: Why containers. “It works on my machine”, virtual machines versus containers, images, layers, containers and registries. Smarter’s containers, and ADR 002 on Docker.

2

45

Lab 1: Look inside. With docker ps, docker images, docker history, docker inspect and docker exec, explore the running Smarter containers: their processes, users, environment and networks. Produces Assignment 1.

3

45

Lecture 2: The Dockerfile. Instructions, the build cache, multi-stage builds, and a walk through Smarter’s Dockerfile stage by stage: base image, system packages, kubectl, the MariaDB connector and the AWS CLI, a non-root user, a virtual environment, the application, hardened permissions, built-in data, and static assets.

4

45

Lab 2: Annotate the Dockerfile. Annotate every stage and instruction: what it does, why it is there, and what would break without it. Produces Assignment 2.

5

45

Lecture 3: Compose. Services, networks, volumes, environment files, health checks and dependencies, through Smarter’s docker-compose.yml. How the docker-* targets in the Makefile wrap it, and what make docker-init does on first start.

6

45

Lecture 4: One image, many roles. Why the web server, the workers and the scheduler run from the same image with different commands. Configuration through the environment, and ADR 004 on the twelve-factor app.

7

45

Lab 3: Follow a request. Send a chat message, and follow it from the web server to a Celery worker and back with docker logs, docker stats and Redis’s MONITOR command. Produces Assignment 3.

8

45

Lecture 5: Images that are small, fast and safe. Layer ordering for caching, slim base images, .dockerignore, running as non-root, secrets at build time versus run time, and scanning with Trivy.

9

45

Lab 4: Measure an image. Explore Smarter’s image layers with dive, find the three largest, and propose one way to shrink each. Ungraded.

10

45

Lecture 6: From Compose to production. Development versus production images, the lack of a bind mount in Smarter’s setup and its trade-offs, the Quick Start’s own Compose file in smarter-deploy, multi-architecture builds and registries, and why Kubernetes comes next.

11

30

Capstone kickoff. Students choose a capstone and plan it.

Smarter in the Source Code

Every lecture, lab and assignment in this course rests on the files below. Every reference is to the main branch of github.com/smarter-sh/smarter, unless another repository is named, so that students can open each one during class.

The Image

Topic

What Smarter does

Where to look

Twelve build stages

linux_base (Python 3.14 on Debian trixie slim), system_packages, kubectl, mariadb_connector, aws_cli, user_setup, venv, application, permissions, data, collect_assets and serve_application, each building on the last, so that a code change rebuilds only the final stages.

Dockerfile

A non-root user

The application runs as smarter_user, in a virtual environment in that user’s home directory. Outside local development, the permissions stage makes the application’s files read-only (mode 400) and its directories 500, so a compromised process cannot rewrite the code.

Dockerfile (user_setup, permissions)

Build arguments

ENVIRONMENT and DOCKER_COLLECT_STATIC_FILES change what is built: make build skips collecting static assets, so a rebuild takes seconds, and make react-build collects the React apps as well.

Makefile (docker-build, docker-build-for-react)

Data baked into the image

The WordNet corpus for plugin selection by synonym is downloaded at build time, so the running container never needs to fetch it.

Dockerfile (venv)

What stays out

Caches, coverage reports, node_modules and other files that would bloat the build context or leak into the image.

.dockerignore

Something to question

The image EXPOSEs port 8000, but uvicorn listens on 9357. EXPOSE is only documentation, which is exactly why a mismatch goes unnoticed.

Dockerfile (serve_application)

Compose and the Makefile

Topic

What Smarter does

Where to look

Six services

smarter-mariadb, smarter-redis, smarter-app (uvicorn, restarted by watchmedo when a Python file changes), smarter-worker and smarter-worker-infrastructure (two Celery workers on separate queues) and smarter-beat (the Celery scheduler).

docker-compose.yml

One image, four roles

The web server, both workers and the scheduler run the same smarter image with different commands. ADR 004.

docker-compose.yml (command:)

Following a request

The web server answers a chat message, and hands its charge, its history and its tool calls to Celery tasks, which the worker writes to the database. docker logs on both containers shows each half.

text_completion/lib/mixins.py, account/tasks.py

Health and start order

Health checks on the workers and the scheduler, and depends_on between services.

docker-compose.yml

No bind mount

The source is copied into the image, not mounted, so the containers run exactly what was built. The trade-off: every edit needs a rebuild or a copy, which is what the sync scripts are for.

sync-changed-files.sh, smarter-docker-environment/SKILL.md

First start

make docker-init starts the services, waits for MariaDB, creates the database, loads a sample database, migrates, and initializes the platform with its built-in resources.

Makefile (docker-init), scripts/smarter_test_db.sql

Configuration

Every setting comes from the environment, through .env, and is validated at start-up.

.env.example, common/conf/settings.py

Something to question

mariadb:latest and redis:latest are not pinned to a version, so two students can run different databases from the same file.

docker-compose.yml

Beyond the Laptop

Topic

What Smarter does

Where to look

A second Compose file

The Quick Start runs a prebuilt image from Docker Hub with its own, smaller Compose file, which uses MySQL rather than MariaDB and has no infrastructure worker. Comparing the two is a lesson in development and production parity.

smarter-deploy: docker-compose.yml

Images in CI

GitHub Actions builds the image for linux/amd64 and linux/arm64 with Buildx, and pushes it to Amazon ECR, whose native vulnerability scanning the workflow switches on. Build.

build.yml

Signed artifacts

The Helm chart is signed with cosign when it is released, and its public key is published for verification on Artifact Hub.

helmChartRelease.yml, sigstore/

The same image on Kubernetes

The Helm chart runs the same image as four Deployments, one for each role. Kubernetes for Running Applications at Scale.

helm/charts/smarter/templates/

Graded Assignments

Assignment 1: Container Inventory

Students produce an inventory of the running Smarter containers: image, command, user, exposed ports, volumes, networks and the main process of each.

Turn in: a table and the commands used to fill it in.

Criterion

Pts

Exemplary

Developing

Completeness

8

Every container and every column filled in correctly.

Gaps or errors.

Method

6

Uses inspect and exec rather than guessing from the Compose file.

Copied from the Compose file.

Observations

4

Notes which containers share an image and why.

None.

Clarity

2

Easy to read.

Disorganized.

Assignment 2: Annotated Dockerfile

Students annotate Smarter’s Dockerfile: what each stage does, why the application runs as a non-root user, and three ways the image could be made smaller or faster to build.

Turn in: the annotated Dockerfile (comments added) in their fork.

Criterion

Pts

Exemplary

Developing

Accuracy

8

Every stage and instruction explained correctly.

Several explanations wrong.

Reasoning

5

Explains why, not only what, including the non-root user.

Restates the instruction.

Improvements

5

Three realistic improvements, with expected effect.

Generic advice.

Observation

2

Notes that the stages form a single chain, and what a separate build stage would change.

Not noticed.

Assignment 3: Request Trace

Students follow one chat request through the containers, with log lines and Redis activity as evidence, and explain why the same image appears in every step.

Turn in: a sequence diagram with the evidence.

Criterion

Pts

Exemplary

Developing

Trace

8

Every hop between containers shown.

Hops missing.

Evidence

6

Log lines and Redis commands for each hop.

Inferred.

Explanation

4

Explains the one-image, many-roles design.

Not addressed.

Diagram

2

Clear.

Cluttered.

Capstone Projects

Students choose one. Capstones are due one week after the bootcamp.

Capstone A: A Leaner, Safer Image

Learning objective. Improve a real production image, and prove the improvement with measurements.

Students make one or more changes to Smarter’s Dockerfile on their fork, for example a separate build stage so that compilers do not ship, better layer ordering, or a tighter .dockerignore, and measure image size, build time (cold and cached) and vulnerability count before and after.

What students turn in:

  • A pull request against their fork with the changes.

  • A before-and-after table of size, build times and Trivy findings, with the commands used.

  • Evidence that the application still works: the containers start and a test chat succeeds.

  • A one-page explanation.

How it is graded (100 points):

Criterion

Pts

Exemplary

Developing

Improvement

25

A meaningful, measured gain.

Marginal or unmeasured.

Measurement

25

Repeatable measurements of size, build time and vulnerabilities.

One measurement, or not repeatable.

Still works

20

All containers healthy; chat works.

Breaks a role (for example the worker).

Dockerfile quality

15

Readable, commented, passes Hadolint.

Hard to follow.

Explanation

15

Explains each change and its trade-off.

Lists changes only.

Capstone B: Containerize Your Own Application

Learning objective. Apply the patterns learned from Smarter to a new application, from Dockerfile to Compose.

Students containerize an application of their own (or an open source one) that has at least a web process, a background worker or scheduled job, and a database, following Smarter’s patterns: one image for several roles, a non-root user, configuration through the environment, and health checks.

What students turn in:

  • A Git repository with the application, Dockerfile, docker-compose.yml, .dockerignore and a README.md.

  • A short recording of docker compose up and the application working.

  • A one-page note comparing their choices with Smarter’s.

How it is graded (100 points):

Criterion

Pts

Exemplary

Developing

Works

25

Starts from a clean clone with one command.

Needs manual steps.

Dockerfile

20

Multi-stage, non-root, cache-friendly.

Single stage, runs as root.

Compose

20

Health checks, dependencies, volumes, environment file.

Services only.

Twelve-factor configuration

15

No secrets in images or the repository.

Secrets baked in.

Documentation

20

Clear README.md and comparison note.

Missing.

Further Study