Key idea
Your app depends on far more than its own code. When those dependencies differ between two machines, the same code behaves differently: that's dependency drift. A container image packs the code and its dependencies together, so every machine runs exactly the same thing.
What drifts
- The language runtime: Node 20 on your laptop, Node 22 on the server.
- Libraries: a lockfile pins your packages, but not the system libraries they call, such as an image-processing or TLS library.
- The operating system: macOS ignores upper and lower case in file names; Linux doesn't. An import of
./Headerfindsheader.json a Mac and fails on the server.
Each one is small. Together they mean "it worked when I tried it" says little about the next machine.
How an image fixes it
An image holds your code, the runtime, the libraries and a Linux file system, built once. Your laptop, a teammate's laptop, CI and production all start that same image. What you tested is what runs.
Configuration still comes from outside, as in One build, many environments: the image is the same everywhere, and each environment gives it its own settings.
What an image doesn't fix
Containers share the host's kernel, so an image is built for one kind of processor. An image built for Intel and AMD servers (amd64) runs slowly under emulation on an Apple silicon Mac (arm64), and Docker prints a warning when you start it. The next lesson explains why.
Check yourself