Stack Signal.
Technical news & guides across AI, programming and the open-source world
WEDNESDAY, SEPTEMBER 23, 2026 · 55 articles · RSS

DevOps & Self-HostingSep 22, 2026572 words
How-To Guide

Getting Started with Docker: Containers, Images, and Your First Container

Getting Started with Docker: Containers, Images, and Your First Container

Docker can feel intimidating until you pin down two words you'll hear constantly: image and container. Good news — the mental model is simpler than it looks. Let's walk through the basics, then get your hands dirty with real commands.

Containers vs. virtual machines

The fastest way to understand a container is to compare it to a virtual machine (VM). A VM bundles a full guest operating system on top of a hypervisor, so every VM drags along its own kernel and OS userland. That's the part that makes VMs heavy and slow to start.

A container takes a different path. All containers on a host share the host kernel — they don't bundle their own OS. What you treat as an OS (like node:alpine or ubuntu in an image) is really the userspace: the binaries, libraries, and config the app needs to run. Because the kernel is shared, containers are lightweight and start in seconds. The trade-off to remember: containers share the host's kernel, so the host has to be running a supported Linux kernel (or Docker runs through a VM layer on macOS and Windows).

Images are blueprints, containers are running instances

An image is a read-only blueprint. It's a packed, read-only template that contains everything needed to run an application. It's the "cake recipe," not the cake.

A container is a running instance of that image. When you start a container, Docker adds a thin read-write layer on top of the image's layers — the container can change files at runtime without mutating the underlying image. That's how you can have dozens of containers all running from the same image, each one isolated from the others.

Your first command: docker run hello-world

Docker ships a tiny test image exactly for this. Open a terminal and run:

docker run hello-world

Docker will pull the small hello-world image, spin up a container from it, print a friendly confirmation message, and then exit. It's a smoke test — if you see that message, your Docker install works. (Add --detach or -d if you ever want a container to keep running in the background instead.)

Writing a Dockerfile

Once you want to build your own image, you write a Dockerfile — a plain-text list of instructions. The big four look like this:

FROM node:24-alpine
COPY . /app
RUN npm install
CMD ["node", "server.js"]
  • FROM picks a base image to start from.
  • COPY copies files from your project into the image.
  • RUN executes a command at build time (like installing dependencies).
  • CMD sets the command that runs when a container starts.

Build it with docker build -t my-app . and run it with docker run my-app.

Tying it together with Docker Compose

Real applications are rarely one container. Docker Compose lets you define all your services — a web app, a database, a cache — in a single compose.yaml file, then start them together with docker compose up. It's how you stop juggling a zoo of docker run commands.

That's the whole skeleton: containers share the kernel, images are read-only blueprints, containers are the running instances, docker run gets you going, a Dockerfile automates builds, and Compose orchestrates multi-container stacks. Pick one small project and containerize it — you'll learn more in an afternoon than in a week of reading.