What Are Storage Drivers (overlay2, etc.) in Docker?

What Are Storage Drivers (overlay2, etc.) in Docker?

A ground-up, zero-jargon tour of the piece of Docker almost nobody thinks about until it breaks: the storage driver that turns a stack of frozen image layers into a real, writable filesystem a container can actually run on.

Imagine a library where every book ever printed is stored, untouched, in a locked archive — nobody is allowed to write in the margins of an archived book. When a reader wants to actually use a book, the library doesn’t hand them the original. It photocopies just the pages the reader needs to write on, clips those loose pages on top of the original book, and gives the reader that combined stack. The reader flips through it and, to them, it looks and behaves like one ordinary book. Underneath, though, the archive stays pristine, and only the clipped-on pages ever get marked up. The librarian who designs and runs this photocopy-and-clip system is, in Docker terms, the storage driver.

This is a complete, practical walkthrough of what a Docker storage driver actually does, how the modern default — overlay2 — works internally, why several other storage drivers exist at all, and what choosing and tuning one concretely means for performance, reliability, and security in a running system. None of this requires prior experience with Docker, filesystems, or the command line. Every technical term is explained the first time it appears, paired with a plain-language analogy and, wherever it helps, a real example drawn from how well-known technology companies actually run their infrastructure.

By the end, “storage driver” should stop sounding like an obscure piece of plumbing buried deep in Docker’s internals, and start feeling like exactly what it is: the single component responsible for making a stack of frozen, shared files feel, to every running container, like an ordinary, private, writable disk — cheaply, safely, and without any container ever needing to know the illusion is happening at all.

1What Is a Storage Driver, Really?

Before comparing drivers, it helps to know exactly what job a storage driver is hired to do.

A Docker image, as covered by the concept of layering, is a stack of independent, read-only pieces. A running container needs two things a plain stack of files cannot provide on its own: it needs that stack to look and behave like one single, ordinary filesystem to any program running inside it, and it needs somewhere to write new files and changes without disturbing the original, shared image underneath. The component responsible for solving both problems — presenting a unified view and handling writes safely — is the storage driver, sometimes called the graph driver.

Everyday Analogy

Think of the storage driver as a translator standing between a container and the raw layers on disk. The container speaks only one simple language: “open this file,” “write to that file,” “list this folder.” It has no idea that what it is looking at is actually several stacked layers glued together. The storage driver listens to every one of those simple requests, quietly figures out which physical layer the answer actually lives in (or which layer a write should land in), and replies in a way that makes the whole stacked arrangement invisible. The container never has to know the translator exists.

Several storage drivers have existed across Docker’s history — overlay2, aufs, devicemapper, btrfs, zfs, vfs, and fuse-overlayfs among them — and each one solves the same two problems using a different underlying filesystem technology, with different trade-offs in speed, disk efficiency, and compatibility. overlay2 has been the default and recommended storage driver on modern Linux systems for several years, because it offers the best balance of performance, stability, and kernel support for the overwhelming majority of workloads. Understanding overlay2 deeply, and understanding why the alternatives exist at all, is the goal of this article.

i
Key Idea

The storage driver is not the same thing as a “volume.” A storage driver manages the image’s own layered filesystem and a container’s thin writable layer. A volume is a separate, driver-independent mechanism for persisting data outside that layered system entirely. Confusing the two is one of the most common early misunderstandings in Docker, and it will be untangled fully in Chapter 4.

The term “graph driver” is older terminology that still appears throughout documentation, source code, and command-line tooling output, and it refers to exactly the same component as “storage driver.” The name comes from an early internal design where the relationships between image layers were modeled as a graph, with each layer pointing back to its parent. Even though the surrounding implementation has evolved considerably since then, the name stuck, and a beginner reading Docker’s own diagnostic output for the first time should not be thrown off by seeing “graph driver” and “storage driver” used interchangeably to describe the same underlying concept.

2Architecture & Components: Where the Storage Driver Sits

The storage driver is one layer inside a taller stack of software, sitting directly between the container runtime and the host’s real filesystem.

flowchart TB
    A["Application Process Inside Container"] --> B["Container Runtime (e.g. containerd, runc)"]
    B --> C["Storage Driver (overlay2, devicemapper, btrfs, ...)"]
    C --> D["Host Kernel Filesystem (ext4, xfs, btrfs, zfs)"]
    D --> E["Physical or Virtual Disk"]
        

Fig. 1 — The storage driver translates simple file operations from a container into layered, copy-on-write operations on the host’s real filesystem.

For overlay2 specifically, four named directories do all the work, and their names are worth learning because every piece of documentation and every troubleshooting guide uses them directly. The lowerdir is the stack of read-only image layers, ordered from oldest to newest. The upperdir is the single writable layer created fresh for one specific container. The workdir is an internal scratch area the kernel’s overlay filesystem implementation uses to safely prepare changes before they are committed into the upperdir — it is invisible to the container itself and exists purely for the mechanics of atomic updates. The merged directory is the final, combined view: the single unified folder tree that actually gets mounted into the running container, and the only one of the four the container’s own processes ever interact with.

Component

lowerdir

The stack of read-only image layers, shared and cached across every container using that image.

Component

upperdir

The single writable layer unique to one container, where every new or changed file actually lands.

Component

workdir

An internal, kernel-managed scratch directory used to keep filesystem updates atomic and consistent.

Component

merged

The single combined view mounted into the container — what every application process actually sees and uses.

overlay2 is, itself, a thin layer of Docker-specific logic sitting on top of a filesystem feature already built directly into the Linux kernel, called OverlayFS. Docker did not invent stacked, copy-on-write filesystems; it adopted a mature kernel capability and wrote the bookkeeping layer that maps “this image has these layers, in this order” onto “mount these kernel directories in this arrangement.” This is an important architectural fact: overlay2’s performance characteristics are, in large part, the Linux kernel’s own OverlayFS performance characteristics, not something Docker independently reimplemented from scratch.

This lineage also explains why overlay2 replaced an earlier driver named simply “overlay.” The original overlay driver supported only a single lower layer, which meant Docker had to work around that limitation with awkward, inefficient techniques to represent an image’s full stack of many layers. Once the Linux kernel itself gained native support for multiple stacked lower directories, Docker built overlay2 specifically to take advantage of that capability directly, mapping an image’s entire layer history onto the kernel’s multi-layer lowerdir feature in one clean step rather than working around a single-layer restriction. This is a useful pattern to notice: several of Docker’s storage-driver decisions over the years have been downstream of, and directly enabled by, capabilities the Linux kernel itself gained over time.

3Internal Working: How overlay2 Actually Resolves a File

Two operations explain almost everything about how overlay2 behaves: reading a file, and writing to one that already exists in a lower layer.

When a process inside a container asks to read a file, the kernel’s OverlayFS implementation searches the stacked directories from the top down — starting at the upperdir, then working backward through the lowerdir layers from newest to oldest — and returns the very first copy of that file it finds. If the file has never been modified inside this particular container, the search finds it in one of the shared, read-only lower layers, and the read is served directly from there, at essentially native filesystem speed, with no copying involved at all.

When a process asks to write to a file that already exists only in a lower, read-only layer, something more expensive has to happen first, called copy-on-write, or “copy-up.” The kernel must first copy the entire file, in full, up from wherever it currently lives in the lower layers into the upperdir, and only then apply the requested change to that new upper copy. From that point forward, every future read and write to that file is served directly from the upperdir copy, and the original in the lower layer is left completely untouched, forever.

1

Write request arrives

A process inside the container asks to modify a file that currently exists only in a read-only lower layer.

2

Kernel checks the upperdir first

If a copy of that file already exists in the upperdir from an earlier write, the kernel writes to it directly — no copy-up needed.

3

Copy-up executes if needed

If no upperdir copy exists yet, the entire file is copied, whole, from the lower layer into the upperdir before any change is applied.

4

Change is applied to the upper copy

The requested modification is written into the newly copied-up file, now living entirely in the writable upperdir.

5

Future access is fast again

Every subsequent read or write to that same file goes straight to the upperdir copy, with no further copy-up cost.

!
Why This Matters

Copy-up cost is proportional to the size of the whole file being modified, not to the size of the change itself. Changing one byte inside a two-gigabyte file that currently lives only in a lower layer means copying the entire two gigabytes up first. Workloads that frequently modify a small number of very large files sitting in image layers — large database files, large log files, large media assets — are exactly the pattern that overlay2 handles worst, and exactly the pattern Chapter 4’s discussion of volumes exists to solve.

Renaming a file behaves similarly to a write for this purpose, because a rename that moves a file from a lower layer into a new location is, under the hood, implemented as a copy-up of that file followed by the rename operation applied to the newly copied-up version. This is a subtle but practical detail: a workload that appears to only be “renaming” large files, without touching their contents at all, can still trigger the same expensive copy-up behavior as an outright content modification, simply because the rename itself has to happen against a writable copy rather than the original read-only one.

Deleting a file that exists in a lower layer works through a related mechanism called a whiteout. Because the lower layers are strictly read-only, a delete cannot physically remove the file from them. Instead, the kernel creates a special marker file inside the upperdir with the same name, which tells the merged view “treat this path as deleted, even though a copy still technically exists further down the stack.” This is the exact same underlying mechanism, at the container’s writable-layer level, that makes image-layer deletions behave the way Chapter 5 of any layering discussion describes: hidden from view, but not physically gone until the whole layer is discarded.

A closely related concept, worth knowing even at a conceptual level, is the opaque directory. If a whole directory is deleted and then a new, different directory is created at that exact same path, the kernel needs a way to say “do not merge this new directory’s contents with whatever used to be at this path in a lower layer — treat it as an entirely fresh start.” It marks the new upperdir directory as opaque to signal exactly that, preventing old, deleted contents from a lower layer from confusingly reappearing underneath a directory that was deliberately replaced. Beginners rarely need to manipulate this directly, but understanding that it exists explains why directory replacement, not just file replacement, behaves predictably under a layered filesystem.

4Data Flow & Lifecycle: From Image Pull to Container Write

Following one image through its full lifecycle shows exactly when the storage driver gets involved, and when it deliberately steps aside.

First, when an image is pulled, the storage driver unpacks each downloaded layer archive onto the host’s disk, in the location the driver manages, and records how those layers stack together. Second, when a container is created, the storage driver allocates a brand-new, empty upperdir and workdir specifically for that container, and mounts the full lowerdir-upperdir-workdir arrangement into a single merged view. Third, while the container runs, every file operation from the application inside it flows through the read and copy-up behavior described in Chapter 3. Fourth, when the container is removed, its upperdir and workdir are deleted entirely — every change that container ever made simply vanishes, while the shared, read-only lowerdir layers remain completely untouched and ready to be reused by the next container started from that same image.

sequenceDiagram
    participant Img as Image Layers (lowerdir)
    participant Drv as Storage Driver
    participant C as Container
    Img->>Drv: Layers unpacked and cached on pull
    Drv->>C: New upperdir + workdir created on container start
    Drv->>C: Merged view mounted (read from lowerdir, write to upperdir)
    C->>Drv: Container removed
    Drv->>Drv: upperdir and workdir deleted; lowerdir untouched and reused
        

Fig. 2 — Every container gets a fresh, disposable writable layer, while the shared read-only layers persist and are reused across containers.

This disposability is precisely why containers are described as ephemeral by default, and it is exactly where volumes enter the picture, deliberately stepping outside the storage driver’s territory. A volume is a directory managed directly by the container engine, living outside the layered upperdir/lowerdir system entirely, and mounted directly into a container’s filesystem at a chosen path. Because a volume is not part of the copy-on-write layering, writes to it never trigger a copy-up, and its contents survive even after the container that used it is removed. Databases, user-uploaded files, and any data meant to outlive a single container’s life belong in a volume, precisely so they never have to pass through the storage driver’s layering machinery at all.

Why This Lifecycle View Matters in Practice

A team running a database inside a container, without a volume, writing its data files directly into the container’s writable layer, will see every single write pay the copy-on-write penalty the very first time the database’s data file is touched, and will lose all of that data instantly the moment the container is removed or recreated. Understanding that the storage driver’s writable layer is intentionally temporary, and that volumes exist as the deliberate escape hatch from it, prevents both of these painful surprises.

Two closely related mechanisms are worth distinguishing here, since both bypass the storage driver but serve different purposes. A named volume is fully managed by the container engine itself, with its storage location decided and tracked by the engine, and is the recommended default for most persistent application data because it is portable and easy to back up, inspect, or move between hosts. A bind mount, by contrast, maps a specific, pre-existing path on the host’s own filesystem directly into the container, giving a container direct access to a folder that already exists outside Docker’s management entirely — commonly used for local development, where a developer wants a container to see live edits made directly on their own machine. Both sit outside the storage driver’s copy-on-write layering, but a named volume is the engine’s own persistent storage, while a bind mount is simply a window into a folder the host already had.

5Advantages, Disadvantages & Trade-offs Across Storage Drivers

overlay2 is the right default for most workloads, but it is a default, not a universal answer — knowing the alternatives clarifies why.

Storage DriverUnderlying TechnologyTypical Trade-off
overlay2Linux kernel OverlayFS, on top of ext4 or xfsBest general-purpose balance of speed, stability, and kernel support; the modern default
devicemapperBlock-level device mapping with thin provisioningOnce common before overlay2 matured; more complex to configure correctly, weaker default performance
btrfsNative copy-on-write filesystem with built-in snapshottingStrong for workloads wanting native snapshots, but requires the host’s entire filesystem to be btrfs
zfsNative copy-on-write filesystem with advanced volume managementExcellent data integrity and snapshot features, at the cost of higher memory usage and setup complexity
vfsPlain directory copies, no copy-on-write at allSimplest and most compatible, but every layer is fully duplicated per container — slow and disk-hungry
fuse-overlayfsUserspace implementation of overlay semantics via FUSEEnables overlay-style behavior in rootless containers where the kernel driver is unavailable, at some performance cost

Why overlay2 Wins by Default

  • Ships directly in the mainline Linux kernel on virtually every modern distribution, requiring no special host filesystem.
  • Shares the page cache across containers reading the same underlying file, which is a major read-performance advantage over drivers that fully duplicate data.
  • Handles the common case — read-heavy application workloads with occasional small writes — efficiently and with low operational overhead.
  • Backed by a large, mature ecosystem of tooling, documentation, and community troubleshooting knowledge.

Where overlay2 Shows Its Limits

  • Copy-up cost on large files makes it a poor fit for write-heavy workloads that modify large files already baked into image layers.
  • Very deep layer stacks can add lookup overhead and, on some older kernels, run into hard limits on how many layers can be stacked at once.
  • Lacks the native snapshotting and data-integrity features that btrfs or zfs offer out of the box.
  • Requires a genuinely modern kernel to get its full performance and correctness benefits; very old kernels may behave inconsistently.
“There is no single best storage driver — there is only the driver whose trade-offs match the workload actually running on top of it.”

It is worth pausing on why vfs still exists at all, given how clearly it loses on both speed and disk efficiency compared to every copy-on-write driver in the table above. vfs performs no copy-on-write sharing whatsoever: every single layer is fully, physically duplicated for every container that uses it, which is slow to set up and wasteful of disk space. Its value is narrow but real — it works reliably on essentially any filesystem, including ones that lack copy-on-write support entirely, which makes it a dependable fallback and a useful tool for isolating whether a performance problem is actually caused by copy-on-write layering at all, by comparing behavior against a driver that has none.

One overlay2 advantage deserves a closer look because it is easy to underestimate: shared page-cache usage. When the operating system reads a file into memory for caching purposes, and two different containers both read that same underlying file from a shared lower layer, the kernel is able to reuse the exact same cached memory pages for both of them, rather than caching two separate copies. Storage drivers that fully duplicate layer data per container, such as vfs, lose this benefit entirely — every container ends up with its own physically separate copy of what should be identical, shared data, both on disk and in memory. On a host densely packed with many containers built from the same base image, this single difference can be the deciding factor in how many containers that host can comfortably run at once.

6Security Implications of Storage Driver Choice

The storage driver is part of the isolation boundary between a container and its host, and between one container and another — its correctness is a security property, not just a performance one.

Because every container’s writable upperdir is created fresh and deleted along with the container, the storage driver is directly responsible for making sure one container’s writes never leak into another container’s view, and never leak back into the shared, supposedly-immutable image layers. A storage driver bug or a misconfiguration that breaks this isolation could allow a process in one container to see or modify data belonging to a completely different container sharing the same underlying image, which is precisely the kind of cross-container isolation break that container security depends on never happening.

!
Security Trap

Running containers as the root user combined with certain older or misconfigured storage-driver setups has historically been linked to a category of container-escape vulnerabilities, where a process manipulates how the overlay filesystem resolves paths to reach files outside its intended container boundary. Keeping the storage driver current, keeping the host kernel patched, and avoiding unnecessary root privileges inside containers are the three practical defenses.

Rootless container setups — where the entire container engine and every container it runs operate without any root privileges on the host at all — deliberately cannot use the standard kernel overlay2 driver in many configurations, because mounting kernel overlay filesystems has traditionally required elevated privileges. This is precisely why fuse-overlayfs exists: it reimplements overlay-style layering in ordinary userspace, using the FUSE (filesystem in userspace) mechanism, so that a completely unprivileged user can still get layered, copy-on-write container storage. Choosing fuse-overlayfs is therefore often not a performance decision at all, but a direct consequence of a security decision to run rootless in the first place.

Risk

Cross-Container Isolation Failures

A storage driver bug can, in rare cases, let one container’s process reach data belonging to another container or the host.

Risk

Stale Kernel, Stale Driver

Running an old kernel means missing security fixes specifically made to the OverlayFS implementation overlay2 depends on.

Risk

Rootful Defaults on Sensitive Hosts

Defaulting to the standard privileged overlay2 setup on a host that should be rootless widens the privilege footprint of every container running on it.

Mandatory access control systems such as SELinux and AppArmor add another layer of interaction worth knowing about. These systems apply their own security labels and policy rules to files and processes independently of the storage driver, and a correctly configured host must ensure those labels are applied consistently to files as they move through copy-up operations and across the merged view a container actually sees. A storage-driver or configuration mismatch here can either silently weaken intended isolation or, just as disruptively, cause legitimate container operations to be unexpectedly denied. This is one of the more common sources of confusing, hard-to-diagnose permission errors when moving a containerized workload between hosts with different security-module configurations, and it is a direct reminder that the storage driver does not operate in isolation from the rest of the host’s security stack.

7Monitoring, Logging & Metrics for Storage Driver Health

Storage driver problems tend to appear as vague symptoms elsewhere — slow writes, mysterious disk pressure — so knowing exactly what to watch turns guesswork into diagnosis.

Disk
HOST DISK USAGE UNDER THE STORAGE DRIVER’S DATA ROOT, TRACKED SEPARATELY FROM APPLICATION VOLUMES
Write %
COPY-ON-WRITE LATENCY OR WRITE-OPERATION LATENCY, WATCHED FOR SPIKES ON LARGE-FILE WORKLOADS
Layers
MAXIMUM STACKED LAYER DEPTH PER IMAGE, WATCHED AGAINST DRIVER-SPECIFIC LIMITS

The first and most direct signal is simply disk usage growth under the storage driver’s own data directory on the host, tracked over time and separately from any data sitting in dedicated volumes. Because every stopped-but-not-removed container leaves its upperdir sitting on disk, and because unused, dangling image layers are not automatically reclaimed the instant they become unreferenced, a host that never runs cleanup can quietly accumulate enormous amounts of storage-driver-managed disk usage that has nothing to do with active application data at all.

It is worth explicitly naming why this matters more than it first appears: a host can be running perfectly healthy applications, with no errors in any application log, while its available disk space steadily shrinks purely because of accumulated storage-driver overhead. By the time that shrinking disk space actually causes a visible failure — a new container failing to start because there is no room left to create its writable layer — the underlying cause has often been building quietly for weeks. Tracking this metric proactively converts a sudden, confusing outage into a routine, predictable maintenance task scheduled well in advance.

Second is write latency, ideally measured from inside representative containers rather than assumed from host-level disk benchmarks alone. A workload that suddenly starts feeling slow on writes, despite the underlying disk hardware being healthy and fast, is a classic symptom of repeated, expensive copy-up operations against large files that keep getting freshly modified inside the writable layer instead of living in a dedicated volume.

Third is layer count and stack depth per running image. Some storage-driver and kernel combinations impose a hard ceiling on how many layers can be stacked in a single overlay mount; approaching that ceiling can cause container start failures that look, at first glance, completely unrelated to layering at all. Tracking maximum layer depth across an organization’s images as a simple metric catches this class of problem long before it causes a production incident.

i
Observability Habit

Mature platform teams monitor storage-driver disk usage, container write latency, and layer depth as distinct metrics from general host disk space, because a healthy-looking “disk usage” dashboard can hide an unhealthy, ballooning population of orphaned container writable layers sitting quietly underneath it.

Most container engines also expose a built-in, human-readable disk-usage breakdown on request, separating space consumed by images, by stopped containers’ writable layers, and by volumes into distinct categories. This single, readily available breakdown is often the fastest first step in any storage investigation, because it immediately answers the most important triage question — is this unexpected disk usage coming from the images themselves, from accumulated container writable layers, or from data sitting in volumes — before any deeper, layer-by-layer inspection is needed at all.

8Design Patterns for Storage Driver Configuration

These are the proven, repeatable configuration patterns experienced platform teams reach for, roughly in order of impact.

PATTERN · 01 Default to overlay2, Deviate With a Reason
What It Is

Treating overlay2 as the assumed choice for every new host running a modern kernel, and only reaching for an alternative driver when a specific, named requirement — native snapshotting, rootless operation, a legacy kernel — makes that alternative genuinely necessary.

Why It Works

overlay2’s maturity, kernel-native support, and page-cache-sharing behavior make it the correct answer for the overwhelming majority of workloads. Deviating without a concrete reason usually trades away real, well-understood performance for speculative benefits that the workload never actually needed.

PATTERN · 02 Route Write-Heavy, Large-File Data to Volumes
What It Is

Identifying any data path that will see frequent writes to large files — database data directories, message-queue logs, large cache files — and deliberately mounting a dedicated volume at that path instead of letting those writes land in the container’s copy-on-write layer.

Why It Works

Volumes sit outside the layered copy-on-write system entirely, so writes to them never pay the copy-up cost described in Chapter 3, and their contents persist independently of any single container’s lifecycle.

PATTERN · 03 Keep Layer Stacks Shallow
What It Is

Applying the layer-consolidation and multi-stage-build discipline from image-building practice specifically to keep the total number of stacked layers in a shipped image reasonably low, rather than letting it grow unchecked over an image’s lifetime.

Why It Works

Fewer stacked layers means less work for the kernel’s overlay lookup on every file access, and keeps every image comfortably clear of driver-specific stacking limits, which become a real and confusing failure mode only once they are actually hit.

PATTERN · 04 Scheduled, Deliberate Cleanup
What It Is

Running regular, scheduled cleanup of stopped containers and unused, dangling image layers, rather than relying on manual, reactive cleanup only once a host runs dangerously low on disk space.

Why It Works

Because the storage driver never automatically reclaims a stopped container’s writable layer or an unreferenced image layer on its own, disk usage under the driver’s data root only ever grows without intervention. A scheduled habit turns an eventual emergency into routine, low-drama maintenance.

PATTERN · 05 Match the Driver to the Privilege Model
What It Is

Deciding whether a host or platform needs to run rootless, and choosing between the standard kernel overlay2 driver and a userspace alternative like fuse-overlayfs as a direct, deliberate consequence of that privilege decision, rather than an afterthought.

Why It Works

Privilege model and storage driver are tightly coupled in practice, since mounting the kernel’s overlay filesystem has traditionally required elevated privileges. Deciding the privilege model first, and then picking the storage driver that actually supports it, avoids the awkward position of discovering the mismatch only after a rootless rollout is already underway.

Together, these five patterns describe a coherent operational posture: trust the well-tested default, keep expensive writes out of the copy-on-write path entirely, keep the layer stack itself lean, never let cleanup become optional, and let the security posture of a host decide its storage driver rather than the other way around. None of them requires exotic tooling — they are disciplines, not products.

9Anti-Patterns: What Quietly Wrecks Storage Performance

Every one of these anti-patterns is the exact mirror image of a pattern from Chapter 8, which is why recognizing the pattern makes the anti-pattern obvious.

Anti-Pattern

Databases Writing Into the Writable Layer

Running a database or any large-file, write-heavy workload with its data directory left inside the container’s default writable layer, instead of on a dedicated volume, guarantees repeated, expensive copy-up operations and data loss on container removal.

Anti-Pattern

Switching Drivers Without a Reason

Changing away from overlay2 based on outdated advice or an unverified rumor about performance, without a specific, measured need that the alternative actually addresses.

Anti-Pattern

Unbounded Layer Growth

Letting an image’s layer count grow indefinitely over its lifetime with no consolidation discipline, eventually approaching driver-specific stacking limits and adding unnecessary lookup overhead on every file access.

Anti-Pattern

No Cleanup Schedule

Never scheduling removal of stopped containers and dangling layers, leaving disk usage under the storage driver’s data root to climb silently until a host runs out of space unexpectedly.

Anti-Pattern

Ignoring Kernel Version

Running overlay2 on a very old or unsupported kernel and expecting the same correctness and performance guarantees as a modern, well-patched one, when the driver’s behavior is fundamentally tied to the kernel’s own OverlayFS implementation.

Anti-Pattern

Mixing Storage Drivers Across a Fleet Without Reason

Letting different hosts in the same fleet silently end up on different storage drivers through inconsistent provisioning, making performance and troubleshooting unpredictable from one node to the next.

Anti-Pattern

Treating Bind Mounts and Named Volumes as Interchangeable

Using a host-path bind mount in production the same casual way it is used in local development, without accounting for the fact that a bind mount depends on a specific path existing on that exact host, which makes it far less portable than a named volume managed by the engine itself.

Anti-Pattern

Assuming Privilege Model Without Checking

Deploying a rootless-only platform configuration onto tooling or images that quietly assume the standard, privileged overlay2 setup is available, only discovering the mismatch when containers fail to start.

!
The Pattern Behind the Anti-Patterns

Every anti-pattern above traces back to ignoring one of two facts from earlier chapters: either it forgets that copy-up cost is paid on large-file writes inside the layered filesystem (Chapter 3), or it forgets that the storage driver never cleans up after itself automatically (Chapter 4 and Chapter 7). Internalizing those two facts is enough to recognize nearly every storage-driver mistake on sight.

10Best Practices & Common Mistakes

A condensed, practical checklist — what to consistently do, and where teams most often slip.

PracticeWhy It HelpsCommon Mistake to Avoid
Use overlay2 unless a specific need says otherwiseBest balance of speed, stability, and kernel support for most workloadsSwitching drivers based on outdated forum advice rather than a measured need
Mount volumes for write-heavy, large-file dataAvoids repeated, expensive copy-up operations and prevents accidental data lossLetting a database write its data files into the default writable layer
Keep image layer stacks shallowReduces per-file lookup overhead and avoids driver-specific stacking limitsLetting layer count grow unchecked with no consolidation discipline
Schedule regular cleanup of stopped containers and dangling layersPrevents silent, unbounded disk usage growth under the storage driverOnly cleaning up reactively once a host unexpectedly runs low on disk space
Keep host kernels currentoverlay2’s correctness and performance are tied directly to kernel-level OverlayFS supportRunning production workloads on very old, unpatched kernels
Standardize the storage driver across a fleetKeeps performance and troubleshooting predictable from node to nodeAllowing inconsistent provisioning to leave different hosts on different drivers
Monitor write latency and layer depth as distinct metricsSurfaces storage-driver problems before they appear as vague application slownessOnly watching general host disk space and missing driver-specific signals
Decide the privilege model before the storage driverAvoids discovering a rootless-versus-overlay2 mismatch mid-rolloutAssuming the standard privileged setup is available without verifying it
Prefer named volumes over host-path bind mounts in productionKeeps persistent data portable and independent of any single host’s exact filesystem layoutReusing local-development bind-mount habits directly in production
Everyday Analogy

Choosing and tuning a storage driver is a lot like choosing how a shared office kitchen handles cookbooks versus grocery lists. The cookbooks — big, rarely-changing references — sit on a shared shelf everyone reads from without needing their own copy, exactly like the shared, read-only lowerdir layers. A grocery list, though, is something each person genuinely needs to scribble on constantly; handing everyone a fresh, personal notepad for that, instead of making them photocopy and mark up a shared cookbook page every time they need to jot something down, is exactly what a volume does for write-heavy data. The kitchen runs smoothly only when the rarely-changing shared references and the constantly-changing personal notes are kept in the right place from the start.

11Real-World & Industry Examples

Storage driver choice and tuning is a well-documented, practical lever that large engineering organizations have pulled to solve concrete production problems.

Docker Inc. — The Industry-Wide Shift From devicemapper to overlay2

Docker’s own engineering team and the broader container ecosystem publicly documented a multi-year shift away from devicemapper as the recommended default, precisely because devicemapper’s default configuration in many early setups was fragile and performed poorly under real production load, while overlay2, once it matured and gained solid kernel support, offered a simpler, faster, and more predictable default for the vast majority of users.

Uber — Volumes for Stateful Workloads at Scale

Infrastructure teams running large fleets of containerized services, including data-intensive systems, have described the discipline of strictly separating stateful, write-heavy data onto dedicated volumes rather than the container’s own writable layer, precisely to avoid both the copy-on-write performance penalty and the risk of silent data loss when a container is rescheduled onto a different host.

Red Hat — fuse-overlayfs for Rootless Container Adoption

As rootless container execution became an increasingly important security requirement in regulated and multi-tenant environments, engineering work around tools associated with Red Hat’s container ecosystem helped popularize fuse-overlayfs specifically as the mechanism that lets unprivileged users get overlay-style, copy-on-write storage without needing root access to mount a kernel filesystem directly.

Large Kubernetes Platform Operators — Standardizing on a Single Driver Fleet-Wide

Organizations running large, multi-thousand-node Kubernetes fleets have described the operational value of enforcing one single, standardized storage driver configuration across every node image, precisely so that a performance issue or an incident investigation never has to first ask “which storage driver is this particular node even using” before getting to the real question.

Google — Minimal, Cache-Friendly Base Layers to Maximize overlay2’s Sharing Benefits

Google’s public engineering guidance around container images has long emphasized building on a small number of minimal, standardized base layers, which pairs directly with overlay2’s page-cache-sharing behavior described in Chapter 5: the more containers across a fleet share byte-identical lower layers, the more that shared page cache benefit compounds, turning a storage-driver-level efficiency into a fleet-wide memory and disk saving.

Fewer
CONFIGURATION SURPRISES WHEN ONE STORAGE DRIVER IS STANDARDIZED ACROSS AN ENTIRE FLEET
Faster
WRITE PERFORMANCE FOR STATEFUL WORKLOADS ONCE THEIR DATA MOVES ONTO DEDICATED VOLUMES
Safer
ROOTLESS OPERATION ENABLED BY USERSPACE OVERLAY IMPLEMENTATIONS LIKE FUSE-OVERLAYFS

12Frequently Asked Questions

Q1Is overlay2 always the right choice?

For the large majority of workloads on modern Linux kernels, yes. It offers the best general-purpose mix of speed, stability, and support. The exceptions are specific: hosts needing native filesystem snapshotting may prefer btrfs or zfs, and rootless setups often need fuse-overlayfs instead, since the standard kernel overlay driver has traditionally required elevated privileges to mount.

Q2Why does my container feel slow only when writing to certain files?

This is almost always copy-on-write cost. If those files originally came from the image’s read-only layers and are large, the very first write to each one pays the cost of copying the entire file up into the writable layer before the change can be applied. Once copied up, later writes to that same file are fast again. Moving that data path onto a dedicated volume removes the copy-up cost entirely.

Q3What actually happens to a container’s writes when the container is removed?

Everything written into that container’s writable layer is deleted along with the container itself, because the writable layer is created fresh per container and is never part of the shared, persistent image layers. Any data meant to survive the container’s removal has to live in a volume, which is intentionally stored outside this disposable writable layer.

Q4Is a storage driver the same thing as a volume driver?

No, and this is a common point of confusion. The storage driver manages the layered image filesystem and each container’s disposable writable layer. A volume driver is a separate mechanism for managing persistent storage that lives outside that layered system entirely, and it can even be backed by a completely different underlying storage technology, such as networked or cloud-based storage, independent of whichever storage driver the host happens to be using.

Q5Can switching storage drivers on an existing host cause data loss?

Generally, yes, in the sense that existing images and any data sitting inside container writable layers are stored in a format specific to the driver that created them, and switching drivers on a host typically means starting from an empty storage area under the new driver. This is exactly why storage-driver choice is treated as a foundational, host-provisioning-time decision rather than something casually changed on a running production system, and why volumes — kept driver-independent — are the correct home for anything that must survive such a change.

Q6Does a deeper layer stack always mean worse performance?

Not dramatically for ordinary read operations under overlay2’s typical stacking depths, since the kernel’s lookup is efficient. But it is not free either, and extremely deep stacks can approach hard limits on some driver-and-kernel combinations, in addition to simply making an image harder to reason about and maintain. Keeping layer stacks reasonably shallow, as covered in Chapter 8, remains good discipline even though the per-layer cost of ordinary reads is small.

Q7Why would anyone still choose devicemapper, btrfs, or zfs over overlay2 today?

Almost always for one specific capability overlay2 does not natively provide. btrfs and zfs offer native, filesystem-level snapshotting and strong built-in data-integrity checks that some teams want directly at the storage layer rather than layered on top separately. devicemapper’s role today is mostly legacy, kept running on older systems that adopted it before overlay2 matured, rather than chosen fresh for new deployments. In every case, the decision should be traceable to a specific requirement overlay2 does not meet, not a general preference.

Q8Can I mix storage drivers on the same physical host for different workloads?

A single running container engine instance typically operates under one active storage driver at a time for its managed images and containers, so mixing drivers usually means running genuinely separate engine instances or separating workloads onto different hosts entirely, rather than switching per container. This is one more reason standardizing on one driver per host, as covered in Chapter 8, keeps operations simpler than trying to run a mixed configuration.

13Summary and Key Takeaways

Key Takeaways

  • A storage driver translates the layered image system into one unified, writable filesystem a container can use, presenting a merged view built from shared read-only layers plus one disposable writable layer per container.
  • overlay2 is the modern default, built on the Linux kernel’s own OverlayFS, using the four named directories — lowerdir, upperdir, workdir, and merged — to resolve reads and handle writes.
  • Copy-on-write is the core mechanic to understand: reads from unmodified files are fast and cache-shared, while the first write to a large file already sitting in a lower layer pays a real, size-proportional copy-up cost.
  • A container’s writable layer is intentionally disposable — anything that must survive a container’s removal belongs in a volume, which lives outside the layered storage-driver system entirely.
  • Alternative drivers exist for real, specific reasons — devicemapper’s legacy role, btrfs and zfs for native snapshotting, vfs as a simple non-copy-on-write fallback, and fuse-overlayfs for rootless, unprivileged operation.
  • Storage-driver health should be monitored directly, tracking disk usage under the driver’s own data root, write latency, and maximum layer depth, rather than relying on general host disk metrics alone.
  • Real engineering organizations — Docker Inc., Uber, Red Hat, and large Kubernetes platform operators — have all made deliberate, documented storage-driver decisions to solve concrete performance, reliability, and security problems in production.