{"post":{"slug":"containers-explained-2026","title":"Containers explained in 2026","excerpt":"Containers are the default unit of deployment in 2026. This guide explains how they work, when to use them, and how to keep images small and secure.","category":"code","date":"February 20, 2026","author":"ByteLedger Team","content":"<span class=\"dropcap\">C</span>ontainers solved the \"works on my machine\" problem that plagued software deployments for decades. By bundling an application with its exact runtime dependencies into a portable image, containers make deployment deterministic — the same image that passes CI is exactly what runs in production. In 2026, containers are not a trend; they are the default.\n\n## What changed in 2026\n\n- **Rootless by default.** Docker Desktop 4.x and Podman 5 run containers as non-root out of the box. Security-sensitive teams moved to Podman or rootless Docker entirely.\n- **BuildKit is the only builder.** The legacy Docker builder is deprecated; BuildKit enables parallel builds, cache mounts, and secrets that never land in image layers.\n- **OCI images everywhere.** The Open Container Initiative image spec means images built with Docker, Podman, Kaniko, or Buildah are interchangeable.\n- **WebAssembly as a container alternative.** WASM modules run in `wasmtime` or `wasmedge` with sub-millisecond cold starts for short-lived workloads — not containers, but worth knowing.\n\n## Containers vs virtual machines\n\n| Dimension | Container | Virtual Machine |\n| --- | --- | --- |\n| Startup time | Milliseconds | Seconds to minutes |\n| Size | MBs | GBs |\n| Isolation | Process + namespace | Full kernel |\n| Overhead | Minimal | ~10–20 % CPU/memory |\n| Use case | App deployment, CI | Full OS isolation, legacy apps |\n\nContainers share the host kernel; VMs run their own. The trade-off is startup speed and density vs stronger isolation.\n\n## How containers work\n\nA container is a Linux process isolated using three kernel primitives:\n\n- **Namespaces** — isolate the process's view of the system (PID, network, filesystem, users).\n- **cgroups** — limit and account for CPU and memory usage.\n- **Union filesystems (overlay)** — layer read-only image layers under a writable container layer.\n\nWhen you run `docker run nginx`, Docker unpacks the nginx image layers, creates namespaces and cgroups, and starts the nginx process inside that environment.\n\n## Multi-stage builds\n\nThe most impactful optimisation for production images:\n\n```dockerfile\n# Stage 1: build\nFROM node:22-alpine AS builder\nWORKDIR /app\nCOPY package*.json ./\nRUN npm ci\nCOPY . .\nRUN npm run build\n\n# Stage 2: production — only the output\nFROM node:22-alpine AS runner\nWORKDIR /app\nENV NODE_ENV=production\n\n# Non-root user\nRUN addgroup -S app && adduser -S app -G app\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/node_modules ./node_modules\nUSER app\n\nEXPOSE 3000\nCMD [\"node\", \"dist/index.js\"]\n```\n\nThis pattern strips build tools, dev dependencies, and source files — typical Node.js images shrink from ~1.2 GB to ~120 MB.\n\n## Image size comparison\n\n| Base image | Approximate size | Use case |\n| --- | --- | --- |\n| `ubuntu:24.04` | ~80 MB | Debugging, legacy scripts |\n| `node:22` | ~1.1 GB | Avoid in production |\n| `node:22-alpine` | ~170 MB | Most Node apps |\n| `node:22-slim` | ~240 MB | When Alpine glibc causes issues |\n| `gcr.io/distroless/nodejs22` | ~90 MB | Maximum security |\n| Scratch + static binary | ~5–20 MB | Go, Rust production binaries |\n\n## Security baseline in 2026\n\n```dockerfile\n# 1. Pin exact versions — never use :latest\nFROM node:22.4.1-alpine3.20\n\n# 2. Run as non-root\nRUN addgroup -S app && adduser -S app -G app\nUSER app\n\n# 3. Read-only root filesystem (set at runtime)\n# docker run --read-only --tmpfs /tmp myimage\n\n# 4. No secrets in layers — use BuildKit secrets\nRUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci\n```\n\nScan images with `docker scout`, `trivy`, or `grype` in CI before pushing to registry.\n\n## How to pick\n\n1. **Deploying any server workload?** → Container. Full stop.\n2. **Need full OS isolation (legacy app, kernel modules)?** → VM or bare metal.\n3. **Running short-lived functions?** → Container, but consider Lambda/Cloud Run to avoid managing the runtime.\n4. **Want the fastest possible cold start (<1 ms)?** → Look at WASM for stateless compute.\n5. **Building locally?** → Docker Compose for multi-service dev stacks.\n\n## Common mistakes\n\n**Using `:latest` tags.** Latest is not pinned — a base image update can silently change your runtime. Pin versions (`node:22.4.1-alpine3.20`).\n\n**Copying `.env` and secrets into the image.** Secrets baked into layers are readable by anyone with pull access. Use BuildKit secrets, environment variables at runtime, or a secrets manager.\n\n**Installing tools in production images.** `curl`, `git`, `vim` have no place in a production image. They increase attack surface and size.\n\n**Not setting resource limits.** A container without CPU/memory limits can starve its neighbours on shared infrastructure. Always set `--memory` and `--cpus` (or Kubernetes `resources.requests/limits`).\n\n## What to skip\n\n- **`docker-compose` in production** — it lacks health-check-driven orchestration and auto-restart policies that Kubernetes or Nomad provide.\n- **Building images as root** — rootless builds are secure by default and required in many enterprise environments.\n- **Fat images with full OS shells** for debugging — use ephemeral debug containers (`kubectl debug`) instead of baking shells into every image.\n\n## FAQ\n\n**What is the difference between an image and a container?**\nAn image is the read-only template (like a class). A container is the running instance (like an object). You can run many containers from the same image.\n\n**Do I need Kubernetes to use containers?**\nNo. Docker Compose, AWS ECS, Fly.io, Railway, and Render all run containers without Kubernetes. Use Kubernetes when you need auto-scaling, rolling deployments, and self-healing across many nodes.\n\n**How do I share data between containers?**\nUse named Docker volumes for persistent data, or bind mounts for development. For production, prefer managed storage (S3, Cloud SQL) outside the container entirely.\n\n**What is containerd and how does it relate to Docker?**\ncontainerd is the low-level container runtime that Docker uses internally. Kubernetes dropped the Docker shim and talks to containerd directly. You rarely interact with containerd unless you are building a platform.\n\n## Where to go next\n\n- [How to containerize an app in 2026](/blog/how-to-containerize-an-app-2026)\n- [How to reduce Docker image size in 2026](/blog/how-to-reduce-docker-image-size-2026)\n- [Virtual machines explained in 2026](/blog/virtual-machines-explained-2026)","hue":305,"metaTitle":"Containers Explained in 2026: Docker, Builds, Security","metaDescription":"2026 guide to containers: how they work, multi-stage Docker builds, image security, Kubernetes basics, and when containers are the right choice.","keywords":["containers explained 2026","docker containers 2026","container technology 2026","docker image optimization 2026","multi-stage docker build 2026","container security 2026","kubernetes containers 2026","containerize an app 2026","docker vs virtual machine 2026","container best practices 2026"],"tldr":["**A container packages code + dependencies** into an isolated, reproducible unit that runs the same everywhere.","**Docker is still dominant** for building images; containerd is the default runtime in Kubernetes clusters.","**Multi-stage builds** cut image sizes by 60–90 % — never ship your build tools to production.","**Rootless containers** and read-only filesystems are the 2026 security baseline — not optional.","**Skip:** running a container per function if you can run multiple workloads in one; over-isolation wastes resources and adds cold-start latency."],"readTime":"5 min read","wordCount":992},"related":[{"slug":"how-to-containerize-an-app-2026","title":"How to containerize an app in 2026: Docker, layers, and production-ready images","excerpt":"Containerizing an app is now a baseline skill for every backend developer. This guide covers Dockerfiles, multi-stage builds, and production best practices.","category":"code","date":"April 14, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":310},{"slug":"how-to-write-a-dockerfile-2026","title":"How to write a Dockerfile in 2026: lean, fast, and secure","excerpt":"A bad Dockerfile ships a 2 GB image with root access and no layer cache. This 2026 guide shows you how to write lean, secure, production-ready Dockerfiles.","category":"code","date":"April 20, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":310},{"slug":"how-to-reduce-docker-image-size-2026","title":"How to reduce Docker image size in 2026","excerpt":"Bloated Docker images slow pull times, increase attack surface, and cost more in registry storage. This guide covers the concrete techniques that actually shrink them in 2026.","category":"code","date":"February 26, 2026","author":"ByteLedger Team","readTime":"5 min read","hue":312}],"sameCategory":[{"slug":"bazel-build-explained-2026","title":"Bazel Explained: What Hermetic Builds Actually Cost","excerpt":"Bazel delivers reproducible, precisely cached builds and demands that you describe everything. Here is what you get, what it costs, and who should say no.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":145},{"slug":"graphql-federation-2026","title":"GraphQL Federation: One Graph, Many Teams","excerpt":"Federation composes independently-owned subgraphs into a single API. Here is what it solves, the operational cost it adds, and when a simpler gateway is enough.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":300},{"slug":"hermetic-builds-explained-2026","title":"Hermetic Builds Explained: Same Inputs, Same Output","excerpt":"A hermetic build depends only on declared inputs. Here is what that property gives you, the common leaks that break it, and how to move toward it incrementally.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":130},{"slug":"monorepo-tooling-compared-2026","title":"Monorepo Tooling Compared: What You Actually Need","excerpt":"Monorepo tools solve task orchestration and caching, not repository layout. Here is what each tier provides and how to tell when you have outgrown the simple option.","category":"code","date":"August 19, 2026","author":"ByteLedger Team","readTime":"3 min read","hue":150}],"newer":{"slug":"ci-cd-pipeline-basics-2026","title":"CI/CD pipeline basics in 2026: build, test, and deploy without fear","excerpt":"A well-designed CI/CD pipeline turns deploys from a stressful event into a boring routine. Here is the 2026 baseline every engineering team needs.","category":"code","date":"February 20, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":314},"older":{"slug":"credit-union-vs-bank-2026","title":"Credit union vs bank in 2026: which one is better for your money","excerpt":"Credit unions and banks both hold your deposits and offer loans, but the ownership model and fee structure differ meaningfully. In 2026, here is how to decide which is better for you.","category":"finance","date":"February 20, 2026","author":"ByteLedger Team","readTime":"4 min read","hue":278}}