Union Filesystems in Depth

Union Filesystems in Depth

How stacking read-only and writable layers on top of each other quietly powers every container you have ever run, every live Linux USB stick you have booted, and every "instant" software update on your phone.

Every time you run docker run nginx and a container starts in under a second, something quietly clever has just happened underneath your feet. Docker did not copy an entire operating system’s worth of files onto your disk. It did not unpack gigabytes of data fresh from the image. Instead, it took several folders that already existed on your disk, stacked them on top of one another like sheets of glass, and showed you the result as if it were a single, ordinary folder. That trick is called a union filesystem, and once you understand how it works, you start seeing it everywhere: in containers, in live-boot USB sticks, in phone updates, and in build systems. This guide walks through what a union filesystem actually is, how it works internally, where it shines, where it bites back, and how the biggest names in the industry use it in production.

1What Exactly Is a Union Filesystem?

Before we go anywhere near Docker, kernels, or copy-on-write, let’s build the idea from nothing.

A regular filesystem is a single, flat source of truth. When you open a file, the operating system looks in exactly one place: the disk (or partition, or volume) where that filesystem lives. A union filesystem breaks that assumption. Instead of one source of truth, it lets you stack several directories — called layers — on top of each other, and then presents them to every program on your computer as though they were a single, unified directory. The word “union” is used in the mathematical sense: just like the union of two sets combines their members into one collection, a union filesystem combines the contents of several directories into one visible view.

Here is the part that makes it genuinely useful rather than just a curiosity: the layers do not have to be equal. Typically, one or more layers are marked read-only, and exactly one layer on top is marked writable. Any program that reads a file walks down through the stack until it finds that file in the topmost layer that has it. Any program that writes or deletes a file only ever touches the writable layer on top — the read-only layers underneath are never modified, no matter what happens above them.

Everyday Analogy

Picture a stack of transparent sheets on an overhead projector, the kind teachers used before digital projectors existed. The bottom sheet has a printed map of a city. The second sheet, also transparent, has hand-drawn bus routes added on top. The third sheet has today’s traffic notes scribbled on with a dry-erase marker. Looking down through the stack, you see one combined picture: the map, the routes, and the traffic notes, all merged into a single image. If you erase something on the top sheet, the map underneath is untouched — you have only changed what is visible on top. That is precisely what a union filesystem does with directories instead of transparent sheets.

i
Key Insight

A union filesystem does not merge files by copying their bytes together. It merges directory listings. The underlying files stay exactly where they are, on whichever layer they were created. The “merging” is an illusion created at the moment you look inside the combined folder — nothing is physically moved or duplicated until you try to change something.

This single idea — many layers, one visible view, changes isolated to the top — is the entire foundation of union filesystems. Everything else in this guide is really just working out the consequences of that one idea: what happens when you edit a file that lives in a lower layer, what happens when you delete something, what happens when two layers have a file with the same name, and how operating systems make all of this fast enough to use in production at massive scale.

2The Problem That Union Filesystems Solve

Good technology usually exists because copying gigabytes of data over and over was too slow, too wasteful, or both.

Imagine you want to run ten copies of the same web server on one machine, each with slightly different configuration files. Without a union filesystem, the naive approach is to copy the entire base operating system — every library, every binary, every configuration file — ten separate times onto disk. If that base system is 500 megabytes, you have just spent 5 gigabytes of disk space to store what is, in reality, the same data ten times over with only a handful of files actually different between the copies. Worse, creating each copy takes real time, because the operating system has to physically write every one of those files to disk before the new instance can start.

This exact problem showed up again and again across computing history, in slightly different clothes each time:

1

Plan 9 and BSD Union Mounts (late 1980s–1990s)

Researchers at Bell Labs building the Plan 9 operating system, and later BSD Unix developers, introduced the idea of mounting one directory “on top of” another so that both became visible at the same path. This was the conceptual birth of the union mount.

2

Translucent and Union Filesystems for Live Media (1990s–2000s)

As bootable CDs and later Live CDs became popular, developers needed a way to let a read-only disc “feel” writable — you could create files and change settings during a session, even though the CD itself obviously could not be altered. Early union-style filesystems layered a writable RAM disk on top of the read-only disc image.

3

UnionFS (2004) and AUFS (2006)

Researchers at Stony Brook University released UnionFS as a proper Linux kernel-level union filesystem. AUFS (“Another Union File System”) followed soon after as a more stable, better-performing rewrite, and became the default storage engine for early Docker.

4

OverlayFS Enters the Mainline Kernel (2014)

Linux kernel version 3.18 merged OverlayFS directly into the kernel itself, rather than requiring a separate patch or module. This gave union filesystems official, first-class support, and it quickly became the default storage driver for Docker and most container runtimes that followed.

Notice the pattern: every generation of this technology was solving the same underlying problem — how do you give many consumers the illusion of their own private, writable copy of something, without physically duplicating the data behind the scenes? Live CDs needed it so a read-only disc could feel interactive. Containers needed it so thousands of near-identical application environments could start instantly and share almost everything on disk. That shared motivation is why union filesystems became one of the quiet, foundational technologies of modern computing.

3Architecture & Core Components

Modern union filesystems, especially Linux’s OverlayFS, are built from a small handful of named directories that each have a very specific job.

Rather than the vague word “layer,” real implementations give each layer role a precise name. Understanding these names is the difference between reading a Docker inspect output as gibberish and reading it as a clear map of what is happening on disk.

Read-Only

lowerdir

One or more read-only directories forming the base of the stack. In Docker, each image layer (each instruction in a Dockerfile that changes the filesystem) becomes its own lowerdir. These are never modified once created, which is exactly what makes them safe to share across hundreds of containers at once.

Writable

upperdir

The single writable layer sitting on top of all the lowerdirs. Every file a running container creates, edits, or “deletes” is actually recorded here. When a container is removed, its upperdir is thrown away — the lowerdirs underneath were never touched, so the original image is untouched and ready to be used again.

Scratch Space

workdir

An internal directory the union filesystem uses as scratch space during operations like renames and atomic file moves. Applications never interact with it directly; it must live on the same physical filesystem as upperdir and is required for OverlayFS to guarantee that operations either fully succeed or fully fail, never leaving things half-done.

The Illusion

merged / mount point

The single directory that everything else in this chapter builds toward: the combined, unified view that applications actually see and interact with. When a container process lists files in its root directory, it is looking at the merged view, blissfully unaware that the data underneath is spread across a dozen separate lowerdirs and one upperdir.

Deletion Marker

Whiteout File

A special marker placed in upperdir that tells the union filesystem “pretend this file, which exists in a lower layer, does not exist anymore.” Deleting a file in a union filesystem never removes it from a read-only lower layer — it hides it with a whiteout instead.

Directory Trick

Opaque Directory

A directory in upperdir marked so that the union filesystem stops looking for its contents in any lower layer. This is how a container can completely replace the contents of a folder rather than merging new files into whatever a lower layer already put there.

graph TB
    subgraph Stack["Union Mount Stack"]
        L3["lowerdir 3 (base OS image layer)"]
        L2["lowerdir 2 (application dependencies layer)"]
        L1["lowerdir 1 (application code layer)"]
        UP["upperdir (this container's writable layer)"]
    end
    WD["workdir (internal scratch space)"]
    MERGE["merged / mount point (what the running process actually sees)"]
    L3 --> MERGE
    L2 --> MERGE
    L1 --> MERGE
    UP --> MERGE
    WD -. supports .-> UP
    MERGE --> APP["Application process reads and writes here"]
    

Fig. 1 — Every lowerdir contributes its files to the merged view; only upperdir ever changes.

?
Interviewer May Ask

“What is the difference between upperdir and workdir, and why does OverlayFS need both?” A strong answer explains that upperdir stores the actual user-visible changes, while workdir is purely internal plumbing OverlayFS uses to perform atomic operations safely — it is never exposed to the application and must sit on the same filesystem as upperdir for the kernel’s rename-based tricks to work.

4Internal Working: Copy-Up, Whiteouts, and Opacity

This is where the “magic” of union filesystems becomes a small set of concrete, learnable mechanics.

Copy-Up: How Editing a Read-Only File Actually Works

Suppose a file called config.txt lives only in a lowerdir, and a running container tries to open it for writing. The lowerdir is read-only, so the kernel cannot simply edit the bytes in place. Instead, OverlayFS performs an operation called copy-up: it copies the entire file from the lowerdir into upperdir, byte for byte, and only then applies the write to that new copy in upperdir. From that moment forward, every read of config.txt finds the version in upperdir first, because upperdir is always checked before any lowerdir. The original file in the lowerdir is left completely untouched, which is exactly why the same base image can be safely reused by a thousand other containers running at the same time.

Everyday Analogy

Think of a library book you are not allowed to write in. If you want to add your own notes, you photocopy the page, scribble your notes on the copy, and keep the copy in your own folder. The original page in the library book is never touched, so the next person who borrows the book still gets the clean, unmarked original. Copy-up is the filesystem doing exactly this photocopy-and-annotate trick automatically, the instant you try to write to a file that only exists in a read-only layer.

Whiteouts: How “Deleting” a File in a Lower Layer Works

Deletion is trickier than it sounds, because the file you are “deleting” might physically live in a read-only lowerdir that the current layer has no permission to touch. OverlayFS solves this with a whiteout: instead of removing the file, it creates a special character device file (traditionally with device numbers 0,0) inside upperdir, using the same filename. When the union filesystem builds its merged view and sees a whiteout marker for a name, it hides that name entirely from every layer below, even though the real file is still sitting untouched in the lowerdir. Delete a file, and from the outside it simply disappears — but underneath, nothing in the read-only layer was ever removed.

Opaque Directories: Replacing, Not Merging

Sometimes a container needs to completely replace a directory’s contents rather than adding new files alongside old ones. If you delete every file inside a directory one by one, OverlayFS would normally still merge in anything a lower layer contributes to that same directory name. To prevent this, OverlayFS marks the directory in upperdir as opaque using an extended file attribute. An opaque directory tells the merge logic: “stop looking in lower layers for this directory’s contents — everything you need is right here in upperdir.” Docker relies on this exact mechanism whenever a Dockerfile instruction removes an entire directory and replaces it with fresh contents.

!
Common Gotcha

Renaming a directory across layers, or moving a file from a lowerdir path to a different directory, can trigger a full copy-up of every file inside it — not just a lightweight rename. On very large directories, this “rename amplification” can turn what looks like an instant operation into a surprisingly slow one, and is a frequent source of unexpected latency spikes in container workloads that manipulate large directory trees.

?
Interviewer May Ask

“How does OverlayFS represent a deleted file that still exists in a lower, read-only layer?” The correct answer is the whiteout mechanism: a character device file with major and minor numbers 0,0 is created in upperdir under the same name, instructing the merge logic to hide that name from every layer beneath it.

5Data Flow & Lifecycle: Read, Write, and Delete Paths

Once you know the pieces from the last two chapters, tracing exactly what happens for each kind of file operation becomes mechanical.

sequenceDiagram
    participant App as Application Process
    participant Overlay as OverlayFS Merge Logic
    participant Upper as upperdir (writable)
    participant Lower as lowerdir (read-only)

    App->>Overlay: open("app.conf", READ)
    Overlay->>Upper: file present?
    Upper-->>Overlay: not found
    Overlay->>Lower: file present?
    Lower-->>Overlay: found, return contents
    Overlay-->>App: return contents from lowerdir

    App->>Overlay: open("app.conf", WRITE)
    Overlay->>Upper: file present?
    Upper-->>Overlay: not found
    Overlay->>Lower: copy-up file to upperdir
    Overlay->>Upper: apply write to new copy
    Overlay-->>App: write succeeds on upperdir copy

    App->>Overlay: delete("old.log")
    Overlay->>Upper: create whiteout marker for old.log
    Overlay-->>App: file now hidden from merged view
    

Fig. 2 — Reads fall through to the lowest layer that has the file; writes and deletes only ever touch upperdir.

OperationWhat Actually HappensLayer(s) Touched
Read a file that exists only in a lowerdirSearch proceeds top to bottom; the first layer containing the file serves it directly, no copying involvedRead-only lowerdir only
Write to a file that exists only in a lowerdirCopy-up: full file copied into upperdir first, then the write is applied to the new copylowerdir (read) + upperdir (write)
Write to a file that already exists in upperdirWrite is applied directly; no copy-up needed since the file is already at the topupperdir only
Delete a file that exists in a lowerdirA whiteout marker is created in upperdir under the same nameupperdir only (lowerdir untouched)
List a directory present across several layersDirectory entries from every layer are merged into one listing, with whiteouts removing hidden names and upperdir versions taking priority on name conflictsAll contributing layers
Container is removed entirelyupperdir is discarded; all lowerdirs remain completely intact and reusable by future containersupperdir deleted; lowerdirs untouched

The lifecycle of a typical container image tells this story end to end. A Dockerfile with five instructions that touch the filesystem produces five lowerdirs, stacked in build order. When you run a container from that image, Docker adds one fresh, empty upperdir and workdir on top, and mounts the whole stack as a single merged directory that becomes the container’s root filesystem. The application inside genuinely believes it has its own private, writable disk. In reality it is looking through five read-only layers shared with every other container using that image, plus one thin, private layer of its own changes. When the container stops and is removed, that thin private layer simply vanishes, and the five shared layers — untouched the entire time — are ready to back the next container instantly.

6Design Patterns & Anti-Patterns

Knowing the mechanism is one thing; knowing how to design systems around it well is another.

Pattern: Layered, Cacheable Build Images

Docker’s build system is really just an application of union filesystems to software packaging. Each instruction in a Dockerfile — installing a package, copying application code, setting an environment variable — produces exactly one new lowerdir layer. Because layers are content-addressed (identified by a hash of their contents), if you rebuild an image and only the last instruction changed, every layer above the unchanged instructions is reused straight from cache, and only the changed layer and anything above it needs to be rebuilt. This is why placing rarely-changing instructions (installing system dependencies) near the top of a Dockerfile and frequently-changing instructions (copying your application’s own source code) near the bottom dramatically speeds up rebuilds — the expensive, stable layers stay cached.

ADR-014 — Storage Driver Selection Accepted
Context

A platform team running a Docker-based CI system needed to choose between the overlay2 storage driver and the older devicemapper driver for their build agents, which each run hundreds of short-lived containers per day.

Decision

The team chose overlay2, the OverlayFS-based driver, because it is directly supported by the mainline kernel, avoids the extra block-device management overhead of devicemapper, and has become the de facto standard driver across the container ecosystem.

Consequences

Container start times improved noticeably because no loopback block devices needed to be allocated per container. The team did need to ensure their build servers used a filesystem (such as ext4 or xfs with d_type support enabled) that overlay2 requires to function correctly.

Pattern: Read-Only Base, Writable Session (Live Media)

Live Linux distributions apply the same layering idea in reverse order of intent, but identically in mechanism: the entire operating system sits in a read-only lowerdir sourced from a compressed disk image, and a small writable upperdir — often backed by RAM, or by a small writable partition on the USB drive — captures every change made during that session. This lets a completely read-only, tamper-proof base image feel fully interactive and writable to the user, without ever needing to modify the original protected image.

Anti-Pattern: Excessive Layer Counts

Every additional lowerdir adds a small amount of lookup overhead to every filesystem operation, because the kernel may need to check multiple layers before finding — or confirming the absence of — a file. Dockerfiles that chain dozens of tiny, separate RUN instructions rather than combining related steps into a single instruction create unnecessarily deep layer stacks. This does not just slow lookups slightly; it also bloats the image, since intermediate layers created by instructions like installing and then removing temporary files can leave “ghost” data taking up space in earlier layers even after later layers mark it deleted with a whiteout.

Anti-Pattern: Treating a Lowerdir as Mutable

A subtler mistake is architecting an application to assume it can write directly to what is actually a lowerdir path — for instance, bypassing the union mount and mounting a lower layer’s underlying directory directly for “faster” writes. This breaks the entire isolation model: changes become visible to every other consumer of that layer, defeating the purpose of the read-only base and potentially corrupting the shared image used by many other containers or sessions.

“A union filesystem’s real value isn’t that it merges files — it’s that it guarantees the base you started from is still there, unharmed, no matter what happened on top.”

7Advantages, Disadvantages & Trade-offs

Like every real engineering decision, union filesystems trade one set of costs for another set of benefits.

Advantages

  • Massive disk space savings when many instances share the same base layers, since the base is stored exactly once no matter how many containers use it
  • Near-instant “copy” creation — starting a new container is just mounting a new, empty upperdir on top of existing layers, not writing gigabytes of new data
  • Strong isolation between instances by default, since one container’s writes are invisible to every other container sharing the same lowerdirs
  • Simple, reliable rollback — deleting a corrupted or unwanted upperdir instantly restores the untouched base layers underneath
  • Efficient distribution — image registries like Docker Hub only need to transfer layers a machine does not already have cached locally

Disadvantages & Trade-offs

  • Write amplification on copy-up: editing one byte of a large file in a lowerdir still requires copying the entire file into upperdir first
  • Increased lookup latency as layer counts grow, since reads may need to traverse many layers before finding — or confirming the absence of — a file
  • Certain low-level filesystem features (some forms of file locking, specific extended attributes, hard links across layers) can behave inconsistently or are restricted, depending on the underlying filesystem and kernel version
  • Inode and page cache duplication: once a file is copied up, its data may temporarily exist in cache and on disk in two separate places, one per layer, until the lower one is garbage collected with the image
  • Rename operations across the layer boundary can be surprisingly expensive on large directories, due to the rename-amplification effect covered in Chapter 4

None of these trade-offs make union filesystems a poor choice — quite the opposite, since the industry’s overwhelming adoption of them for containers proves the benefits outweigh the costs for the vast majority of workloads. But they do explain why certain specialized workloads, particularly databases that perform constant, heavy in-place writes to large files, are usually configured to use dedicated volumes that bypass the union mount entirely rather than writing through several layers of copy-up logic on every update.

8Security Considerations

Because union filesystems sit directly underneath container isolation, their security properties matter for the entire platform built on top of them.

Shared Read-Only Layers as an Attack Surface

Because many containers share the exact same lowerdirs, a vulnerability that allows one container to somehow write directly into a lowerdir path — bypassing the intended union mount — would compromise every other container sharing that layer, not just the attacker’s own container. This is precisely why container runtimes enforce strict permission boundaries and mount namespaces around upperdir and lowerdir paths, ensuring a compromised container process genuinely cannot reach outside its own upperdir.

!
Security Warning

Never grant a container process direct filesystem access to the host paths backing lowerdir or upperdir outside of the intended union mount. Doing so, even for debugging convenience, breaks the isolation guarantee the entire union filesystem model depends on and can let one container tamper with the shared base image used by many others.

Whiteout and Opaque Directory Trust

Whiteout markers and opaque-directory attributes are just files and metadata like any other — which means an image containing maliciously crafted whiteouts could, in theory, be used to hide files or make a scanning tool believe certain paths do not exist, when in fact the data is still present in an underlying layer. This is one reason security scanning tools for container images increasingly inspect each layer independently, rather than only inspecting the final merged view, so that nothing hidden by a whiteout in a later layer goes unnoticed.

Permission and Ownership Consistency

When copy-up duplicates a file from a lowerdir into upperdir, the file’s ownership and permission bits are preserved by default. However, misconfigured user-namespace remapping (used to make container processes run as an unprivileged user on the host, even if they believe they are root inside the container) can create situations where copied-up files end up with unexpected ownership, which has historically been a source of subtle privilege-related bugs in container platforms.

Defense in Depth Around Union Mounts

Production container platforms typically combine the union filesystem’s natural isolation with additional layers of defense: Linux namespaces to isolate the process’s view of the filesystem tree, control groups to limit resource usage, and mandatory access control frameworks such as SELinux or AppArmor to restrict what the container process can do even if it somehow gains unexpected filesystem access. The union filesystem is one layer of a much larger defense-in-depth strategy, never the only one.

?
Interviewer May Ask

“If lowerdirs are shared read-only across many containers, what stops one compromised container from affecting the others?” A strong answer names the combination of the union filesystem’s own read-only enforcement on lowerdir, plus OS-level isolation (namespaces, mount restrictions, and mandatory access control) that prevents a container process from ever reaching the lowerdir’s real host path directly.

9Monitoring, Logging & Metrics

You cannot manage disk pressure on a container host without understanding what a union filesystem’s numbers actually mean.

A common source of confusion is that traditional disk usage tools were never designed with layered storage in mind. Running a plain directory-size check on a container’s merged view can report a number close to the entire image size, even though almost all of that data is shared, read-only, and already counted once for every other container using the same base layers. Platform teams instead rely on tools built specifically for layered storage, such as Docker’s own system df reporting, which separately reports the space consumed by images, the space consumed by each container’s own writable layer, and reclaimable space from stopped containers and unused layers.

~90%
TYPICAL SHARED BASE LAYER SIZE ACROSS RELATED IMAGES IN A FLEET
<10 MB
TYPICAL WRITABLE UPPERDIR SIZE FOR A SHORT-LIVED WORKER CONTAINER
3–8
COMMON NUMBER OF EFFECTIVE LAYERS IN A WELL-OPTIMIZED PRODUCTION IMAGE

What matters most in production monitoring is tracking the growth of upperdir directories specifically, since that is the only part of the storage footprint that grows unpredictably during a container’s lifetime — the lowerdirs are fixed the moment the image is built. Teams running many long-lived containers typically alert on individual upperdir growth rather than total merged filesystem size, because a single misbehaving process writing an ever-growing log file directly into the container’s writable layer, instead of to a mounted volume, is a frequent and easily missed cause of a host quietly running out of disk space.

i
Practical Tip

Any file a container writes frequently and does not need to persist after the container exits — logs, temporary caches, scratch data — should be mounted as a dedicated volume rather than being written directly into the union filesystem’s writable layer. This both avoids unnecessary copy-up overhead and makes disk usage far easier to reason about and monitor.

10Best Practices & Common Mistakes

Most union-filesystem problems in production trace back to a small, well-known set of avoidable mistakes.

Best Practice

Order Layers by Change Frequency

Place instructions that rarely change (installing system packages) before instructions that change often (copying application source code), so rebuilds reuse the maximum amount of cached, unchanged lowerdir layers.

Best Practice

Route Write-Heavy Paths to Volumes

Databases, log directories, and caches should be mounted as dedicated volumes rather than written through the union mount’s copy-up path, avoiding both performance overhead and unpredictable upperdir growth.

Best Practice

Keep Layer Count Reasonable

Combine related setup steps into fewer, more purposeful instructions rather than dozens of tiny ones, reducing both lookup overhead and the number of intermediate “ghost data” layers left behind.

Common Mistake

Deleting Files in an Earlier Layer to “Save Space”

Removing a large file in a later build instruction does not shrink the image — the file still physically exists in the earlier, already-built lowerdir. Only a whiteout marker is added; the underlying bytes remain and still count toward image size.

Common Mistake

Assuming Upperdir Data Survives Container Removal

Any data relied upon after a container’s life ends must live in a volume or be exported elsewhere; the writable upperdir is deleted the moment the container is removed, with no separate backup by default.

Common Mistake

Ignoring the Underlying Filesystem’s Requirements

OverlayFS has specific requirements of the filesystem hosting its layers, such as d_type directory entry support. Running it on an unsupported underlying filesystem can cause subtle, hard-to-diagnose correctness issues rather than a clear error.

11Real-World & Industry Examples

Union filesystems are not a niche curiosity — they quietly run some of the most widely used software delivery systems on the planet.

Docker and containerd

Docker’s overlay2 storage driver, built on OverlayFS, is the default engine behind how every Docker image is stored and how every container’s writable layer is created. containerd, the container runtime that also powers Kubernetes clusters at companies including Google and countless cloud providers, uses the same overlay-based snapshotting model to manage image layers efficiently at massive scale, starting containers by mounting layers rather than copying data.

Live Linux Distributions

Distributions designed to run entirely from a USB stick or DVD — historically Knoppix, and later live editions of Ubuntu and Debian — use a union filesystem to layer a small, writable, RAM-backed directory on top of the read-only, compressed system image on the removable media. This is what allows you to install new software, change settings, and create files during a live session, even though the disc or USB image itself is never modified.

Android’s Read-Only System Partition Model

Modern Android devices keep their core system partition strictly read-only for security and update-reliability reasons, while still needing to apply vendor customizations and runtime overlays without duplicating the entire system image. Overlay-based mounting techniques allow Android to layer these customizations on top of the protected base system image, keeping the verified, signed base untouched while still presenting a combined, working filesystem to apps and services.

Continuous Integration and Build Farms

Companies running large fleets of build agents, where thousands of short-lived containers spin up and tear down every hour to compile code and run tests, depend heavily on union filesystems to make that churn economically viable. Without shared, read-only base layers, each build agent would need its own full copy of every build tool and dependency, multiplying both storage costs and container startup latency across the fleet.

Industry Pattern — Registry Layer Deduplication Widely Adopted
Observation

Container image registries store layers by content hash. When a new image shares a base layer with an existing image already in the registry, that layer is stored exactly once, regardless of how many images reference it.

Effect

Pulling a new image that shares layers with images already present on a machine only requires downloading the layers that are actually new, which is why updating an application container is often nearly instant compared to a fresh install of the same image on a machine that has never pulled it before.

12Frequently Asked Questions

Q1Is a union filesystem the same thing as OverlayFS?

No — OverlayFS is one specific, modern implementation of the broader union filesystem concept, and the one built directly into the mainline Linux kernel today. Earlier implementations such as UnionFS and AUFS applied the same underlying idea using different internal mechanisms and had different trade-offs and compatibility characteristics.

Q2Does using a union filesystem slow down my application?

For typical read-heavy workloads, the overhead is small enough to be unnoticeable, since reads that hit a file already present in upperdir, or in the topmost lowerdir containing it, are close to as fast as a normal filesystem lookup. The overhead becomes more noticeable for workloads with heavy write patterns to large files stored only in a lowerdir, due to the copy-up cost described in Chapter 4.

Q3What happens if the same file exists in two different lowerdirs?

The layer closer to the top of the stack wins. If lowerdir 2 sits above lowerdir 3 and both contain a file named settings.conf, the merged view shows the version from lowerdir 2, and the version in lowerdir 3 is simply shadowed — it still exists physically, but it is invisible in the merged view.

Q4Can a union filesystem have more than one writable layer at a time?

In the common OverlayFS model, no — there is exactly one upperdir per mount. If you need what looks like multiple independent writable views of the same base, you create multiple separate union mounts, each with its own upperdir and workdir but sharing the same underlying lowerdirs, which is precisely how many containers share one base image simultaneously.

Q5Why do container images build faster the second time?

Because each unchanged Dockerfile instruction maps to an unchanged, already-built lowerdir layer, the build system can reuse those cached layers directly instead of recomputing them. Only the layers from the first changed instruction onward need to be rebuilt, which is why editing only your application’s final “copy source code” step typically results in a near-instant rebuild.

Q6Is data in a lower, read-only layer ever actually deleted from disk?

Not by the act of “deleting” it from within a container. A whiteout only hides the file from the merged view; the bytes remain on disk in the lowerdir until that entire image, and every layer that makes it up, is explicitly removed and garbage collected by the container runtime.

13Summary and Key Takeaways

What to Remember

  • A union filesystem stacks several directories and shows them as one. The bottom layers are typically read-only; exactly one layer on top is writable, and reads always search top to bottom for the first layer that has the file.
  • Copy-up is the core write mechanism. Editing a file that only exists in a read-only layer copies it into the writable layer first, so the original in the read-only layer is never modified.
  • Whiteouts and opaque directories are how deletion and replacement work. Nothing is ever physically removed from a read-only lower layer — it is simply hidden from the merged view.
  • Containers are the flagship use case, but not the only one. Live Linux distributions, Android’s read-only system partition model, and CI build farms all rely on the same layering trick for different reasons.
  • The main trade-off is write amplification and lookup depth versus enormous storage and startup-time savings — which is exactly why write-heavy workloads like databases are routed to dedicated volumes instead.
  • Security depends on layers staying properly isolated. Union filesystems provide strong isolation by design, but that guarantee only holds when the surrounding platform (namespaces, permissions, access control) enforces it correctly.
  • Monitoring should focus on upperdir growth, not total merged size, since the writable layer is the only part of a container’s storage footprint that changes unpredictably over its lifetime.