The Architecture of Container Filesystem Layers
Docker containers rely on the ability to stack multiple read-only filesystem images into a single, unified view. This is achieved through Union File Systems, with 'overlay2' serving as the current standard driver on Linux. By leveraging the kernel's overlayfs, Docker minimizes storage overhead and accelerates startup times by sharing base layers across multiple containers.
How Overlayfs Functions
The overlay2 driver works by combining two distinct directories on the host filesystem: the 'lowerdir' and the 'upperdir.' The lowerdir represents the read-only image layers, while the upperdir provides a writable scratch space for the container instance. A 'merged' directory provides the unified view that the container process actually interacts with.
When a file is modified within a container, the driver employs a 'copy-up' mechanism:
Read: If a file exists in the lowerdir, it is read directly from the image.
Modify: When a write operation occurs, the file is copied from the lowerdir to the upperdir.
Write: Subsequent changes are applied only to the copy in the upperdir, effectively masking the original file in the lowerdir.
Trade-offs and Performance Implications
While overlay2 is highly efficient, it introduces specific overheads. The copy-up operation can be expensive for large files, as it requires an immediate copy from the read-only layer to the writable layer before the write can proceed. Furthermore, excessive layering can degrade directory lookup performance due to the kernel having to traverse the stack of lower directories to locate a file's inode.
Engineers should be mindful of 'layer bloat.' Keeping image layers thin and minimizing the number of layers in a Dockerfile directly impacts the performance of the overlay2 driver. Because each file modification in a container creates a divergence from the original image, high-churn workloads—such as log writing or temporary file creation—should always be offloaded to Docker volumes to bypass the overhead of the overlay filesystem entirely.
Understanding these mechanics allows for more predictable performance in containerized environments. By treating the container writable layer as a temporary scratch space and relying on volumes for persistent state, engineers can optimize both storage utilization and I/O throughput.
