Docker & Containers
From the kernel features that make a container a container through to a hardened, scanned image running as a Compose stack β layers, Dockerfiles, volumes, networking, registries and the failure modes that waste afternoons.
beginner level
4 lessonsThe packaging problem containers actually solve, why a container is not a small virtual machine, and the honest list of things Docker is the wrong answer for.
Follow docker run all the way down through the REST API, the daemon, containerd and runc β and understand why the daemon can restart without killing your containers.
The run flags that matter β detached, interactive, published ports, restart policies and resource limits β plus why your container exits immediately and how to prove it.
The two kernel features that make a container a container β which namespaces exist, what each one hides, and why cgroups are the only thing standing between one container and the whole host.
intermediate level
6 lessonsWhy an image is a stack of read-only layers, what the storage driver unions together to make one filesystem, and how the thin writable layer decides what survives a container's death.
Every instruction that matters, the ENTRYPOINT/CMD relationship that confuses everyone, the difference between ARG and ENV, and why the build context is usually the reason your build is slow.
Build with a compiler, ship without one. How multi-stage builds separate the build environment from the runtime image, and the BuildKit features that make builds fast as well as small.
Three ways to keep data out of the writable layer, when each one is right, and the anonymous-volume behaviour that quietly fills a host's disk.
The container network model, why the default bridge has no DNS but a user-defined one does, what each native driver is actually for, and how to trace a packet from the host to a container port.
Tagging for a registry, pushing to Docker Hub, ECR and ACR, why a tag is not an identity, and the rate limits and retention rules that break builds at the worst time.
advanced level
4 lessonsDeclare a whole stack in one file, gate startup on real health rather than depends_on, and make the same definition serve development, CI and a small production host.
Non-root users, dropped capabilities, read-only root filesystems, secrets that never reach a layer, and the two mounts that hand an attacker your host.
A repeatable triage order for a container that will not start, will not stay up, or cannot be reached β plus the exit codes worth memorising and the disk problem that causes half of them.
Take an application from a bare repository to a hardened, multi-stage, scanned image running as a Compose stack behind a proxy β with a written rollback that you have actually executed.
π― What You'll Learn
- β’ Explain a container as a process with namespaces and cgroups, not as a small virtual machine.
- β’ Trace docker run down through the daemon, containerd and runc β and know why the daemon can restart without killing your containers.
- β’ Diagnose a container that exits immediately from the exit code alone, without guessing.
- β’ Set CPU, memory and PID limits deliberately, and recognise 137 as an OOM kill on sight.
- β’ Read an image as a stack of layers, and explain why a RUN rm at the end never shrinks anything.
- β’ Order a Dockerfile so a code change reuses the dependency layer, and get ENTRYPOINT and CMD right the first time.
- β’ Cut an image by an order of magnitude with a multi-stage build, and keep secrets out of every layer.
- β’ Choose between a volume, a bind mount and tmpfs on their real trade-offs β and account for every anonymous volume on a host.
- β’ Explain why the default bridge has no DNS, and segment a stack across two user-defined networks.
- β’ Tag for a registry so a rollback is one line, and deploy by digest where certainty matters.
- β’ Gate a Compose stack on real health rather than on depends_on, and know what changes before it leaves a laptop.
- β’ Run non-root, read-only and capability-dropped, and name the two mounts that hand an attacker your host.
- β’ Work a repeatable triage order for a container that will not start, will not stay up, or cannot be reached.
- β’ Ship one service end to end: multi-stage, hardened, scanned, pushed, deployed and rolled back with a measured recovery time.
π‘οΈ Best Practices in Production
The short version of this path. Every lesson also ends with the specific mistake it exists to prevent.
- β Order the Dockerfile so dependencies install before source is copied β that is the whole build cache.
- β Use multi-stage builds and a minimal runtime base; ship the artifact, not the toolchain.
- β Pin base images by digest, and rebuild on a schedule to pick up security fixes.
- β Run as a non-root
USER, read-only root filesystem, and--cap-drop=ALLplus what you need back. - β Set memory and CPU limits explicitly, and treat exit code 137 as an OOM kill on sight.
- β Use
.dockerignoreβ it decides build context size and stops secrets from entering the build. - β Use BuildKit secret mounts for build-time credentials, never
ARGor aCOPYed file.
- β
RUN rmof a file added in an earlier layer β the bytes are still in the image, and still extractable. - β Using
:latestanywhere. The build stops being reproducible and rollback stops being precise. - β Mounting
/var/run/docker.sockinto a container. That is root on the host. - β Storing state in the container filesystem β it disappears on the next deploy.
- β One giant
RUNchain nobody can cache, or fifty tiny ones that bloat the layer count. - β Running an init-less process as PID 1 that ignores SIGTERM, so every stop takes the full grace period.