Vetora logo
๐Ÿ“ฆCloud-Native

Containers & Docker

Containers package an application with its dependencies into an isolated, portable unit that runs consistently across environments. Docker popularized OS-level virtualization using Linux namespaces and cgroups, enabling sub-second startup times and near-native performance compared to traditional VMs.

Overview

Containers are a lightweight virtualization mechanism that packages application code, runtime, libraries, and configuration into a single artifact called a container image. Unlike virtual machines, containers share the host operating system kernel, eliminating the overhead of running a full guest OS. This shared-kernel model gives containers near-native performance, sub-second startup times, and a memory footprint measured in megabytes rather than gigabytes.

The technology rests on two Linux kernel primitives: namespaces and cgroups. Namespaces provide isolation -- each container gets its own view of the PID tree, network stack, mount points, and user IDs, so processes inside a container cannot see or interfere with processes in other containers or on the host. Cgroups (control groups) enforce resource limits -- CPU shares, memory caps, I/O bandwidth -- preventing a single container from monopolizing host resources. Together, these primitives create the illusion of an isolated machine without the cost of hardware virtualization.

Docker, released in 2013, made containers accessible to mainstream developers by providing a simple CLI, a declarative Dockerfile for building images, and a registry (Docker Hub) for distributing them. The container image format was later standardized as the Open Container Initiative (OCI) specification, ensuring portability across runtimes (Docker, containerd, CRI-O, Podman). A container image is a layered filesystem: each Dockerfile instruction creates a read-only layer, and layers are shared across images, dramatically reducing storage and pull times.

In modern architectures, containers are the deployment unit for microservices. Each service is built into its own image, versioned independently, and deployed without affecting other services. This enables polyglot stacks (Python ML models alongside Go APIs alongside Node.js frontends), independent scaling, and rolling deployments. However, containers introduce operational complexity: networking between containers, service discovery, secret management, log aggregation, and orchestration of thousands of ephemeral instances require tooling that did not exist in the VM era.

Key Points
  • 1Containers share the host kernel and use namespaces (PID, NET, MNT, UTS, IPC, USER) for isolation and cgroups for resource limits. This gives near-native performance with millisecond startup times.
  • 2Container images are layered filesystems. Shared layers reduce storage and network transfer -- a base image like Alpine (5 MB) is pulled once and reused across hundreds of service images.
  • 3The OCI specification standardizes image format and runtime behavior, ensuring images built with Docker run on containerd, CRI-O, Podman, or any compliant runtime.
  • 4Multi-stage builds separate build dependencies from runtime, reducing production images from 1+ GB to 10-50 MB. Smaller images mean faster pulls, smaller attack surfaces, and lower registry costs.
  • 5Container networking uses virtual bridges, veth pairs, and overlay networks (VXLAN, Geneve) to provide each container a unique IP. Kubernetes CNI plugins (Calico, Cilium) add network policies and observability.
  • 6Security hardening includes running as non-root, using read-only filesystems, dropping Linux capabilities, enabling seccomp profiles, and scanning images for CVEs in CI/CD pipelines.
Simple Example

Shipping Container Analogy

Before standardized shipping containers, cargo was loaded loose onto ships -- different shapes, sizes, and handling requirements made loading slow and error-prone. The invention of the standard 20-foot steel container in the 1950s revolutionized global trade: any cargo that fits in the container can be loaded onto any ship, train, or truck without repacking. Software containers work the same way. A Dockerfile defines the 'box' (base OS, dependencies, application code), and the resulting image runs identically on a developer's laptop, a CI server, a staging cluster, and production -- eliminating 'works on my machine' problems. The container runtime (Docker, containerd) is the 'crane' that loads, starts, and stops containers on any host.

Real-World Examples

Google

Google runs over 4 billion containers per week across its infrastructure, using Borg (the internal predecessor to Kubernetes). Every Google product -- Search, Gmail, YouTube, Maps -- runs in containers. Google's experience operating containers at this scale for over 15 years directly informed the design of Kubernetes, cgroups v2, and gVisor (a user-space kernel for stronger container isolation).

Spotify

Spotify migrated from hand-managed Debian packages to Docker containers, reducing deployment times from 30+ minutes to under 5 minutes. Each of their 2,000+ microservices ships as an independently versioned container image. Their internal platform (Backstage, now open-source) provides a standardized container build pipeline that enforces security scanning, size limits, and labeling conventions.

Capital One

Capital One containerized their banking applications to meet both agility and regulatory requirements. They run over 12,000 containers in production, using multi-stage builds to keep images minimal and immutable. Container image signing (Notary/cosign) ensures only verified images from their internal registry reach production, satisfying SOC 2 and PCI-DSS audit requirements.

Trade-Offs
AspectDescription
Containers vs. Virtual MachinesContainers start in milliseconds and use 10-100x less memory than VMs, but share the host kernel, creating a larger attack surface. VMs provide hardware-level isolation (separate kernels) at the cost of minutes-long startup and GB-scale overhead. For multi-tenant SaaS with untrusted workloads, VMs or microVMs (Firecracker) are safer; for trusted internal microservices, containers are more efficient.
Image Size vs. Developer ConvenienceFat images with full OS tools (Ubuntu, Debian) simplify debugging but increase pull times, registry costs, and CVE surface. Minimal images (Alpine, distroless, scratch) are 10-50 MB and have fewer vulnerabilities but lack debugging tools and may have musl libc compatibility issues. A common compromise is multi-stage builds: full OS for build, distroless for runtime.
Shared Host vs. Dedicated HostBin-packing many containers onto shared hosts maximizes utilization (60-80% CPU vs. 10-15% for VMs) but introduces noisy-neighbor problems and kernel-level blast radius. Dedicated hosts (or VM-per-pod models like Kata Containers) provide stronger isolation at lower density. Most organizations use shared hosts for stateless services and dedicated hosts for sensitive workloads.
Ephemeral vs. Persistent ContainersTreating containers as disposable (no local state, restart freely) simplifies orchestration and enables rolling updates. But stateful workloads (databases, caches) need persistent volumes, which couple containers to specific hosts and complicate scheduling. CSI drivers (EBS, GCE PD) enable portable persistent storage but add latency and failure modes.
Case Study

Uber's Migration from VMs to Containers

Scenario

By 2016, Uber operated over 1,000 microservices on a mix of bare-metal servers and VMs. Deployment took 30-60 minutes per service, host utilization averaged 10-15%, and each team maintained custom deployment scripts. Onboarding a new service took days of infrastructure provisioning.

Solution

Uber built an internal container platform (Peloton, later open-sourced) that standardized all microservice deployments into Docker containers orchestrated at scale. They implemented multi-stage builds to minimize image sizes, a centralized image registry with automated CVE scanning, and a resource-aware scheduler that bin-packed containers based on CPU/memory reservations. Each service defined its resource requirements in a declarative manifest, and the platform handled placement, health checks, and auto-scaling.

Outcome

Host utilization increased from 10-15% to 60-80%, saving an estimated $100M+ annually in infrastructure costs. Deployment times dropped from 30-60 minutes to under 3 minutes. New service onboarding went from days to minutes via self-service templates. The standardized container format also enabled Uber to implement fleet-wide security policies (image signing, runtime sandboxing) that were impossible with heterogeneous VM deployments.

Common Mistakes
  • โš Running containers as root. The default Docker behavior runs processes as UID 0 inside the container. A container escape vulnerability gives the attacker root on the host. Always specify USER in the Dockerfile and drop unnecessary Linux capabilities.
  • โš Using 'latest' tag in production. The 'latest' tag is mutable -- it points to whatever was pushed last. Two deployments minutes apart can get different images. Pin images to immutable digest hashes (sha256:abc123) or semantic version tags for reproducible deployments.
  • โš Storing secrets in container images. Baking API keys, database passwords, or TLS certificates into the image (via ENV or COPY) exposes them to anyone with image pull access. Use runtime secret injection via Kubernetes Secrets, Vault, or cloud-native secret managers.
  • โš Ignoring container resource limits. Without CPU and memory limits, a single misbehaving container can OOM-kill other containers on the same host. Always set resource requests (scheduling) and limits (enforcement) in your orchestrator manifests.
Related Concepts

See Containers & Docker in action

Explore system design templates that use containers & docker and run traffic simulations to see how these concepts perform under real load.

Browse Templates

Compare container startup time vs VM provisioning for e-commerce

Metrics to watch
startup_time_msmemory_overhead_mbimage_size_mbthroughput_rps
Run Simulation
Test Your Understanding

1What Linux kernel feature provides process isolation for containers?

2Why are multi-stage Docker builds recommended for production images?

Deeper Reading