Docker is a containerization platform that packages an application with its dependencies so it runs identically across environments. That portability is what makes the packaged unit the default format for modern web applications: the same artifact moves from a developer's laptop to a staging server to a cloud cluster without modification. What looks like a simple idea carries enough depth to trip up teams that try to skip the fundamentals, so the sections below build that foundation in order, from the runnable-package model itself through to the production patterns that make container orchestration practical.
What Containers Actually Are
A container is a runnable instance of an image: it has its own isolated filesystem, networking, and process tree, but shares the host operating system kernel rather than emulating separate hardware (Docker documentation: Run containers). That shared-kernel design explains why these units start in milliseconds where virtual machines take seconds or minutes. Four terms anchor everything else in the ecosystem, and keeping them distinct prevents the most common beginner confusion.
- Image
- A read-only, layered blueprint that bundles an application, its runtime dependencies, environment variables, and filesystem layout. Images are immutable; running one produces a container, not a modified image.
- Container
- A live process spawned from an image. Each instance gets its own isolated filesystem and network interface, but shares the host kernel. Stop one and its writable layer disappears unless you commit or mount a volume.
- Dockerfile
- A plain-text file of sequential build instructions (FROM, RUN, COPY, CMD, and so on). The engine reads this file top to bottom and converts each instruction into an image layer. Changing one line only invalidates layers below it, so builds stay fast.
- Registry
- A server-side store for images. Docker Hub is the default public registry; teams use private registries on AWS, GCP, or Azure to keep proprietary images internal. Pulling an image means downloading its layers from a registry to the local machine.
Understanding the image-to-instance relationship also clarifies how these packaged apps integrate with infrastructure at the edge. The how content delivery networks improve web performance explainer covers the complementary layer: CDNs sit in front of the workload to cache static assets and reduce origin load, while the running process handles dynamic application logic.
How Docker Builds and Runs Images

Docker turns a Dockerfile into a container image by executing each instruction as a layer, then caches those layers so subsequent builds only rebuild what changed (Docker: Get Started). The layer cache is one of the engine's most practical features for web teams: a Node.js app that installs 200 packages only re-runs npm install when package.json changes, not on every code edit. The desktop app gives teams the build and run toolchain in a single installer, so there is no need to configure a Linux environment manually.
The build-and-run workflow follows five steps in practice:
- Write the Dockerfile. Start with a base image (e.g.,
FROM node:lts-alpine), copy application source, install dependencies, and declare the startup command withCMD. - Build the image. Run
docker build -t my-app:latest .from the directory containing the Dockerfile. The engine executes each instruction in order, producing a tagged container image stored locally. - Tag for the registry. Apply a registry-qualified tag (
docker tag my-app:latest registry.example.com/my-app:latest) so the push command knows the destination. - Push to a container registry. Run
docker push registry.example.com/my-app:latest. The image layers upload to the registry and become available for any host with pull access. - Run the image. On any machine with the engine installed,
docker run -p 3000:3000 registry.example.com/my-app:latestpulls the image (if not cached locally) and starts a workload with port 3000 mapped to the host.
Docker Desktop includes a GUI that shows running workloads, their logs, and resource consumption, which is useful during the early stages before teams adopt a monitoring stack. For teams on Mac or Windows, the app also handles the Linux VM that the runtime requires underneath, so the experience is transparent.
Where Kubernetes Fits In
Kubernetes takes over when a single host is no longer enough: it schedules workloads across a cluster of nodes, automatically restarts failed pods, and rolls out updates without downtime. This is what container orchestration means in practice: a control plane that continuously reconciles the desired state you declare (say, five replicas of a web server) with the actual state running in the cluster. When a node crashes, the orchestrator reschedules its pods elsewhere without manual intervention.
Four Kubernetes objects cover most of what a web team needs to understand at the start. For teams evaluating whether to deploy containers across regions or closer to users, the edge computing vs cloud computing comparison is a useful parallel decision.
- Pod
- The smallest schedulable unit in Kubernetes. A pod wraps one or more containers that share network and storage, and always run on the same node. In most cases a pod contains exactly one application container. Kubernetes restarts a pod automatically if it exits or becomes unhealthy.
- Deployment
- A controller that declares how many pod replicas should run and what image they should use. Deployments manage rolling updates: when you push a new image tag, the cluster gradually replaces old pods with new ones, keeping a configurable minimum number in service throughout.
- Service
- A stable network endpoint that routes traffic to a set of pods. Because pod IP addresses change when pods restart or reschedule, a Service provides the fixed DNS name and load balancing that clients connect to instead of addressing pods directly.
- Ingress / Gateway
- An API object that exposes HTTP and HTTPS routes from outside the cluster to internal Services. Ingress requires a separate Ingress controller to function; the Kubernetes project now recommends the Gateway API for new work, as it offers a more expressive and extensible model. An Ingress or Gateway resource handles SSL termination and path-based routing in one place.
Docker vs Kubernetes: When You Need Each
Docker and Kubernetes solve different problems at different scales: the former is the build and local-run tool, while the latter is the production-cluster manager that runs the images Docker produces. The confusion arises because both use the word "container" and the tooling partially overlaps at the local development stage. Docker Compose, for example, lets teams define multi-service apps in a single YAML file and run them locally, which satisfies most development and small production needs without a full cluster.
| Dimension | Docker (standalone) | Kubernetes |
|---|---|---|
| Primary role | Build images, run containers on a single host | Schedule and manage containers across a cluster of nodes |
| Scale | One server; scale limited to that host's resources | Multiple nodes; horizontal scaling across machines |
| Config format | Dockerfile + Docker Compose YAML | Kubernetes YAML manifests (Deployment, Service, Ingress) |
| Local development | Strong; Docker Desktop gives one-click setup | Available via Docker Desktop built-in cluster or kind/minikube |
| Production suitability | Works for low-traffic apps; no built-in self-healing across nodes | Purpose-built for production: self-healing, rolling updates, load balancing |
The common pattern for growing web teams: start with the engine alone, add Docker Compose when the app needs a database or cache alongside it, and migrate to Kubernetes when the team needs self-healing, multi-node scaling, or zero-downtime rolling update automation. Jumping to a full Kubernetes cluster for a two-service app adds operational overhead without proportional benefit.
Getting Started: Local Setup for Web Teams

Docker Desktop is the fastest on-ramp for web teams: a one-click installer for Mac, Linux, or Windows that ships the runtime, a GUI for managing workloads, and a built-in single-node Kubernetes cluster for local testing (Docker Desktop documentation). Installing the app removes the need to configure a daemon manually on Mac or Windows, since the tool handles the underlying Linux VM transparently.
The following six steps take a web team from zero to a running pod on a local Kubernetes cluster:
- Install Docker Desktop. Download the installer from
docs.docker.com/desktop/and run it. After launch, confirm the Docker daemon is active by runningdocker infoin a terminal. - Run your first workload. Execute
docker run hello-world. The engine pulls thehello-worldimage from Docker Hub, starts an instance, prints a confirmation message, and exits. This confirms the runtime is working correctly. - Write a Dockerfile for your app. In your project root, create a Dockerfile that starts from an appropriate base image, copies source files, installs dependencies, and sets a CMD entry point.
- Build a custom image. Run
docker build -t my-app:local .. Test it locally withdocker run -p 8080:8080 my-app:localand confirm the app responds onlocalhost:8080. - Enable the built-in Kubernetes cluster. In Docker Desktop, go to Settings, then Kubernetes, and toggle "Enable Kubernetes." The app provisions a single-node cluster and installs
kubectlconfigured to talk to it. - Deploy a pod to the local cluster. Create a minimal Deployment manifest pointing to your local image, then apply it with
kubectl apply -f deployment.yaml. Runkubectl get podsto confirm the pod starts. Expose it inside the cluster with a Service manifest and test withkubectl port-forward.
Production Patterns Worth Knowing Early
Even before your first production deployment, three Kubernetes patterns will shape how you architect your application: rolling updates, load-balanced Services, and a private container registry. Learning them during local development avoids painful retrofits later. For context on how horizontal scaling decisions interact with infrastructure design, the load balancing and auto-scaling tradeoffs comparison covers the relationship between these two approaches in detail.
- Rolling updates via Deployments. A Kubernetes Deployment replaces pods incrementally during a rolling update rather than stopping all instances at once. Configure
maxUnavailableandmaxSurgeto control how aggressive the rollout is. If the new pods fail their readiness checks, the rollout pauses automatically, protecting live traffic. - Readiness and liveness probes. A readiness probe tells Kubernetes when a pod is ready to receive traffic; a liveness probe tells it when the pod should be restarted. Without these, the cluster routes requests to pods that are still initializing or stuck in an error loop. Define both in every production Deployment.
- Resource limits. Setting CPU and memory limits on each container prevents one pod from starving neighboring pods on the same node. Requests (the guaranteed allocation) and limits (the ceiling) are declared per-container in the Deployment spec. Omitting limits on a shared cluster invites noisy-neighbor problems.
- Private container registry. Public registries like Docker Hub impose rate limits and expose your images publicly by default. A private container registry (hosted on the same cloud as your cluster) keeps proprietary images internal, avoids pull-rate throttling, and places the registry on the same network backbone as the cluster for faster pulls during scaling events.
- Namespace separation. Kubernetes namespaces partition a cluster into logical environments. Running staging and production workloads in separate namespaces (or, for stronger isolation, separate clusters) prevents misconfigured RBAC policies from allowing a staging deployment to affect production resources. Load balancing across environments also becomes easier to reason about when namespace boundaries are explicit.
References
- Docker Documentation: Get Started
- Docker Documentation: Get Started Workshop
- Docker Documentation: Docker Desktop
- Docker Documentation: Run Containers
- Kubernetes Documentation: Ingress
Further reading
Frequently Asked Questions
Does Docker replace virtual machines?
No. Docker containers share the host OS kernel and are isolated processes, not full VMs. They start in milliseconds and consume far less memory than a traditional VM, but they rely on a compatible host runtime rather than emulating hardware.
Do I need Kubernetes if I only run one or two containers?
No. A single-server setup or Docker Compose handles one or two containers without the overhead of a cluster orchestrator. Kubernetes becomes worthwhile when you need automatic restarts, rolling deployments across multiple nodes, or horizontal scaling beyond what one server can deliver.
Can Docker and Kubernetes work together?
Yes. Docker builds and packages the container image; Kubernetes schedules and manages those images at scale. Docker Desktop also ships with a built-in single-node Kubernetes cluster, making it easy to test both tools on a local machine before deploying to a cloud cluster.
What is a container image versus a running container?
An image is a read-only blueprint that includes the application, its dependencies, configuration, and runtime. A container is a live, running instance created from that image. Multiple containers can run from the same image simultaneously, each with its own isolated filesystem and network.









