Docker is a platform for packaging an application together with its dependencies, libraries, and runtime into a single portable unit called a container, so it runs the same way on a developer's laptop, a CI server, and production. Unlike a virtual machine, a container doesn't bundle a full guest operating system — it shares the host machine's kernel while isolating the process using Linux kernel features (namespaces for isolation, cgroups for resource limits).
A Dockerfile describes how to build an image — a read-only, layered filesystem snapshot — as a sequence of instructions (FROM, COPY, RUN, CMD):
FROM node:20-alpine
WORKDIR /app
COPY package.json .
RUN npm install
COPY . .
CMD ["node", "server.js"]
Each instruction adds a cached, reusable layer, which is why reordering a Dockerfile (installing dependencies before copying application code, as above) speeds up rebuilds — Docker can reuse the cached dependency-install layer when only the application code changes. A running instance of an image is a container; the same image can run as many independent containers as needed. Images and their runtime format are standardized by the OCI (Open Container Initiative), which is why images built by Docker can also run under other compatible runtimes like Podman or containerd.