July 21, 2026

The Complete Docker Guide for 2026: Containers, Dockerfile and Compose

Photo of Marco Orta Marco Orta | 15 min read
Compartir
3D illustration of a whale carrying stacked containers next to a terminal window: the complete Docker guide for 2026
Table of Contents

    Docker is the container platform that packages your application with all its dependencies into a portable unit that runs the same on your laptop, on a VPS or in the cloud. In 2026 it is no longer the “modern option” — it is the standard. According to the 2025 Stack Overflow survey, 71.1% of developers use Docker — a 17-point jump in a single year, the biggest rise of any technology surveyed — and Docker Hub serves more than 20 billion image pulls per month.

    But the Docker of 2026 is not the Docker of three-year-old tutorials: docker-compose (with a hyphen) is dead, Compose jumped to v5, Engine 29 changed its image storage backend, Docker Hardened Images became free, and you can now run AI models locally with docker model run. This guide covers everything from zero to that state of the art: what Docker is, how to write a good Dockerfile, how to use Compose today, and which new features are worth adopting.

    Docker news — August 2026 update

    I keep this guide alive month by month. What changed in the Docker world since the last revision:

    • Patch “Copy Fail” now if you haven’t (CVE-2026-31431). The most serious container story of the year: a Linux kernel flaw in the AF_ALG crypto interface (CVSS 7.8, present in kernels 4.14 through 6.19.12) lets an unprivileged process write to the page cache and escalate to root — and it works as a container escape, because Docker’s default seccomp profile used to allow AF_ALG sockets. It is being actively exploited (CISA added it to its KEV catalog in May). You are safe if you run Docker Engine 29.4.3+ (its default seccomp profile now blocks AF_ALG) or a patched kernel (6.18.22+, 6.19.12+ or 7.0+). Docker Desktop backported the kernel fix to its VM in the July 2 release.
    • Compose v5.3 added native init containers: services that run and finish before your app starts (migrations, seeds, permission fixes) declared directly in compose.yaml, no more depends_on + one-shot service hacks.
    • Docker Desktop’s July release fixed the Dashboard failing to load volumes/images/containers, containers ignoring configured stop timeouts, and startup failures on WSL2 ARM kernels.

    One takeaway if you manage your own servers (a VPS with Coolify, for example): docker --version and your kernel version are now a security checklist item, not trivia.

    What is Docker and what is it for?

    Docker solves the oldest problem in software: “it works on my machine”. A container is an isolated process that carries everything your application needs — runtime, libraries, configuration — and shares the host operating system’s kernel. The result: identical environments in development, testing and production.

    Three concepts to keep straight from day one:

    • Image: the immutable template (the “installer”): file layers + metadata. Built once, distributed through a registry like Docker Hub.
    • Container: a running instance of that image (the “process”). You can launch ten containers from the same image.
    • Dockerfile: the text file with the recipe to build the image.

    The relationship between the three is what trips most people up at the start, so here it is as a diagram:

    flowchart TB
        subgraph local["💻 Your machine"]
          D["📄 Dockerfile"] -->|docker build| I["📦 Image"]
          I -->|docker run| C["⚙️ As many containers<br/>as you want"]
        end
        I -->|docker push| R[("🌐 Registry")]
        R -->|docker pull| I2["📦 The same image"]
        subgraph remote["☁️ Any other machine"]
          I2 -->|docker run| C3["⚙️ Identical behaviour"]
        end

    Read it top to bottom: you write one Dockerfile, build one image from it, and from that single image you launch as many containers as you want — locally or, after a trip through the registry, on any other machine with the same result. That last part is the whole point of Docker.

    Docker vs virtual machine

    The classic confusion. A container is not a lightweight VM; it is an isolated process:

    Container (Docker)Virtual machine
    KernelShares the host’sOne per VM
    StartupMilliseconds–secondsMinutes
    SizeMBs (an alpine image is ~5 MB)GBs
    IsolationProcess-level (namespaces, cgroups)Fully virtualized hardware
    Typical usePackaging and deploying applicationsIsolating entire operating systems

    They don’t compete: on Windows and macOS, Docker Desktop runs your containers inside a utility Linux VM. And on many servers, containers run on top of cloud VMs.

    Installing Docker in 2026 (and when you have to pay)

    Here is a nuance many people discover too late:

    • Docker Engine (Linux) is open source (Apache 2.0) and always free, including for companies. On an Ubuntu/Debian server you install it from the official repository in two minutes.
    • Docker Desktop (Windows, macOS, Linux with a GUI) is free for personal use, education, open source and small companies, but requires a paid subscription for commercial use in organizations with more than 250 employees or more than 10 million USD in annual revenue. Paid plans go from $9 to $24 per user/month (official pricing).

    On Windows, Docker Desktop runs on WSL2 and is the recommended path. If your organization is over the license threshold and doesn’t want to pay, the mature alternatives in 2026 are:

    AlternativePlatformNote
    Podman + Podman DesktopLinux, Windows, macOSFree, daemonless, rootless by design; Docker-compatible CLI
    Rancher DesktopWindows, macOS, LinuxFree (SUSE), ships with built-in Kubernetes
    OrbStackmacOS onlyBlazing fast; paid for business use
    ColimamacOS, LinuxFree, minimalist, CLI-driven

    Verify your install with:

    docker version        # Engine 29.x in 2026
    docker compose version  # v5.x — note: NO hyphen
    docker run hello-world
    

    The essential commands

    90% of day-to-day Docker fits in this table:

    CommandWhat it does
    docker run -d -p 8080:80 nginxPulls (if needed) and starts a container in the background, mapping port 8080 → 80
    docker ps / docker ps -aLists running / all containers
    docker logs -f <name>Follows a container’s logs
    docker exec -it <name> shOpens a shell inside the container
    docker build -t myapp:1.0 .Builds an image from the directory’s Dockerfile
    docker imagesLists local images
    docker stop / docker rmStops / removes a container
    docker system pruneCleans stopped containers, networks and dangling images (frees GBs)
    docker initGenerates a Dockerfile, compose.yaml and .dockerignore tailored to your project
    docker debug <name>Debug shell with its own toolbox, even in shell-less containers (now free for everyone)

    Two recent additions worth highlighting: docker init detects your stack (Node, Python, Go, PHP, Rust…) and generates starter files with best practices baked in — the best way to start a project today — and docker debug gives you a fully equipped shell even in distroless images that don’t ship ls.

    Dockerfile in depth: your image’s recipe

    A modern Dockerfile for a Node app looks like this (the same pattern applies to PHP, Python or Go):

    # --- Stage 1: build ---
    FROM node:24-alpine AS build
    WORKDIR /app
    
    # 1) Manifests first: the dependency layer gets cached
    COPY package*.json ./
    RUN --mount=type=cache,target=/root/.npm npm ci
    
    # 2) Then the code (changes more often, invalidates less cache)
    COPY . .
    RUN npm run build
    
    # --- Stage 2: runtime ---
    FROM node:24-alpine
    WORKDIR /app
    ENV NODE_ENV=production
    
    COPY --from=build /app/dist ./dist
    COPY --from=build /app/node_modules ./node_modules
    
    # Non-root user: compromising the app doesn't compromise the container
    USER node
    
    HEALTHCHECK --interval=30s --timeout=3s \
      CMD wget -qO- http://localhost:3000/health || exit 1
    
    EXPOSE 3000
    CMD ["node", "dist/server.js"]
    

    The decisions that make a Dockerfile good (or bad) in 2026:

    1. Multi-stage builds, whenever you compile

    The build stage carries compilers and dev dependencies; the final stage only the artifact. It is the number-one technique for going from 1 GB images to 100 MB images. Official docs.

    2. Order layers to exploit the cache

    Docker caches each instruction as a layer. Golden rule: what changes least goes first. That’s why you copy package*.json and install dependencies before copying the code. Add cache mounts (RUN --mount=type=cache) so that even a dependency change doesn’t re-download everything from scratch.

    3. Choose your base image wisely

    • alpine — minimal (~5 MB). Careful: it uses musl instead of glibc and some native packages can fight you.
    • slim (Debian) — the safe middle ground for most apps.
    • Distroless — no shell, no package manager: minimal attack surface.
    • Docker Hardened Images — the big news: hardened, CVE-mitigated images maintained by Docker that used to be a paid product and since December 2025 are free and open source (over 1,000 images in the catalog). In 2026 they are my first choice as a production base.

    Always pin a version (node:24-alpine, not node:latest) and, in production, consider pinning the digest (@sha256:...).

    4. Never bake secrets into the image

    No tokens in ARG or ENV: they are written into the layers forever. Use build secrets:

    docker build --secret id=npmrc,src=$HOME/.npmrc .
    
    RUN --mount=type=secret,id=npmrc,target=/root/.npmrc npm ci
    

    5. .dockerignore, non-root user and HEALTHCHECK

    A .dockerignore (at minimum: node_modules, .git, .env) speeds up builds and keeps sensitive files out. A non-root USER limits the blast radius of a compromise. HEALTHCHECK lets Docker (and Compose) know whether your app actually works, not just whether the process exists.

    6. SBOM and provenance: the supply chain matters

    BuildKit can generate and attach attestations (SBOM software inventory + SLSA provenance) to your images:

    docker buildx build --sbom=true --provenance=true -t myapp:1.0 .
    

    Since Engine 29.6 you can even query them via the API. If you sell software to enterprises, they are already asking you for this. Pair it with Docker Scout for continuous vulnerability analysis.

    Docker Compose in 2026: v5 and no hyphen

    If a tutorial says docker-compose up, it’s outdated. Compose v1 (Python, hyphenated) reached end of life in July 2023; the current command is docker compose, a Go CLI plugin. And in December 2025, Compose v5 “Mont Blanc” arrived — they deliberately skipped v3 and v4 so nobody confuses the program’s version with the legacy 2.x/3.x file formats, which are also obsolete.

    What defines Compose today:

    • The file is called compose.yaml (preferred over docker-compose.yml) and no longer takes version: — that key is ignored.
    • docker compose build delegates to Docker Bake, the same engine as docker build: same capabilities, same cache.
    • You can publish and consume Compose projects as OCI artifacts or Git repos (docker compose publish).

    A realistic compose.yaml for development:

    services:
      app:
        build: .
        ports:
          - "3000:3000"
        environment:
          DATABASE_URL: postgres://app:secret@db:5432/app
        depends_on:
          db:
            condition: service_healthy
        develop:
          watch:
            - action: sync
              path: ./src
              target: /app/src
            - action: rebuild
              path: package.json
    
      db:
        image: postgres:17-alpine
        environment:
          POSTGRES_USER: app
          POSTGRES_PASSWORD: secret
        volumes:
          - db-data:/var/lib/postgresql/data
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U app"]
          interval: 5s
          retries: 10
    
      adminer:
        image: adminer
        ports:
          - "8081:8080"
        profiles: [debug]
    
    volumes:
      db-data:
    

    Three features that change your daily workflow and that few people use:

    1. Watch modedocker compose watch syncs your code into the container on save (or rebuilds when package.json changes). Hot reload without fragile bind mounts. Docs.
    2. Profiles — optional services (like adminer above) that only start with docker compose --profile debug up. Docs.
    3. include — compose your stack from other teams’ or repos’ Compose files. Docs.

    Working with these YAML files every day? My JSON ⇄ YAML converter will save you more than one syntax headache.

    What changed under the hood: Docker Engine 29

    The major Engine 29 release (November 2025) brought the biggest structural changes in years. The ones that affect you:

    • containerd image store by default on new installs: the classic graph drivers (overlay2) are deprecated. Direct benefit: native support for multi-platform images (amd64 + arm64 under the same tag) and attestations, no workarounds.
    • Minimum API 1.44: clients older than Docker 25 stop working against Engine 29 (there’s a daemon.json override if you need it temporarily).
    • Experimental nftables firewall backend (--firewall-backend=nftables), on track to replace iptables. Still not compatible with Swarm.

    As of mid-2026 the Engine is on the 29.6.x series and Docker Desktop on 4.8x, with Kubernetes 1.36 built in. If you build for ARM (Graviton, Apple Silicon, Raspberry Pi), multi-platform builds with --platform linux/amd64,linux/arm64 are now a first-class workflow.

    Docker + AI: containers for models and agents

    Docker’s most visible bet in 2025-2026 is generative AI, and it goes far beyond marketing:

    • Docker Model Runner (GA since September 2025, open source): run LLMs locally with docker model pull ai/llama3.2 and docker model run, expose an OpenAI-compatible API, and distribute models as OCI artifacts on Docker Hub. It supports NVIDIA GPUs (CUDA), Apple Silicon and, since October 2025, AMD/Intel via Vulkan. If you want to try a local model without fighting Python, this is the shortest path today.
    • MCP Catalog and Toolkit: a curated catalog of MCP servers (the protocol that connects AI agents to tools) packaged as verified images — it passed one million pulls in its first year. If MCP is new to you, I explain how to build an AI agent with Laravel and MCP on the blog.
    • Docker Agent (formerly cagent): define agents and multi-agent teams in YAML, with local models (Model Runner) or remote ones, plus MCP tools. Compose also supports a top-level models element for declaring agentic stacks.
    • Docker Offload (GA in April 2026): moves the Engine to Docker’s managed cloud when your machine runs out of steam, included in the Business plan.

    The underlying pattern: containers are becoming the distribution unit for models, MCP servers and agents too — the same thesis I develop in the agentic AI guide for 2026. And if you let an agent write code, run it in an isolated container: I cover that in secure vibe coding.

    What about production? Compose vs Swarm vs Kubernetes

    The million-dollar question, with the short 2026 answer:

    1. Docker Compose — development and single-server deployments (VPS, side projects, most SMBs). With restart: always, healthchecks and a reverse proxy in front, it covers more cases than people admit in public. It’s how I serve several of my own projects.
    2. Docker Swarm — still shipped with the Engine, but effectively in maintenance mode: no meaningful new features, and left out of the new nftables backend. Fine if you already operate it; I wouldn’t pick it for a new project.
    3. Kubernetes — the de facto standard for orchestrating at scale (multi-node, autoscaling, self-healing). Engine 29 itself justified its image-store change as “ecosystem alignment… platforms like Kubernetes”. Start with a managed offering (EKS, GKE, AKS) or k3s, not a hand-rolled cluster.

    And no: Kubernetes does not “replace” Docker. Kubernetes orchestrates containers; the images it deploys are still built with Docker/BuildKit. The confusion comes from the 2022 dockershim removal, which only changed how Kubernetes runs containers internally (containerd) — not your images or your Dockerfiles.

    Docker 2026 checklist

    • docker compose (no hyphen) and a compose.yaml without version:
    • docker init to start new projects with best practices baked in
    • Multi-stage builds + layers ordered by change frequency + cache mounts
    • slim/alpine/distroless base or a Docker Hardened Image, with a pinned version
    • Non-root USER, HEALTHCHECK and .dockerignore in every service
    • Secrets via --mount=type=secret, never in ENV/ARG
    • --sbom=true --provenance=true on images you distribute
    • Multi-platform builds if you deploy to ARM
    • Production ladder: Compose (single host) → managed Kubernetes (multi-node)

    Frequently asked questions

    What is Docker and what is it used for? It’s the platform that packages your app and its dependencies into portable containers that run the same on any machine. It kills “it works on my machine” and simplifies deployments.

    What is the difference between an image and a container? The image is the immutable template; the container is a running instance of it. One image, N containers.

    Is Docker free? Engine on Linux, always. Desktop is free except for commercial use in organizations with 250+ employees or $10M+ revenue, where it requires a paid plan (from $9/user/month).

    Dockerfile or Compose? Both: the Dockerfile builds one service’s image; compose.yaml orchestrates several services together.

    docker-compose or docker compose? No hyphen. v1 died in 2023 and current Compose is on v5.

    Does Kubernetes replace Docker? No: Kubernetes orchestrates the containers whose images you build with Docker.

    Conclusion

    Docker in 2026 is two things at once: a foundation you should already master — small and secure images, Compose v5, Dockerfile best practices — and a platform reinventing itself around AI, with models, MCP servers and agents distributed as containers. The good news is that the investment pays double: what you learn to deploy your app is exactly what you need to run AI locally or on your server.

    If your business needs to containerize a system, set up a solid VPS deployment or move to modern infrastructure, that’s exactly what I do in my custom systems service. And if you’re just starting out: install Docker, run docker init on your project, and tell me how it goes.

    Compartir

    Search

    Tags

    Tutorial PHP Laravel AI JavaScript Web Development Best Practices Laravel 13 Security Migration Tools Claude SEO Regular Expressions Text Manipulation