Frontend Labs
⋯

Part 15 — Docker in depth

Part 14 showed you what a container actually is from the kernel's point of view — namespaces, cgroups, a filesystem. This part is the practical layer built on top of that mechanism: Docker specifically, running and understanding real containers rather than the primitives underneath them.

Chapter 47 — Running your first containers, and understanding what happened

In one sentence

docker run does several distinct things in sequence — pull an image if needed, create a container from it, and start the process inside — and naming each step precisely turns "Docker magic" into a small, predictable sequence you fully understand.

Why this matters

Every Docker command you'll ever run is a variation on this same handful of verbs — knowing them precisely, not just by muscle memory, is what lets you debug when something doesn't behave as expected.

How it actually works

   docker pull ubuntu:22.04       # download an IMAGE (Chapter 46) from
                                 # a registry (Chapter 52), if not
                                 # already present locally
   docker run ubuntu:22.04 echo "hi"    # CREATE a container from that
                                 # image, and START the process inside
                                 # it (this implicitly pulls first, if
                                 # needed)
   docker ps                      # list RUNNING containers
   docker ps -a                     # list ALL containers, including
                                 # stopped ones
   docker stop <container>           # send SIGTERM (Chapter 20!),
                                 # wait, then SIGKILL if it hasn't
                                 # exited -- EXACTLY Kubernetes' pod
                                 # termination sequence from Chapter
                                 # 20, one layer down
   docker rm <container>              # remove a STOPPED container
                                 # (and its writable layer, Chapter 46
                                 # -- any unsaved changes are gone)
   docker exec -it <container> bash    # run an ADDITIONAL process
                                 # inside an ALREADY-RUNNING container
                                 # -- useful for poking around, NOT
                                 # how the container's main process
                                 # started
   docker logs <container>              # see the STDOUT/STDERR
                                 # (Chapter 28's file descriptors 1/2)
                                 # of the container's main process

   FLAGS WORTH KNOWING IMMEDIATELY:
     -d          detached -- run in the background, return your
                terminal immediately (Chapter 32's background jobs,
                one layer up)
     -it          interactive + a pseudo-TTY -- lets you actually type
                into the container's process (needed for `docker exec
                ... bash` to feel like a real shell)
     --rm          automatically remove the container once it exits --
                good hygiene for throwaway/test runs
     --name X       give it a memorable name instead of a random one
     -p HOST:CONTAINER   publish a port (Chapter 50 covers this properly)

Real-world example

   `docker run hello-world` is, quite literally, Docker's OWN official
   "does this actually work" onboarding test -- documented in Docker's
   getting-started material since the project's early public releases,
   and still the first command most engineers ever run with Docker
   installed. It's worth understanding EXACTLY what it does, because
   it's a genuinely complete, minimal demonstration of this chapter's
   whole sequence: Docker checks for the `hello-world` image locally
   (usually not found, the first time), PULLS it from Docker Hub
   (Chapter 52's registry), CREATES a new container from it, STARTS the
   tiny program inside (which just prints an explanatory message and
   exits immediately), and the container then sits, STOPPED (Chapter 3's
   exit -- the process finished, exit status 0), visible in `docker ps
   -a` but not `docker ps`.
   Running it once, and then deliberately walking through `docker ps
   -a`, `docker logs`, and `docker rm` on the resulting stopped
   container -- rather than just trusting the friendly printed message
   -- is a genuinely good way to make this chapter's whole vocabulary
   concrete on your very first real Docker command.

Try it yourself

# The official one, examined properly
docker run hello-world
docker ps -a                     # see it, STOPPED, exit code 0
docker logs $(docker ps -a -q --filter ancestor=hello-world | head -1)

# Run something longer-lived, and practice the full lifecycle
docker run -d --name webtest nginx
docker ps                          # RUNNING
curl -s localhost:80 > /dev/null 2>&1 || echo "(not published yet --
  Chapter 50 covers -p properly; this container's port 80 isn't
  reachable from the host yet)"
docker exec webtest ls /usr/share/nginx/html    # poke around inside
docker logs webtest
docker stop webtest                 # SIGTERM, then SIGKILL if needed
docker ps -a                          # STOPPED, not gone
docker rm webtest                      # actually removed now
docker ps -a | grep webtest || echo "confirmed: gone"

# Clean up hello-world containers too
docker rm $(docker ps -a -q --filter ancestor=hello-world) 2>/dev/null

Common mistakes

  • Confusing docker stop (graceful, Chapter 20's SIGTERM) with docker kill (immediate SIGKILL). Use stop by default; reach for kill only when a container genuinely won't respond to the polite request.
  • Forgetting docker rm is needed after docker stop. A stopped container still exists (and its writable layer still takes disk space) until explicitly removed.
  • Using docker exec and assuming it's "how the container started." exec runs an ADDITIONAL process alongside the main one — killing your exec'd shell does NOT stop the container itself.

Check yourself

  1. List, in order, what docker run actually does the first time you run a given image.
  2. What's the difference between docker stop and docker rm?
  3. Why does killing a docker exec'd shell not stop the container?

(Answers: Appendix E.)

Further reading

  • Docs: Docker's own "Getting Started" guide — still one of the clearest, most concrete introductions available, directly from the source.
  • Reference: docker --help, docker run --help (genuinely worth reading in full once).
  • Practice: run docker events in one terminal while you run commands in another — watch the exact sequence of internal events fire in real time.

Generated from real-life-os-guide.md · 8 Oct 2026 16:36