Container foundations

What a container is

Build a useful mental model of images, containers, isolation, and the host kernel before running Docker commands.

A container is a process. A normal process running on your machine, with one difference: it has its own view of the filesystem, the environment variables, the users, and the network. It can’t see the rest of your system.

It’s tempting to think of a container as a small virtual machine. It’s not. A virtual machine boots a whole operating system, with its own kernel. A container shares the kernel of the host. That’s why a container starts in a fraction of a second, while a VM takes a while to boot.

Images and containers

Two words you’ll hear all the time: image and container.

An image is a read-only package. It contains the files the process needs (a Linux distribution, Node.js, your application code) plus the instructions to start it.

A container is a running instance of that image. Docker takes the image, adds a thin writable layer on top, and asks the operating system to run the startup command in isolation.

Think of the image as a recipe and the container as the dish. You can cook the same recipe many times, and throwing a dish away doesn’t touch the recipe.

The main process

When Docker starts a container, the startup command becomes the container’s main process. The container lives as long as that process lives.

This is the part people get wrong at the beginning. If your Node.js server crashes, the container stops. If your command is a script that finishes in two seconds, the container stops after two seconds. A container is not a machine that keeps running in the background.

Any files the process wrote end up in the writable layer. They stay there while the container exists, but they are tied to that container. We’ll see how to keep data outside of it later in the course.

Isolation is not a wall

Isolation is useful. Your app can’t overwrite files on your laptop, and two apps can use different versions of Node.js without fighting.

But don’t treat it as a security boundary you can forget about. The process still shares the kernel with the host, and a kernel bug affects both.

So a few habits I’d suggest from day one: run with the fewest privileges you can, keep durable data outside the writable layer, and treat the image as the thing you build once and containers as disposable copies of it.

Before moving on, take a small Node.js API you have (or imagine one) and write down four things: the application code, the runtime it needs, any system packages, and the command that starts it. Those are the ingredients we’ll put in an image in the next lessons.

Lesson completed