Docker packages an application with everything it needs into a read only image, and runs that image as an isolated process on the host kernel rather than inside its own operating system. Nothing boots, so a container starts in milliseconds and costs a fraction of the memory a virtual machine does.
- An image is what you build
- A container is one running instance of it
- Isolation comes from namespaces and cgroups
- The kernel is shared, never shipped
- Open source since 2013
On this page
- The problem Docker was built for
- Images, containers, and the difference people trip on
- What actually does the isolating
- What Docker is made of
- The pieces you will actually touch
- Where containers actually run
- The commands worth knowing
- Where it goes wrong
- Docker Desktop, and the part that reaches finance
- Is Docker still the answer
- Comparison
- FAQ
Why it existsThe problem Docker was built for
Software that works on one machine and fails on another is the oldest complaint in the trade, and the cause is almost always the same.
The application depends on things that are not the application: a library version, an environment variable, a locale, a path, a package installed years ago by someone who has left. The code moves between machines. Everything around it does not.
The traditional answer was a virtual machine, which carries the whole operating system along with the application so nothing is left behind. It works, and it is heavy.
Each virtual machine boots a kernel, runs its own init system, its own logging, its own package manager and its own scheduled tasks, and reserves memory for all of it whether the application needs it or not.
Docker takes the other route. Ship the application and everything above the kernel, and borrow the kernel from the host. The application, its libraries and its files travel together in the image. The kernel does not travel at all, because every Linux machine already has one.
That single decision explains every property people notice about Docker containers. Docker containers start fast because nothing boots. They are small because the operating system is not inside them. They are dense because a host runs hundreds instead of dozens.
And they are limited to the kernel they borrow, which is why a Linux container needs a Linux kernel and why Docker on Windows or a Mac quietly runs a Linux virtual machine to provide one.
FundamentalsImages, containers, and the difference people trip on
The two words are used interchangeably in conversation and mean different things, which makes half the documentation confusing until the distinction lands.
A Docker image is a build artifact. It is read only, it has an identity you can pin, and it does not run. It is closer to an installer or a disk image than to a program.
A Docker container is an image that has been started. It gets a writable layer on top, a process, a network interface and a lifetime. Stop it and the writable layer goes with it unless you arranged otherwise. Start ten containers from one image and you have ten independent processes sharing one read only stack underneath.
The relationship is the one between a class and an object, or between a recipe and a meal. You build an image once and run it anywhere, many times.
Layers, and why builds are fast the second time
An image is not one blob. It is a stack of layers, each one the filesystem change made by a single build step, stacked so the top layer wins.
Two Docker images that start from the same base share those layers on disk and over the network, which is why pulling a second image from the same base downloads almost nothing.
The same stacking makes builds fast and makes badly ordered builds slow. Docker caches each layer and reuses it while the step that produced it has not changed. Copy your source code in before installing dependencies, and every code change invalidates the dependency layer and reinstalls everything.
Install dependencies first and copy the code last, and a code change rebuilds one small layer. This is the single most common performance mistake in a Dockerfile and it is entirely an ordering problem.
The kernelWhat actually does the isolating
Nothing in a container is emulated. The isolation is a set of features the Linux kernel already had, which Docker configures on your behalf.
Namespaces decide what a process can see. A process in its own PID namespace sees itself as process 1 and cannot see the host's processes. Its own mount namespace gives it a different root filesystem. Its own network namespace gives it its own interfaces, routing table and ports. There are namespaces for hostnames, users and inter-process communication as well.
Control groups decide what a process can use. They cap memory, CPU shares, block device throughput and the number of processes, and they are what stops one container from starving the rest of the machine.
A layered filesystem gives each container its own writable view over the shared read only image without copying it.
Put those three together and you have a process that believes it has a machine to itself, running directly on the host kernel with no hypervisor in the path. That is the whole trick, and it is why the performance overhead of a container is close to zero and the isolation is weaker than a virtual machine's.
ArchitectureWhat Docker is made of
Typing a Docker command does not start a container. It sends a request.
The Docker client is the command you type. It speaks a REST API and does no work itself, which is why the same command can drive a container on your laptop or on a machine across the network by pointing it somewhere else.
The Docker daemon, the background service called dockerd, receives those requests and does the work: building images, managing networks and volumes, and telling a runtime to start containers. It listens on a socket, and access to that socket is effectively root on the host, which is the single most important sentence in Docker's security model.
containerd is the container runtime the daemon delegates to. It manages the container lifecycle and pulls images, and it is a separate project with its own standard interface.
runc is the piece at the bottom that actually asks the kernel for the namespaces and control groups. It is small on purpose.
Docker Hub is the default registry, the public place images are published to and pulled from. A company usually runs a private registry instead, or as well.
Two things follow from that stack. Docker is not one program, so replacing the top of it changes nothing underneath, which is exactly what happened when Kubernetes stopped talking to dockerd and started talking to containerd directly.
And because the daemon runs as root and hands out its socket, anyone who can reach that socket can own the host. Rootless mode exists for this reason, and so does the family of tools that run the same images without a daemon at all.
DetailThe pieces you will actually touch
A Dockerfile is the recipe. Each line is a build step and each build step becomes a layer. It names a base image, copies files, installs things and declares the command to run.
The build turns that recipe into an image and tags it with a name and a version.
A registry stores Docker images so other machines can pull them. Docker Hub is the public one, and every cloud provider runs its own, but most companies also keep a private registry for software they do not publish.
Docker Compose describes several containers that belong together, in one file: the application, its database, its cache, the network between them and the volumes they keep. It is how most people manage a multi service application on a single host. It is what turns a single container into something resembling an environment, and it is where most small deployments stop.
A volume is storage that outlives the container. Anything written inside a container disappears when it is replaced, which is correct behavior and a surprise the first time a database is lost to it.
In productionWhere containers actually run
Building an image is the easy half. Deciding what runs it is where the choice is, and the options form a ladder rather than a menu.
One host, one container. A Docker daemon on a server, started by hand or by a systemd unit. This is fine, and it is how a great many internal tools run. It has no answer for the machine dying.
One host, several containers. Docker Compose, describing the application and its services in one file. Still one machine, still no answer for that machine dying, but the environment is now written down and reproducible.
A cluster you run. Kubernetes, or Red Hat OpenShift, which is Kubernetes with a vendor's opinions and a support contract attached. These schedule containers across machines, restart what dies, and roll out new versions gradually. They also add a whole platform to operate, which is worth it above a certain size and expensive below it.
A cluster you rent. The managed services do the scheduling and hand you an endpoint. AWS runs ECS and Fargate, Google Cloud Run takes an image and gives back a URL, Azure has Container Apps. You give them an image and they run it, which for most applications is the shortest honest path to production.
The judgement to make is not which is best. It is how much platform you are willing to operate.
A team that adopts Kubernetes for three services has bought a second full time job, and a team that stays on one host with Compose has accepted that the host is a single point of failure. Both are defensible; drifting into either without saying so is not.
CommandsThe commands worth knowing
The Docker client has a large surface and a small center. These eight cover most of what anyone types in a normal week, and each one is worth understanding rather than copying.
docker run -d -p 8080:80 --name web nginx start a container in the background
docker ps what is running, and on which ports
docker ps -a including what stopped, and why
docker logs -f web follow the output of one container
docker exec -it web sh open a shell inside a running container
docker build -t myapp:1.4 . build an image from the Dockerfile here
docker compose up -d start everything described in the compose file
docker system prune -a reclaim disk from stopped containers and unused images
Three of those deserve a note.
docker run is doing more than it looks. It pulls the image if it is missing, creates a container, connects it to a network, publishes ports and starts the process, and any of those steps can be the one that fails. When a container will not start, read the error for which stage it reached.
docker exec opens a shell in a container that is already running, and it is the right tool for looking. It is the wrong tool for fixing, because anything you change there is gone at the next deployment. If the fix belongs anywhere, it belongs in the Dockerfile.
docker system prune reclaims real disk, and the version with the flag removes images nothing is using rather than only dangling ones. Docker accumulates layers quietly, and a host that ran out of disk with no obvious cause has usually been building images for a year.
PitfallsWhere it goes wrong
Treating a Docker container like a small server. Containers are meant to be replaced, not maintained. If you log into one to fix something, the fix is gone at the next deployment. The change belongs in the image.
Losing data to the container writable layer. Databases, uploads and logs need a volume or an external service. Without one they live in a layer that is discarded on every update.
Docker images that are mostly operating system. A base image chosen without thought carries a package manager, a shell and hundreds of libraries the application never calls, and every one of them is something to patch. A smaller base is smaller to ship and smaller to defend.
Running everything as root. By default the process inside a container runs as root, and root inside a container is closer to root outside it than most people assume. A user directive in the Dockerfile costs one line.
Secrets baked into the image. An environment variable set at build time is in the image layers forever, readable by anyone who can pull it. Secrets belong at run time, from the platform.
LicensingDocker Desktop, and the part that reaches finance
Docker the technology is open source. Docker the company sells the tooling around it, and the line between the two is where budgets get surprised.
Docker Engine, the daemon and runtime on a Linux server, is free and open source. Nothing about running containers in production requires paying anyone.
Docker Desktop, the application developers install on Windows and macOS, is not free for everyone. It requires a paid subscription for larger companies, on a threshold measured by employee count and revenue, and the license covers the person rather than the machine.
A company that grew past the threshold is out of compliance from that day whether or not anyone noticed, and nothing in the software stops working to tell them.
The practical shapes this takes:
- Small companies keep using Docker Desktop free of charge and are fine
- Larger companies buy seats, which is a real per developer line item
- Some replace Desktop with alternatives that run the same images, since the format is a standard and nothing about the images changes
- Servers are unaffected either way, because Docker Engine on Linux was never the licensed part
Worth checking before an audit rather than during one. It is one of the few pieces of open source technology where the developer laptops are the licensed surface and the production servers are not.
TodayIs Docker still the answer
The word has come to mean two things, and only one of them is still the default.
The container format won completely. Docker images are an open standard now, and everything from a laptop to a managed cloud service can run one without asking who built it.
The Docker runtime has more competition than it did. Kubernetes dropped direct support for the Docker daemon in favor of smaller runtimes that implement the same standard, and tools like Podman run the same images with no daemon at all. None of that changes the image you built.
For a single machine, or a developer laptop, Docker with Compose is still the shortest path from nothing to a running environment, and it is what most small cloud deployments run. For a cluster, the thing that schedules containers is usually not Docker, and the images are the same either way.
ComparisonA container and a virtual machine, property by property
| Criterion | Container | Virtual machine |
|---|---|---|
| What it virtualizes | The operating system, one kernel shared | The hardware, each guest boots its own kernel |
| Start time | Milliseconds | Tens of seconds |
| Size on disk | Tens to hundreds of megabytes | Gigabytes |
| Memory cost | Only what the process uses | The guest operating system, whether used or not |
| Density on one host | Hundreds | Dozens |
| Isolation strength | A kernel bug reaches the host | A hypervisor is a much smaller surface |
| Running a different operating system | No, the kernel is shared | Yes, that is the point |
| Best fit | One application and its dependencies | A whole machine, or an untrusted workload |
They solve overlapping problems and fail differently, so the honest comparison is per property rather than a winner. The row that matters for a decision is isolation. Containers share a kernel, so a kernel vulnerability is a path from one container to the host and to every other container.
That is acceptable for your own applications and a poor choice for running code you do not trust. This is why cloud providers run customer containers inside virtual machines rather than side by side on bare metal.
FAQFrequently asked questions
What is Docker in simple terms?
Docker is a way to package an application with all the software it needs into one file, and run that file as an isolated process on any machine with a compatible kernel.
What is the difference between an image and a container?
An image is the read only package and does not run. A container is a running instance of an image, with a writable layer and a lifetime of its own.
Is Docker a virtual machine?
No. A virtual machine emulates hardware and boots its own kernel, and Docker Engine does neither. A container is a normal process on the host kernel, fenced off with namespaces and control groups.
Why are containers so much faster to start?
Because nothing boots. Starting a container is starting a process, and the operating system is already running.
Does Docker work on Windows and macOS?
Yes, by running a small Linux virtual machine in the background to supply the kernel the containers need. Windows containers on Windows hosts are a separate thing and less common.
Do I need Kubernetes to use Docker?
No. Kubernetes schedules Docker containers across many machines and is worth its complexity at that scale. One machine needs Docker and Compose, and a managed cloud service needs neither.
Is a Docker container secure?
It is isolated, which is not the same. A container shares the host kernel, so it is a weaker boundary than a virtual machine, and it is the wrong boundary for code you do not trust.
What happens to data written inside a container?
It goes into the writable layer and disappears when the container is replaced. Anything that must survive needs a volume or an external service.
What is a Dockerfile?
The text file describing how to build an image: the base to start from, the files to copy, the commands to run and the process to start.
Why is my build slow every time?
Almost always the order of steps. Copying source code before installing dependencies invalidates the dependency layer on every code change. Install first, copy last.
Should I run one process per container?
As a default, yes. One process makes restarts, logs and health checks mean something. Bundling several turns the container into a small server, which is the thing containers exist to avoid.
Is Docker free for commercial use?
Docker Engine on a server is free and open source. Docker Desktop on a developer machine requires a paid subscription above a company size threshold, which is the part that surprises people.
How does this relate to a hypervisor?
A hypervisor sits under a whole guest operating system. A container runtime sits beside your process on a kernel that is already running. They are different layers and are routinely used together.
Keep readingRelated concepts
Read next · Identity and access What Is MFA? Access to the Docker socket is root on the host, so who reaches it is an identity question. Open this next16 min- Addressing · 15 min What Is a Subnet? Container networking is bridges and address ranges, which is what a subnet is.
- Operations · 11 min What Is a Cron Job? A container has no cron by default, and adding one is usually the wrong answer.
- Hypervisors · 11 min Hyper-V vs VMware The hypervisors underneath, when a container is not the right unit.
- Containers · 11 min Containers vs VMs How containers compare with the virtual machines they usually run inside.
- Hypervisors · 10 min Type 1 vs Type 2 Hypervisor What Docker runs inside on a Mac or a Windows machine, which is a hypervisor either way.
- Platforms · 12 min Open Source Operating Systems, and Where the Cost Actually Goes Where you are running it without having chosen to.