# How Dive Handles Docker Daemon, Podman, and Archive Image Sources

> Dive abstracts image fetching from Docker, Podman, and archives into a unified structure for easy layer analysis. Discover how Dive handles diverse image sources.

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

---

**Dive abstracts image fetching through a Resolver interface that normalizes Docker daemon, Podman, and local archive sources into a unified `*image.Image` structure for layer analysis.**

Dive is an open-source tool for exploring container image layers and detecting wasted space. According to the `wagoodman/dive` source code, the tool implements a pluggable architecture that handles multiple image sources—including Docker daemon, Podman, and local tar archives—through a consistent abstraction layer defined in [`dive/image/resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/resolver.go).

## The Resolver Interface Architecture

At the core of Dive's multi-source support is the **Resolver** interface. This contract declares three key operations that every image source must implement:

- **Fetch**: Retrieve an image by ID or reference from the source
- **Build**: Construct an image from a Dockerfile or build context
- **Extract**: Pull out layer contents for detailed analysis

By coding against this interface, Dive’s analysis engine—responsible for calculating efficiency scores and rendering the terminal UI—remains completely agnostic to whether the image came from a local Docker daemon, a remote Podman socket, or a tar file on disk.

## Detecting and Routing Image Source Types

When you invoke Dive with an image reference, the tool first determines which resolver to use. The function `DeriveImageSource` in [`dive/get_image_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/get_image_resolver.go) parses the URL scheme to classify the source:

```go
func DeriveImageSource(image string) (ImageSource, string) {
    s := strings.SplitN(image, "://", 2)
    // …
    switch scheme {
    case "docker":        return SourceDockerEngine, imageSource
    case "podman":        return SourcePodmanEngine, imageSource
    case "docker-archive":return SourceDockerArchive, imageSource
    case "docker-tar":    return SourceDockerArchive, imageSource
    }
    return SourceUnknown, ""
}

```

The `GetImageResolver` function then maps these enum values to concrete implementations:

| ImageSource | Resolver Implementation | Source File |
|-------------|----------------------|-------------|
| `SourceDockerEngine` | `docker.NewResolverFromEngine()` | [`dive/image/docker/engine_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/docker/engine_resolver.go) |
| `SourcePodmanEngine` | `podman.NewResolverFromEngine()` | [`dive/image/podman/resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/podman/resolver.go) |
| `SourceDockerArchive` | `docker.NewResolverFromArchive()` | [`dive/image/docker/archive_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/docker/archive_resolver.go) |

## Docker Daemon Resolution

The **Docker Engine Resolver** in [`dive/image/docker/engine_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/docker/engine_resolver.go) communicates directly with the Docker daemon using the official Docker client library.

When fetching an image, the `fetchArchive` method:
1. Creates a client with `client.NewClientWithOpts` and `determineDockerHost` for host detection
2. Pulls the image automatically if it’s missing locally
3. Exports the image via `ImageSave` to obtain a tar stream
4. Processes the stream through `ExtractFromImage` to build the layer tree

For building images, `buildImageFromCli` wraps the `docker build` command, then fetches the resulting image ID. This resolver supports TLS-encrypted daemons, SSH-based hosts, and automatic authentication.

## Podman Resolution

The **Podman Resolver** in [`dive/image/podman/resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/podman/resolver.go) takes a different approach: it delegates heavy lifting to the Docker resolver after converting Podman images to Docker-compatible archives.

The resolver executes `podman image save <id>` via `streamPodmanCmd` to produce a tar stream, then feeds that stream into Docker’s `NewImageArchive` parser. This strategy works because Podman’s export format follows the Docker image specification, allowing Dive to reuse existing parsing logic without duplication.

For builds, `buildImageFromCli` invokes `podman build`, saves the resulting image, and reuses the Docker extraction logic. The current implementation relies on the Podman CLI being available in `$PATH` and does not yet use the Varlink or REST API directly (noted as a TODO in the source).

## Docker Archive Resolution

For local tar files, the **Docker Archive Resolver** in [`dive/image/docker/archive_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/docker/archive_resolver.go) provides a read-only implementation.

The `fetch` method opens the file with `os.Open`, wraps it with `NewImageArchive`, and returns the parsed `*image.Image`. This resolver does not support building (returns an error) because archives are immutable exports. Extraction is handled by the caller after fetching, using the shared Docker extraction utilities.

## Unified Analysis Workflow

Regardless of which resolver activates, the output is always a `*image.Image` struct containing the layer tree and file system representation. Dive’s analysis engine operates exclusively on this unified structure, calculating efficiency scores, detecting duplicate files, and rendering the terminal UI.

This design allows the CLI to accept any of the following forms interchangeably:

```bash

# Analyze from Docker daemon

dive docker://nginx:latest

# Analyze from Podman

dive podman://myapp:latest

# Analyze from local archive

dive docker-archive:///path/to/image.tar

# legacy alias

dive docker-tar:///path/to/image.tar

```

## Programmatic Usage in Go

You can leverage Dive’s resolver architecture in your own Go applications. The following example demonstrates deriving the source and fetching an image programmatically:

```go
import (
    "context"
    "github.com/wagoodman/dive"
    "github.com/wagoodman/dive/dive/image"
)

func loadImage(ref string) (*image.Image, error) {
    src, id := dive.DeriveImageSource(ref)
    resolver, err := dive.GetImageResolver(src)
    if err != nil {
        return nil, err
    }
    return resolver.Fetch(context.Background(), id)
}

```

This code mirrors the CLI’s internal workflow: classify the source, obtain the appropriate resolver, and fetch the unified image structure.

## Summary

- **Dive abstracts image sources** through the `Resolver` interface in [`dive/image/resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/resolver.go), enabling support for Docker daemon, Podman, and local archives without changing the analysis engine.
- **Source detection** occurs in [`dive/get_image_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/get_image_resolver.go) via `DeriveImageSource`, which parses URL schemes (`docker://`, `podman://`, `docker-archive://`) to route to the correct implementation.
- **Docker daemon resolution** uses the official Docker client library in [`dive/image/docker/engine_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/docker/engine_resolver.go) to pull, build, and export images via the daemon API.
- **Podman resolution** in [`dive/image/podman/resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/podman/resolver.go) delegates to the Docker resolver after exporting images via `podman image save`, maintaining compatibility without requiring Podman-specific parsing logic.
- **Archive resolution** in [`dive/image/docker/archive_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/docker/archive_resolver.go) reads local Docker tar exports directly, providing a read-only path for offline analysis.

## Frequently Asked Questions

### How does Dive determine whether to use Docker or Podman?

Dive examines the URL scheme prefix in your image reference. If you specify `podman://`, Dive uses the Podman resolver. If you specify `docker://` or omit the scheme entirely, Dive defaults to the Docker daemon resolver. The `DeriveImageSource` function in [`dive/get_image_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/get_image_resolver.go) handles this classification by splitting the string on `://` and matching the scheme against known constants.

### Can Dive analyze Podman images without a Docker daemon running?

Yes. The Podman resolver in [`dive/image/podman/resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/podman/resolver.go) executes `podman image save` to export the image as a tar stream, then parses that stream using Docker-compatible archive logic. This means Dive can analyze Podman images on systems where Docker is not installed, provided the Podman CLI is available in your `$PATH`.

### Why does the Podman resolver use Docker's archive parser instead of native Podman libraries?

The Podman resolver delegates to Docker's `NewImageArchive` because Podman's exported tar format follows the Docker image specification. Rather than duplicating parsing logic, Dive reuses the existing Docker archive implementation after obtaining the image via `podman image save`. This design keeps the codebase DRY and ensures consistent layer analysis across both container engines. The source code notes that direct Varlink or REST API integration remains a future TODO.

### What archive formats does Dive support for offline analysis?

Dive supports Docker image archives exported via `docker save` or `podman save`. You can reference these using the `docker-archive://` or legacy `docker-tar://` scheme followed by the absolute path to the tar file. The archive resolver in [`dive/image/docker/archive_resolver.go`](https://github.com/wagoodman/dive/blob/main/dive/image/docker/archive_resolver.go) opens these files read-only and parses them using the same `NewImageArchive` logic used for daemon exports, enabling offline analysis without any running container engine.