I Knew What Docker Did. I Didn't Know Why I Needed It.
What changed when I started looking beneath the abstractions of frontend deployment.
The abstraction I started from
I came into this from frontend engineering — mainly React and Next.js, with GitHub and Vercel as the path to production.
Deployment was abstracted. I could push code and have an application running without owning the machines, runtime, packaging, or deployment infrastructure underneath.
I had read about Docker. I understood the basic pitch: package an application and what it needs so it can run consistently elsewhere. I just didn’t really have a reason to care. I wasn’t dealing with that problem myself.
Knowing about Docker is not the same as using it. I only started genuinely using Docker when I began moving into cloud engineering. That was when the problem Docker was solving started becoming relevant to me.
The environment problem
Not hiding — abstracting.
An application does not run just because the source code exists. Somewhere, something still has to provide a machine, an operating environment, the right runtime, dependencies, configuration, networking, and a way to start the app and keep it running. On Vercel, a lot of that was already handled 🫠.
When I started learning cloud engineering, those questions became mine. Especially this one: if I move an application from one machine to another, how do I make sure it still has the environment it expects?
People call this “works on my machine.” The deeper issue is reproducibility: can I recreate the environment this application needs, on another machine, in a reliable way?
That is the problem. Not containers yet. Not Docker yet.
Before containers
We were solving this long before Docker.
Engineers configured servers by hand, wrote scripts, used configuration management, pinned runtimes locally. 😩
Virtual machines were another real answer: they gave applications isolated environments by running a full guest operating system with its own kernel. That works, but for many workloads it’s heavier than necessary, because each VM brings that whole guest OS along.
Do we need an entire virtual machine every time we want an isolated environment for an application?
Containers
Containers are one answer to that question.
They let you run an application in an isolated environment without giving every application its own virtual machine. You get isolation from other applications on the machine, and you can package the environment the app needs — but you are not booting a separate guest operating system for each one.
That is enough for now. A container is not a tiny VM. What it actually is underneath is a different article.
Why Docker?
Containers as an idea are older than the way most developers meet them. What Docker did was make the workflow approachable.
You describe how the application environment should be built. You build an image from that. You run containers from the image. You can distribute that image to other machines.
That is the loop: Dockerfile, image, container, registry.
Once the environment problem is visible, the original pitch is clearer: package your application and run it consistently elsewhere.
But there's something I skipped over; I said a container gives an application an isolated environment without giving it an entire virtual machine.
If a container isn't a tiny VM, what actually is it?