← All courses
IVYXSTUDIO · COURSE

CONT 201

cont-201 · v1.0.0

ivyx✓

Containers as the Unit of Deployment: put wave one's retriever in an image, watch the container disagree with the host, count what a rebuild redoes, address a second container by name, read exit codes, lose an index on purpose, find a deleted secret in a layer, and ship an image you can defend.

intermediate485 min9 lessonsen
#containers#docker#compose#deployment#platform#ai-series#intermediate

What this course is for

By the end of this course you can write a compose file that stands your service and its store up together, read the logs of a container that will not start, and name the difference between your machine and the image.

What you will be able to do

  • Run one service on the host and in a container, and explain two different answers from one relative path
  • Read an image layer by layer with history, inspect and find, and put a size on what the copy brought in
  • Reorder two Dockerfile lines and predict from the file alone which steps a rebuild takes from the cache
  • Stand two containers up with Compose, reach one from the other by service name, and say what localhost means inside a container
  • Read a stopped container's exit code and log and sort it into finished, crashed or misconfigured before touching it
  • Tell the writable layer from a volume by what survives a restart and what survives a recreate
  • Find a file a running container cannot see in the layer that still carries it, and move configuration and secrets out of the image
  • Justify every line of a shipped Dockerfile with a measurement, and prove two runs from nothing are the same run

Who it is for

Learners who finished RAG 101 and can write a Python function, and who now have to hand a working service to somebody else's machine.

Before you start

  • PYTHON 101, for functions, files and the standard library the service is written in
  • RAG 101, for the retriever, the corpus and the questions this course puts in a container

Lesson path

The image3 lessons

What is in an image, how it got there, and what a rebuild has to redo

  1. 1It works on my machine40 min

    Run the retriever on the host, run it in a container, and get two different answers to one question

  2. 2What is actually in there55 min

    Read the image layer by layer and find the three things the copy brought in that nobody meant to ship

  3. 3The rebuild that took two seconds55 min

    Reorder two lines, measure the cached layer count, and say which edit invalidates what

The system2 lessons

Two containers on one network, and the ones that stop

  1. 4Two containers, one network55 min

    Stand the service and its store up together and name what a service address is when it is not localhost

  2. 5The container that will not start55 min

    Read an exit code and a log, and tell a crash apart from a container that did its job and stopped

State2 lessons

What a container writes, where it goes, and what belongs outside the image

  1. 6What survives a restart55 min

    Separate the writable layer from a volume, and lose an index on purpose

  2. 7Configuration is not code55 min

    Move the corpus path and the port out of the image, and find the secret that was baked into a layer that is still there after it was deleted

Judgment2 lessons

The image you would ship, and the proof that it ships the same twice

  1. 8The image you would actually ship55 min

    Base, user, healthcheck and size, each justified against a measurement rather than a habit

  2. 9From nothing to answering60 min

    Stand the whole thing up in one command, verify it with the smoke questions, tear it down, and prove the second run is the same as the first

About this course

CONT 201 · Containers as the Unit of Deployment

Wave one ended with a retriever you built, measured and priced: BM25 over Northgate Motors' 52 documents, a lot table of 24 cars, a query log of a week. It runs in a notebook, on one machine, for one person. This course is about the first thing that changes when it has to run somewhere else: the thing you hand over stops being a folder of Python and becomes an image, and an image is a record of exactly what is inside it, which is not what your machine had. The tour proves it in five questions. The same 139 line service, run on the host and in a container built from its own folder, gives two different answers to two of them, because one relative path resolved against two working directories and the copy brought a stale snapshot of the corpus along.

The course does not explain containers; Docker's documentation does that well and the reading list points at the pages. It puts wave one's retriever in a container in front of you and measures what happens: how many layers the image has and what each weighs, how many build steps a one character edit redoes under two orderings of the same Dockerfile, what localhost means from inside a container standing next to another, what three exit codes and three logs say about three containers that stopped, what survives a restart and what survives a recreate, where a deleted secret still lives, and what each line of a shipped image is for.

Every number a graded cell checks comes from a recording made when the course was built, so the answers are the same on every machine and on a machine with no Docker at all. Every live cell runs your own Docker when you have one and prints what your machine says beside the recording. Layer counts, cached step counts, exit codes and addresses agree; sizes and seconds are your machine's, and the prose says so wherever it quotes one.

How this course teaches

Lesson 1 is a tour: it runs the service twice, asks five questions twice, and lets you predict how many answers match before it shows you. The eight lessons after it are graded work, each built the same way, and nine or ten of their cells are yours.

  • A prediction you commit to before the cell runs. It is graded on the reasoning, not the guess, and being wrong here is the point.
  • Warmups: a one line blank or a short exercise under the theory it practices, each with a four rung hint ladder behind it, where the last rung explains and still does not hand over the code.
  • An exercise that is broken when you open it.
  • A diagnose cell: code that runs, prints a confident and plausible conclusion, and is wrong. The evidence that refuses it is already on the screen.
  • A challenge that ends in a sentence you write. The tutor grades the sentence, which means a green tick earned for the wrong reason can be taken back.

No cell in this course passes in the state it ships. That is deliberate, and it is checked mechanically before the course is published.

The particular danger of this subject is a command that answers a different question from the one you asked. ls inside a container says a deleted file is gone, and the file is in layer 7 of the image with its token intact. docker ps says a container is Up, and the container is answering nothing. docker run -d returns 0, and the process it started crashed a second later. A build log says 5.3 seconds, and the number that belongs to the Dockerfile is 1 of 4 steps cached. Every diagnose cell is one of those, and every refusal is the record that answers the right question: the layer listing, the health status, the exit code, the cached count.

What you will be able to do

  • Run one service on the host and in a container, and explain two different answers from one relative path.
  • Read an image layer by layer with history, inspect and find, and put a size on what the copy brought in.
  • Reorder two Dockerfile lines and predict from the file alone which steps a rebuild takes from the cache.
  • Stand two containers up with Compose, reach one from the other by service name, and say what localhost means inside a container.
  • Read a stopped container's exit code and log and sort it into finished, crashed or misconfigured before touching it.
  • Tell the writable layer from a volume by what survives a restart and what survives a recreate.
  • Find a file a running container cannot see in the layer that still carries it, and move configuration and secrets out of the image.
  • Justify every line of a shipped Dockerfile with a measurement, and prove two runs from nothing are the same run.

The lessons

1. It works on my machine. The service on the host searches 52 documents; the same image, built with COPY . ., searches 27, because data/docs.csv inside the folder is a snapshot from before the 2025 warranty edition and the listings. Two of five smoke answers differ: the warranty question falls to the 2023 edition and the A-123 question to an FAQ about mileage. Same code, same path, two working directories.

2. What is actually in there. Fifteen history rows, seven layers, four of them the base's. The Dockerfile added three: a directory at 8.19 kB, a copy at 94.2 kB and an install at 85.7 MB. The copy brought .env, .venv and __pycache__, about 40 kB together in this fixture; the install left 20 MB of pip cache behind, 500 times the three. The folder you copied is 0.02 percent of the image.

3. The rebuild that took two seconds. A one character edit under the naive ordering keeps 1 of 4 steps and downloads the 19.4 MB wheel again; under the ordered file it keeps 3 of 5 and only the source copy runs. An edit to the dependency list keeps 1 of 5 either way. The recording's clock says 5.3 seconds against 0.3; the count is the number you keep, and you can predict it from the Dockerfile without a build.

4. Two containers, one network. One image, two roles. From inside the service container localhost:8001 is refused and store:8001 answers, because localhost is the caller's own loopback and store is a name Compose resolves to 172.19.0.2. A lot request asked of the service comes back answered_by: store with eight Kessel rows, and both containers log it. depends_on orders starts and waits for nothing.

5. The container that will not start. Three containers, three Exited rows, codes 1, 0 and 2: an uncaught FileNotFoundError on data/nope.csv, an index job that finished, a program that printed its usage. docker run -d returned 0 for all three. The log names the cause in its last line. A restart would have helped none of them and on-failure would have looped two.

6. What survives a restart. The index job added three paths to its writable layer and a fresh container from the same image had none of them. A running container kept its index across docker restart and lost it to rm plus run. A named volume carried the 21,309 byte index into a container that never built it. A deploy is a recreate.

7. Configuration is not code. RUN rm .env made ls say the file was gone and left it in layer 7 of nine, token and all, under a whiteout in layer 8. Adding .dockerignore while keeping the rm failed the build at step 6; removing the rm gave an image with the token in no layer. The same image read 27 documents by default and 52 with DOCS_PATH set and the corpus mounted.

8. The image you would actually ship. Uid 10001 where the naive image ran as 0; a healthcheck that turned a container unhealthy after three checks while docker ps said Up; about 20 MB saved, all of it --no-cache-dir, with the .dockerignore changing the size by 151 bytes and changing what shipped. One line is wider than the measurements justify, and the challenge names it.

9. From nothing to answering. Zero containers, one up, both services running with health starting, five smoke answers identical to the host's from lesson 1, seven Torres rows through the store. One down, two containers and one network removed, zero left. The second run matched the first on every answer, every score and the base digest 78387bc3..., and the report says what that proves and what it does not.

Requirements

Python 3.10 or later with duckdb, which the service uses for the lot table:

pip install duckdb

Docker is a tool, not a package, and requires.packages cannot install it. Docker Desktop on macOS or Windows, or the docker engine with the compose plugin on Linux, makes the live cells build and run containers on your machine; the first build pulls python:3.12-slim and one wheel. Without Docker every cell still runs, from the recording made when the course was built, and every graded cell reads that recording either way. The live cells publish the service on port 18000 and remove every container they start; the images they build and one named volume, cont201_index, stay until you remove them with the commands lesson 9 prints.

What to read outside this course

Docker's Dockerfile reference is the document to keep open; the page on COPY and the build context is lesson 2's theory and the guide on layers and the build cache is lesson 3's. The Compose networking page explains why a service is reachable by name and why localhost inside a container is that container. The best practices page on writing Dockerfiles is lesson 8's checklist with reasons attached; the course's contribution is that you measure each item before adopting it. For what a whiteout is, the OCI image specification's layer section is short and exact.