# Understanding Whiteout Files in Dive's Container Image Analysis

> Learn how whiteout files in Dive's container image analysis reveal deleted files and directories in upper Docker layers, ensuring accurate storage calculations and layer state reconstruction.

- Repository: [Alex Goodman/dive](https://github.com/wagoodman/dive)
- Tags: internals
- Published: 2026-03-07

---

**Whiteout files in Dive's analysis are overlay filesystem markers that indicate when files or directories have been deleted in upper Docker image layers, enabling the tool to accurately reconstruct layer state and calculate storage efficiency.**

When analyzing Docker and OCI images, the open-source tool Dive must interpret special filesystem entries called whiteout files to properly visualize layer changes. These markers, implemented in the `wagoodman/dive` repository, allow Dive to distinguish between files that persist from lower layers versus those explicitly removed in subsequent layers.

## What Are Whiteout Files in Container Images?

Docker and OCI images use **overlay-whiteout files** to record deletions within layered filesystems. When a file or directory present in a lower layer is deleted in an upper layer, the overlay filesystem creates a special marker file rather than actually removing the underlying data.

There are two primary types of whiteout markers:

- **Regular whiteouts** – Files prefixed with `.wh.` indicate that a specific file or directory has been deleted. For example, [`.wh.config.yaml`](https://github.com/wagoodman/dive/blob/main/.wh.config.yaml) signals the removal of [`config.yaml`](https://github.com/wagoodman/dive/blob/main/config.yaml).
- **Opaque whiteouts** – The special marker `.wh..wh..opq` indicates that an entire directory has been replaced or deleted, instructing the overlay driver to ignore all contents from lower layers.

## How Dive Detects and Filters Whiteout Markers

Dive implements whiteout detection in the `dive/filetree` package, distinguishing between these marker types to build accurate file trees for each image layer.

### Whiteout Prefix Constants in file_tree.go

The recognition patterns for whiteout files are defined in [`dive/filetree/file_tree.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/file_tree.go) at lines 18-20:

```go
const (
    whiteoutPrefix       = ".wh."
    doubleWhiteoutPrefix = ".wh..wh.."
)

```

These constants enable the file tree parser to identify deletion markers during tree construction.

### Node Creation Logic in file_node.go

The core filtering logic resides in [`dive/filetree/file_node.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/file_node.go). When adding paths to the tree via the `AddPath` method, Dive checks for opaque whiteouts at lines 91-94:

```go
if strings.HasPrefix(name, doubleWhiteoutPrefix) {
    return nil
}

```

For regular whiteout files, the `IsWhiteout()` method at lines 264-267 provides detection:

```go
func (node *FileNode) IsWhiteout() bool {
    return strings.HasPrefix(node.Name, whiteoutPrefix)
}

```

When displaying paths, Dive strips the whiteout prefix using `strings.TrimPrefix` at lines 285-289 to show the original filename that was deleted.

## Impact on Efficiency Calculations

Whiteout files directly affect Dive's storage efficiency scoring. When a whiteout file indicates directory removal, Dive must account for the total size of all hidden children to accurately reflect the deletion's impact.

In [`dive/filetree/efficiency.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/efficiency.go) (lines 57-86), the efficiency calculation logic walks the previous stacked tree to sum the sizes of files hidden by whiteout markers. This ensures that removing a directory via whiteout correctly reduces the efficiency score by the cumulative size of all deleted contents, not just the marker file itself.

## Practical Implementation Examples

### Detecting Regular Whiteout Files

When processing a standard whiteout marker, Dive creates a node to track the deletion but handles it differently than regular files:

```go
tree := filetree.NewFileTree()

// Regular file – a node is created
node, _, _ := tree.AddPath("/etc/config.yaml", dive.FileInfo{})
fmt.Println(node.Name) // "/etc/config.yaml"

// Whiteout file – node is marked as deletion
// The IsWhiteout() method returns true for ".wh.config.yaml"

```

### Filtering Opaque Whiteout Markers

Opaque whiteouts are completely discarded during tree construction:

```go
node, _, err := tree.AddPath("/var/lib/.wh..wh..opq", dive.FileInfo{})
// node == nil and err == nil – the opaque marker is discarded entirely

```

This behavior is verified in [`dive/filetree/file_tree_test.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/file_tree_test.go) at lines 327-343, confirming that opaque whiteouts create no tree nodes.

### Calculating Efficiency with Directory Whiteouts

When scoring layer efficiency, Dive accounts for removed directory contents:

```go
score, inefficient := filetree.Efficiency([]*filetree.FileTree{lower, upper})
// score reflects the total size of files removed via whiteout markers
// inefficient contains paths with significant size reduction from deletions

```

The implementation in [`efficiency.go`](https://github.com/wagoodman/dive/blob/main/efficiency.go) specifically handles cases where `.wh.` prefixed entries represent directories, walking the lower layer tree to accumulate the total bytes freed by the deletion.

## Summary

- **Whiteout files** are overlay filesystem markers indicating deleted files or directories in Docker image layers.
- **Dive filters opaque whiteouts** (`.wh..wh..opq`) entirely, while tracking regular whiteouts (`.wh.`) to represent deletions in the file tree.
- **Detection constants** are defined in [`dive/filetree/file_tree.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/file_tree.go), with filtering logic in [`dive/filetree/file_node.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/file_node.go).
- **Efficiency calculations** in [`dive/filetree/efficiency.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/efficiency.go) sum the sizes of hidden children when directories are removed via whiteout markers.
- **Unit tests** in [`dive/filetree/file_tree_test.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/file_tree_test.go) verify that whiteout files are handled correctly during tree construction.

## Frequently Asked Questions

### What do whiteout files represent in Docker image layers?

Whiteout files represent deletion operations in overlay filesystems. When a file is deleted in an upper layer but exists in a lower layer, Docker creates a `.wh.` prefixed marker to hide the underlying file without modifying the read-only lower layer. This allows the union filesystem to present a coherent view where the file appears deleted while preserving the original image data.

### How does Dive distinguish between regular and opaque whiteout files?

Dive distinguishes these markers using prefix detection constants defined in [`dive/filetree/file_tree.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/file_tree.go). Regular whiteouts use the `.wh.` prefix, while opaque whiteouts use `.wh..wh..`. The `AddPath` method in [`dive/filetree/file_node.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/file_node.go) checks for the double prefix first and returns `nil` to skip opaque markers entirely, whereas regular whiteouts are processed as deletion indicators.

### Why does Dive ignore opaque whiteout files when building the file tree?

Opaque whiteouts (`.wh..wh..opq`) indicate that an entire directory has been replaced in the upper layer, meaning all contents from lower layers should be disregarded. Dive ignores these markers because the directory replacement is implicitly handled by the presence of the new directory contents; creating a node for the opaque marker itself would add unnecessary clutter to the tree visualization.

### How do whiteout files affect Dive's efficiency scoring?

When calculating storage efficiency, Dive treats whiteout files as indicators of data removal. If a whiteout file represents a directory, the efficiency algorithm in [`dive/filetree/efficiency.go`](https://github.com/wagoodman/dive/blob/main/dive/filetree/efficiency.go) walks the previous layer's tree to sum the total size of all hidden children. This ensures the efficiency score accurately reflects the bytes freed by deletions, preventing removed data from being counted as wasted space in the final image analysis.