Introduction to Docker

By Vishvesh Patel · DevOps EngineerUpdated September 15, 2026

What Docker is and the problem it solves. Images versus containers, how containers differ from virtual machines, the core workflow, and when not to use it.

Docker packages an application together with everything it needs to run, the runtime, the libraries, the system tools, the configuration, into a single artifact that behaves the same wherever it runs.

That is the whole pitch, and it addresses a problem every team has had.

The problem

An application works on a developer's laptop and fails in staging. The cause is invariably an environment difference: a different Python version, a missing system library, a config file somewhere else, a locale setting nobody thought about.

The traditional fixes were documentation nobody kept current, configuration management that drifted, or a virtual machine image that was tens of gigabytes and slow to build.

Docker's answer is to ship the environment with the application. If it runs in the container on your laptop, it runs in the same container in production, because it is the same container.

Images and containers

The distinction people most often blur, and everything else depends on it.

ImageContainer
What it isA read-only templateA running instance of an image
AnalogyA classAn object
StateImmutableHas a writable layer
CountOne imageMany containers from it
docker pull nginx:1.27        # fetch an image
docker run -d nginx:1.27      # create and start a container from it
docker run -d nginx:1.27      # and another, from the same image

Images are built in layers, each the result of an instruction in the Dockerfile. Layers are cached and shared. Ten images based on the same Ubuntu layer store that layer once. This is why images are far smaller in practice than their nominal sizes suggest, and why ordering Dockerfile instructions well makes rebuilds fast.

How this differs from a virtual machine

A VM virtualises hardware and runs a full guest operating system. A container shares the host kernel and isolates only the process.

ContainerVirtual machine
IsolationProcess-level, shared kernelFull hardware virtualisation
Start timeMillisecondsTens of seconds
SizeMegabytesGigabytes
Density per hostHundredsTens
KernelShared with hostIts own
Isolation strengthGoodStronger

Two consequences worth knowing. Containers cannot run a different kernel. Linux containers on macOS or Windows actually run inside a small Linux VM that Docker Desktop manages, which is why file sharing between host and container is slower on those platforms. And because isolation is weaker than a VM's, running genuinely untrusted code deserves a stronger boundary.

The workflow

# 1. Write a Dockerfile describing the image
# 2. Build it
docker build -t myapp:1.0 .

# 3. Run a container
docker run -d -p 8080:80 --name web myapp:1.0

# 4. Look at what is happening
docker ps
docker logs web

# 5. Clean up
docker stop web && docker rm web

A minimal Dockerfile:

FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]

The ordering there is deliberate and worth noticing early. Dependencies are copied and installed before the application code, so a change to your source does not invalidate the cached npm ci layer. Reversing those two lines makes every build reinstall everything, which is the single most common Dockerfile performance mistake.

The pieces

Docker Engine is the daemon that builds images and runs containers. The CLI talks to it over a socket, which is why docker commands work against a remote host just as easily as a local one.

A registry stores images. Docker Hub is the default; ECR, GCR, GitHub Container Registry and self-hosted registries all work the same way.

A volume persists data beyond a container's life. Anything written to a container's own filesystem disappears when it is removed, which surprises people exactly once.

A network lets containers reach each other. Containers on a user-defined network resolve each other by name, which is how multi-container applications are wired together.

Containers are disposable

This is the mental shift that makes Docker click.

A container is not a small server you log into and maintain. It is a process you replace. Configuration comes from environment variables, data lives in volumes or a database, and logs go to stdout, so that destroying and recreating the container loses nothing.

Treating containers as long-lived pets, SSHing in, installing packages, editing files, produces exactly the environment drift Docker exists to eliminate.

Where Docker is not the answer

Worth stating, because it is frequently applied by default:

  • Desktop GUI applications. Possible, awkward, rarely worth it.
  • Workloads needing a specific kernel or kernel modules. Containers share the host kernel.
  • Genuinely untrusted multi-tenant code, where a VM or something like Firecracker gives a stronger boundary.
  • A single simple application on one server that is working fine. Containerising it adds a layer for no gain.

Where to go next

TopicWhat you will learn
Why Use DockerThe practical benefits in more depth
Docker vs Virtual MachinesThe architectural difference
Installing DockerSetting it up on your platform
Key ConceptsImages, containers, volumes, networks
Dockerfile BasicsBuilding your own images

Quick reference

TaskCommand
Pull an imagedocker pull <image>:<tag>
Builddocker build -t <name>:<tag> .
Run detached with a portdocker run -d -p 8080:80 --name <n> <image>
Running containersdocker ps
All containersdocker ps -a
Logsdocker logs -f <name>
Shell insidedocker exec -it <name> sh
Stop and removedocker stop <n> && docker rm <n>
Disk usagedocker system df

Key takeaways

  • An image is a template; a container is a running instance. One image, many containers.
  • Images are layered and cached, which is why Dockerfile instruction order matters so much.
  • Containers share the host kernel: far lighter than VMs, and a weaker isolation boundary.
  • Copy dependency manifests before source code so the install layer stays cached.
  • Containers are disposable. Config in environment variables, data in volumes, logs to stdout.
  • Linux containers on macOS and Windows run in a hidden VM, which is why file sharing is slower there.
  • Docker is not always the answer: a working single-server application may not need it.

Check your understanding

Exercise

Images and containers

You run docker run three times against the same image. How many images and containers now exist?

Exercise

A build that is slow every time

A Dockerfile copies all source code before running npm ci. Every build reinstalls all dependencies even when only one source file changed. Why?


Frequently Asked Questions

What is Docker used for?

Packaging an application with its runtime, libraries and configuration into a single image that runs identically anywhere Docker runs. It eliminates the "works on my machine" class of problem, since the environment ships with the application rather than being recreated at each destination. In practice it is used for local development environments, CI build and test isolation, and as the deployment unit for anything running on Kubernetes, ECS or similar platforms.

What is the difference between a Docker image and a container?

An image is a read-only template built from a Dockerfile; a container is a running instance created from that image with its own writable layer. The relationship is like a class and an object. One image can produce any number of containers, all sharing the same underlying layers and differing only in their writable layer and running state. Images are built and pulled; containers are run, stopped and removed.

How is Docker different from a virtual machine?

A VM virtualises hardware and runs a complete guest operating system with its own kernel, typically taking gigabytes and tens of seconds to boot. A container shares the host kernel and isolates only the process, so it is measured in megabytes and starts in milliseconds. That makes containers far denser and faster, at the cost of weaker isolation, and it means a container cannot run a different kernel, which is why Linux containers on macOS or Windows run inside a small managed VM.

Do I need to learn Docker before Kubernetes?

Yes. Kubernetes orchestrates containers and assumes you already understand images, containers, ports, volumes and environment variables. A large share of Kubernetes problems turn out to be container problems in disguise: a wrong entrypoint, a missing environment variable, a process writing to a path that is not persisted. Being comfortable with docker build and docker run makes the Kubernetes learning curve considerably shorter.

Why does my data disappear when a container restarts?

Because a container's writable layer is destroyed when the container is removed, and it is not preserved across docker rm and a fresh docker run. Anything that must survive belongs in a volume, mounted into the container, or in an external service such as a database. This catches nearly everyone once, and it is the practical expression of the principle that containers are disposable. Configuration comes from environment variables and data lives outside.

Is Docker always the right choice?

No. A single simple application running fine on one server gains little from containerisation and pays the cost of another layer to understand and maintain. Desktop GUI applications are awkward in containers. Workloads needing a specific kernel or kernel modules cannot use them, since containers share the host kernel. And genuinely untrusted multi-tenant code deserves a stronger boundary than a container provides. A VM or a microVM runtime such as Firecracker.

Continue Learning

Explore Related Topics

Try the Tool

Practise this in the browser

Docker Playground

Run the commands in a simulated terminal, no install needed.

When it breaks

Related Resources