Where to Find the Source Code for Dive's Docker Image Resolver

The source code for Dive's Docker image resolver is located in the dive/image/docker package, with the core Resolver interface defined in dive/image/resolver.go and concrete implementations handling Docker Engine and tar archive sources.

Dive, the container image exploration tool maintained in the wagoodman/dive repository, abstracts image fetching behind a pluggable Resolver interface. If you need to extend Dive's image-loading capabilities or reuse its Docker integration in your own Go projects, you'll find the relevant source code organized into clear interface definitions and protocol-specific implementations.

Core Interface: The Resolver Contract

The foundation of Dive's image resolution system lives in dive/image/resolver.go. This file defines the Resolver interface that all image sources—including Docker—must implement.

According to the wagoodman/dive source code, the interface requires four key capabilities:

type Resolver interface {
    Name() string
    Fetch(ctx context.Context, id string) (*Image, error)
    Build(ctx context.Context, options []string) (*Image, error)
    ContentReader
}

type ContentReader interface {
    Extract(ctx context.Context, id string, layer string, path string) error
}

Any struct implementing these methods can serve as a valid image resolver, allowing Dive to support Docker Engine, Docker archives, Podman, and other container runtimes through the same abstraction.

Docker-Specific Implementations

The Docker-specific resolvers reside in the dive/image/docker/ directory. Dive provides two distinct resolvers for handling Docker images depending on their source location.

Engine Resolver (engine_resolver.go)

The Engine resolver handles live Docker daemon interactions. Located in dive/image/docker/engine_resolver.go, this implementation connects to a running Docker Engine to pull, build, or save images.

Key functions in this file include:

  • determineDockerHost() – Discovers the correct Docker host endpoint from environment variables or context
  • fetchArchive() – Orchestrates the image save operation using dockerClient.ImageSave() to stream layers as a tar archive
  • Fetch() – Checks if the image exists locally via dockerClient.ImageInspect(), pulls it if missing, then converts the Docker image stream into Dive's internal Image representation via NewImageArchive()

Archive Resolver (archive_resolver.go)

The Archive resolver loads images from local tar files created by docker save. Found in dive/image/docker/archive_resolver.go, this resolver implements the same Resolver interface but works with static files rather than live daemons.

This resolver simply opens the specified tar path using os.Open() and passes the file handle to NewImageArchive(), which parses the Docker archive format into Dive's layer model.

How Dive Selects the Right Resolver

Dive determines which concrete resolver to instantiate through a factory pattern defined in dive/get_image_resolver.go.

The selection process follows three steps:

  1. Source Parsing – The DeriveImageSource() function parses URI strings (e.g., docker://nginx:latest) and maps them to an ImageSource enum value (SourceDockerEngine, SourceDockerArchive, etc.)

  2. Factory Dispatch – GetImageResolver() returns the appropriate implementation based on the source type:

func GetImageResolver(r ImageSource) (image.Resolver, error) {
    switch r {
    case SourceDockerEngine:
        return docker.NewResolverFromEngine(), nil
    case SourceDockerArchive:
        return docker.NewResolverFromArchive(), nil
    // … Podman, etc.
    }
    return nil, fmt.Errorf("unable to determine image resolver")
}
  1. Execution – The returned resolver's Fetch() method handles the actual image acquisition, whether that means querying the Docker daemon or reading from disk.

Programmatic Usage Examples

You can import and use Dive's resolvers directly in your own Go applications to leverage its Docker integration.

Resolving from Docker Engine

package main

import (
	"context"
	"log"

	"github.com/wagoodman/dive/dive"
	"github.com/wagoodman/dive/dive/image"
)

func main() {
	// Parse the source string the same way Dive's CLI does.
	src, imgRef := dive.DeriveImageSource("docker://nginx:latest")
	if src != dive.SourceDockerEngine {
		log.Fatalf("unexpected source: %v", src)
	}

	// Obtain the concrete resolver.
	resolver, err := dive.GetImageResolver(src)
	if err != nil {
		log.Fatalf("resolver error: %v", err)
	}

	// Fetch the image (pulls if needed).
	img, err := resolver.Fetch(context.Background(), imgRef)
	if err != nil {
		log.Fatalf("fetch error: %v", err)
	}

	// `img` now holds Dive's internal representation.
	log.Printf("Image %s has %d layers", img.ID, len(img.Layers))
}

Loading from a Tar Archive

resolver, _ := dive.GetImageResolver(dive.SourceDockerArchive)
img, err := resolver.Fetch(context.Background(), "/path/to/nginx.tar")
if err != nil {
    // handle error
}
log.Printf("Loaded archive image %s with %d layers", img.ID, len(img.Layers))

Extracting Files from Layers

Use the ContentReader interface to pull specific files from image layers without loading the entire filesystem:

resolver, _ := dive.GetImageResolver(dive.SourceDockerEngine)
err := resolver.Extract(context.Background(), "nginx:latest", "layerID", "/etc/nginx/nginx.conf")
if err != nil {
    // handle error
}

Summary

Frequently Asked Questions

What file contains the Resolver interface definition?

The Resolver interface and the embedded ContentReader interface are both defined in dive/image/resolver.go. This file establishes the contract that all image resolution implementations—including Docker, Podman, and containerd—must satisfy to integrate with Dive's analysis engine.

How does Dive choose between the engine and archive resolvers?

Dive uses the DeriveImageSource() function in dive/get_image_resolver.go to parse the input string. If the string starts with docker:// or lacks a protocol prefix (defaulting to Docker), it returns SourceDockerEngine. If the path points to a .tar file, it returns SourceDockerArchive. The GetImageResolver() factory then instantiates the appropriate struct from the dive/image/docker package.

Can I use Dive's resolvers in my own Go code?

Yes. Import github.com/wagoodman/dive/dive and github.com/wagoodman/dive/dive/image into your project. Use dive.DeriveImageSource() to parse image references, then call dive.GetImageResolver() to obtain a resolver implementing the image.Resolver interface. This allows you to programmatically fetch images or extract files from specific layers without invoking the Dive CLI directly.

Where does the engine resolver handle Docker host detection?

Docker host detection occurs in dive/image/docker/engine_resolver.go within the determineDockerHost() helper function. This function inspects environment variables like DOCKER_HOST and platform-specific contexts to determine the correct API endpoint before constructing the Docker client used for ImageInspect and ImageSave operations.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →