CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-spotify--docker-client

A comprehensive Docker client library for Java applications providing programmatic Docker API access with container lifecycle management, image operations, and Docker Swarm support.

Pending
Overview
Eval results
Files

images.mddocs/

Image Operations

This document covers comprehensive Docker image management including building, pulling, pushing, tagging, searching, and lifecycle operations.

Image Listing and Inspection

Listing Images

import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.messages.Image;

// List all images
List<Image> images = docker.listImages();

// List all images including intermediates
List<Image> allImages = docker.listImages(
    ListImagesParam.allImages()
);

// List dangling images (untagged)
List<Image> dangling = docker.listImages(
    ListImagesParam.danglingImages()
);

// Filter by label
List<Image> labeled = docker.listImages(
    ListImagesParam.withLabel("maintainer", "nginx")
);

// Filter by name pattern
List<Image> nginx = docker.listImages(
    ListImagesParam.byName("nginx")
);

// Include digests in output
List<Image> withDigests = docker.listImages(
    ListImagesParam.digests()
);

Image Information

// Get detailed image information
ImageInfo info = docker.inspectImage("nginx:latest");

System.out.println("Image ID: " + info.id());
System.out.println("Created: " + info.created());
System.out.println("Size: " + info.size());
System.out.println("Virtual Size: " + info.virtualSize());
System.out.println("Author: " + info.author());
System.out.println("Comment: " + info.comment());
System.out.println("Docker Version: " + info.dockerVersion());
System.out.println("Architecture: " + info.architecture());
System.out.println("OS: " + info.os());

// Repository tags and digests
List<String> tags = info.repoTags();
List<String> digests = info.repoDigests();

// Image configuration
ContainerConfig config = info.config();
System.out.println("Exposed Ports: " + config.exposedPorts());
System.out.println("Environment: " + config.env());
System.out.println("Entrypoint: " + config.entrypoint());
System.out.println("Cmd: " + config.cmd());

// Root filesystem info
RootFs rootFs = info.rootFs();
System.out.println("Root FS Type: " + rootFs.type());
System.out.println("Root FS Layers: " + rootFs.layers());

Image History

// Get image layer history
List<ImageHistory> history = docker.history("nginx:latest");

for (ImageHistory layer : history) {
    System.out.println("Layer ID: " + layer.id());
    System.out.println("Created: " + layer.created());
    System.out.println("Created By: " + layer.createdBy());
    System.out.println("Size: " + layer.size());
    System.out.println("Tags: " + layer.tags());
    System.out.println("Comment: " + layer.comment());
    System.out.println("---");
}

Image Building

Basic Image Building

import java.nio.file.Paths;

// Build from directory containing Dockerfile
String imageId = docker.build(Paths.get("/path/to/build/context"));

// Build with specific name and tag
String imageId = docker.build(
    Paths.get("/path/to/build/context"),
    "myapp:1.0"
);

// Build with custom Dockerfile path
String imageId = docker.build(
    Paths.get("/path/to/build/context"),
    "myapp:1.0",
    BuildParam.dockerfile(Paths.get("custom.Dockerfile"))
);

Advanced Build Parameters

String imageId = docker.build(
    Paths.get("/path/to/build/context"),
    "myapp:latest",
    BuildParam.name("myapp:1.0"),           // Additional tag
    BuildParam.quiet(),                      // Suppress verbose output
    BuildParam.noCache(),                    // Don't use build cache
    BuildParam.rm(),                         // Remove intermediate containers
    BuildParam.forceRm(),                    // Always remove intermediate containers
    BuildParam.pullNewerImage(),             // Always pull newer base image
    BuildParam.memory(1024L * 1024 * 1024), // Memory limit (1GB)
    BuildParam.cpuShares(512),               // CPU shares
    BuildParam.dockerfile(Paths.get("Dockerfile.prod"))  // Custom Dockerfile
);

Build with Progress Handler

import com.spotify.docker.client.ProgressHandler;
import com.spotify.docker.client.messages.ProgressMessage;

final AtomicReference<String> imageIdFromProgress = new AtomicReference<>();

String imageId = docker.build(
    Paths.get("/path/to/dockerfile"),
    "myapp:latest",
    new ProgressHandler() {
        @Override
        public void progress(ProgressMessage message) throws DockerException {
            String buildImageId = message.buildImageId();
            if (buildImageId != null) {
                imageIdFromProgress.set(buildImageId);
            }
            
            // Handle different message types
            if (message.stream() != null) {
                System.out.print(message.stream());
            }
            
            if (message.status() != null) {
                System.out.println("Status: " + message.status());
            }
            
            if (message.error() != null) {
                System.err.println("Error: " + message.error());
            }
            
            // Progress details
            ProgressDetail detail = message.progressDetail();
            if (detail != null) {
                System.out.printf("Progress: %d/%d%n", 
                    detail.current(), detail.total());
            }
        }
    }
);

Build from Git Repository

// Build from remote Git repository
String imageId = docker.build(
    Paths.get("."),  // Not used for remote builds
    "myapp:git",
    BuildParam.remote(URI.create("https://github.com/user/repo.git#branch"))
);

// Build from Git with specific context
String imageId = docker.build(
    Paths.get("."),
    "myapp:git-subdir",
    BuildParam.remote(URI.create("https://github.com/user/repo.git#:subdirectory"))
);

Image Pulling and Pushing

Pulling Images

// Pull public image
docker.pull("nginx:latest");

// Pull specific tag
docker.pull("ubuntu:20.04");

// Pull with progress handler
docker.pull("large-image:latest", new ProgressHandler() {
    @Override
    public void progress(ProgressMessage message) throws DockerException {
        if (message.status() != null) {
            System.out.println("Pull status: " + message.status());
        }
        
        ProgressDetail detail = message.progressDetail();
        if (detail != null && detail.total() != null && detail.total() > 0) {
            double percentage = (double) detail.current() / detail.total() * 100;
            System.out.printf("Progress: %.1f%%%n", percentage);
        }
    }
});

Pulling Private Images

import com.spotify.docker.client.messages.RegistryAuth;

// Create registry authentication
RegistryAuth auth = RegistryAuth.builder()
    .username("myuser")
    .password("mypassword")
    .email("user@example.com")
    .serverAddress("https://my-registry.com")
    .build();

// Pull private image
docker.pull("my-registry.com/myapp:latest", auth);

// Pull private image with progress
docker.pull("my-registry.com/myapp:latest", auth, new ProgressHandler() {
    @Override
    public void progress(ProgressMessage message) throws DockerException {
        System.out.println("Private pull: " + message.status());
    }
});

Pushing Images

// Push public image
docker.push("myuser/myapp:latest");

// Push with progress handler
docker.push("myuser/myapp:latest", new ProgressHandler() {
    @Override
    public void progress(ProgressMessage message) throws DockerException {
        if (message.status() != null) {
            System.out.println("Push status: " + message.status());
        }
    }
});

// Push to private registry
RegistryAuth auth = RegistryAuth.builder()
    .username("myuser")
    .password("mypassword")
    .serverAddress("https://my-registry.com")
    .build();

docker.push("my-registry.com/myapp:latest", auth);

// Push to private registry with progress
docker.push("my-registry.com/myapp:latest", new ProgressHandler() {
    @Override
    public void progress(ProgressMessage message) throws DockerException {
        System.out.println("Private push: " + message.status());
    }
}, auth);

Image Tagging

Basic Tagging

// Tag existing image
docker.tag("nginx:latest", "myapp/nginx:v1.0");

// Tag with force (overwrite existing tag)
docker.tag("nginx:latest", "myapp/nginx:latest", true);

// Tag for different registry
docker.tag("myapp:latest", "registry.example.com/myapp:1.0");

Multi-Tag Strategy

public void tagImageForRelease(DockerClient docker, String sourceImage, String version) 
        throws DockerException, InterruptedException {
    
    String repository = "mycompany/myapp";
    
    // Tag with specific version
    docker.tag(sourceImage, repository + ":" + version);
    
    // Tag as latest
    docker.tag(sourceImage, repository + ":latest");
    
    // Tag with major version
    String majorVersion = version.split("\\.")[0];
    docker.tag(sourceImage, repository + ":" + majorVersion);
    
    // Tag for production registry
    docker.tag(sourceImage, "prod-registry.com/" + repository + ":" + version);
}

Image Creation and Loading

Creating Images from Tarballs

import java.io.*;

// Create image from tarball
File tarFile = new File("/path/to/image.tar");
try (InputStream imageInput = new BufferedInputStream(new FileInputStream(tarFile))) {
    docker.create("myapp:from-tar", imageInput);
}

// Create with progress handler
try (InputStream imageInput = new BufferedInputStream(new FileInputStream(tarFile))) {
    docker.create("myapp:from-tar", imageInput, new ProgressHandler() {
        @Override
        public void progress(ProgressMessage message) throws DockerException {
            System.out.println("Create progress: " + message.status());
        }
    });
}

Loading Images

// Load single image from tarball
File imageFile = new File("/path/to/exported-image.tar");
try (InputStream imageInput = new BufferedInputStream(new FileInputStream(imageFile))) {
    docker.load(imageInput);
}

// Load with progress tracking
try (InputStream imageInput = new BufferedInputStream(new FileInputStream(imageFile))) {
    Set<String> loadedImages = docker.load(imageInput, new ProgressHandler() {
        @Override
        public void progress(ProgressMessage message) throws DockerException {
            if (message.stream() != null) {
                System.out.println("Load: " + message.stream());
            }
        }
    });
    
    System.out.println("Loaded images: " + loadedImages);
}

Image Saving and Export

Saving Single Image

// Save image to tarball
try (InputStream imageData = docker.save("nginx:latest")) {
    Files.copy(imageData, Paths.get("/path/to/nginx.tar"));
}

// Save with processing
try (InputStream imageData = docker.save("myapp:latest")) {
    byte[] buffer = new byte[8192];
    int bytesRead;
    long totalBytes = 0;
    
    try (FileOutputStream output = new FileOutputStream("/path/to/myapp.tar");
         BufferedOutputStream buffered = new BufferedOutputStream(output)) {
        
        while ((bytesRead = imageData.read(buffer)) != -1) {
            buffered.write(buffer, 0, bytesRead);
            totalBytes += bytesRead;
            System.out.println("Saved: " + totalBytes + " bytes");
        }
    }
}

Saving Multiple Images

// Save multiple images to single tarball
try (InputStream multipleImages = docker.saveMultiple("nginx:latest", "redis:latest", "postgres:latest")) {
    Files.copy(multipleImages, Paths.get("/path/to/multiple-images.tar"));
}

// Process multiple image tarball
try (InputStream imageData = docker.saveMultiple("app:v1", "app:v2", "app:latest");
     TarArchiveInputStream tarStream = new TarArchiveInputStream(imageData)) {
    
    TarArchiveEntry entry;
    while ((entry = tarStream.getNextTarEntry()) != null) {
        System.out.println("Archive entry: " + entry.getName());
        if (entry.getName().equals("manifest.json")) {
            // Process Docker manifest
            byte[] manifest = new byte[(int) entry.getSize()];
            tarStream.read(manifest);
            System.out.println("Manifest: " + new String(manifest));
        }
    }
}

Image Search

Searching Docker Hub

// Search for images
List<ImageSearchResult> results = docker.searchImages("nginx");

for (ImageSearchResult result : results) {
    System.out.println("Name: " + result.name());
    System.out.println("Description: " + result.description());
    System.out.println("Stars: " + result.starCount());
    System.out.println("Official: " + result.isOfficial());
    System.out.println("Automated: " + result.isAutomated());
    System.out.println("---");
}

// Search with filtering
List<ImageSearchResult> officialOnly = docker.searchImages("python")
    .stream()
    .filter(ImageSearchResult::isOfficial)
    .collect(Collectors.toList());

Image Removal

Basic Image Removal

// Remove single image
List<RemovedImage> removed = docker.removeImage("myapp:old");

for (RemovedImage removedImage : removed) {
    if (removedImage.untagged() != null) {
        System.out.println("Untagged: " + removedImage.untagged());
    }
    if (removedImage.deleted() != null) {
        System.out.println("Deleted: " + removedImage.deleted());
    }
}

// Force remove (remove even if containers are using it)
List<RemovedImage> forceRemoved = docker.removeImage("myapp:latest", true, false);

// Remove without pruning (don't delete untagged parent images)
List<RemovedImage> noPrune = docker.removeImage("myapp:latest", false, true);

Bulk Image Cleanup

public void cleanupUnusedImages(DockerClient docker) 
        throws DockerException, InterruptedException {
    
    // Remove dangling images
    List<Image> danglingImages = docker.listImages(ListImagesParam.danglingImages());
    
    for (Image image : danglingImages) {
        try {
            List<RemovedImage> removed = docker.removeImage(image.id());
            System.out.println("Removed dangling image: " + image.id());
        } catch (DockerException e) {
            System.err.println("Failed to remove " + image.id() + ": " + e.getMessage());
        }
    }
    
    // Remove old images by pattern
    List<Image> allImages = docker.listImages();
    for (Image image : allImages) {
        for (String tag : image.repoTags()) {
            if (tag.matches("myapp:.*-SNAPSHOT")) {
                try {
                    docker.removeImage(tag);
                    System.out.println("Removed snapshot image: " + tag);
                } catch (DockerException e) {
                    System.err.println("Failed to remove " + tag + ": " + e.getMessage());
                }
                break;
            }
        }
    }
}

Image Commit

Creating Images from Containers

// Commit container to new image
ContainerCreation newImage = docker.commitContainer(
    "container-id",
    "myuser/myapp",     // repository
    "v1.0",             // tag
    containerConfig,     // container configuration
    "Initial commit",   // commit message
    "John Doe"          // author
);

System.out.println("New image ID: " + newImage.id());

// Commit with minimal parameters
ContainerConfig config = ContainerConfig.builder()
    .image("base-image")
    .cmd("echo", "hello")
    .build();

ContainerCreation committed = docker.commitContainer(
    "container-id",
    "myapp/committed",
    "latest",
    config,
    null,  // no message
    null   // no author
);

Distribution Information

Getting Distribution Metadata

// Get distribution information (manifest, etc.)
Distribution distribution = docker.getDistribution("nginx:latest");

System.out.println("Descriptor:");
Descriptor descriptor = distribution.descriptor();
System.out.println("  Media Type: " + descriptor.mediaType());
System.out.println("  Size: " + descriptor.size());
System.out.println("  Digest: " + descriptor.digest());

// Platform information
for (Platform platform : distribution.platforms()) {
    System.out.println("Platform:");
    System.out.println("  Architecture: " + platform.architecture());
    System.out.println("  OS: " + platform.os());
    System.out.println("  Variant: " + platform.variant());
}

Image Filtering Parameters

ListImagesParam Options

// Show all images including intermediates
ListImagesParam.allImages()
ListImagesParam.allImages(true)

// Show image digests
ListImagesParam.digests()
ListImagesParam.digests(true)

// Show dangling images only
ListImagesParam.danglingImages()
ListImagesParam.danglingImages(true)

// Filter by labels
ListImagesParam.withLabel("maintainer")
ListImagesParam.withLabel("version", "1.0")

// Filter by name/reference
ListImagesParam.byName("nginx")
ListImagesParam.byName("myregistry.com/myapp")

// Custom filters
ListImagesParam.filter("reference", "nginx:*")
ListImagesParam.filter("before", "image-id")
ListImagesParam.filter("since", "image-id")
ListImagesParam.filter("label", "key=value")

Complete Image Pipeline Example

public class ImagePipelineExample {
    
    public void buildPushPipeline(DockerClient docker, String version) 
            throws DockerException, InterruptedException, IOException {
        
        final String repository = "mycompany/myapp";
        final Path buildContext = Paths.get("/app/source");
        
        System.out.println("Starting build pipeline for version: " + version);
        
        // 1. Build image with progress tracking
        AtomicReference<String> builtImageId = new AtomicReference<>();
        
        String imageId = docker.build(
            buildContext,
            repository + ":" + version,
            BuildParam.rm(),
            BuildParam.noCache(),
            new ProgressHandler() {
                @Override
                public void progress(ProgressMessage message) throws DockerException {
                    if (message.buildImageId() != null) {
                        builtImageId.set(message.buildImageId());
                    }
                    if (message.stream() != null) {
                        System.out.print(message.stream());
                    }
                }
            }
        );
        
        System.out.println("Built image: " + imageId);
        
        // 2. Tag for multiple targets
        docker.tag(imageId, repository + ":latest");
        docker.tag(imageId, repository + ":" + version);
        
        String majorVersion = version.split("\\.")[0];
        docker.tag(imageId, repository + ":" + majorVersion);
        
        // 3. Push to registry with authentication
        RegistryAuth auth = RegistryAuth.builder()
            .username(System.getenv("DOCKER_USER"))
            .password(System.getenv("DOCKER_PASSWORD"))
            .build();
            
        // Push all tags
        String[] tags = {version, "latest", majorVersion};
        for (String tag : tags) {
            String fullTag = repository + ":" + tag;
            System.out.println("Pushing " + fullTag);
            
            docker.push(fullTag, new ProgressHandler() {
                @Override
                public void progress(ProgressMessage message) throws DockerException {
                    if (message.status() != null && message.id() != null) {
                        System.out.printf("  %s: %s%n", message.id(), message.status());
                    }
                }
            }, auth);
        }
        
        // 4. Verify image
        ImageInfo info = docker.inspectImage(imageId);
        System.out.println("Final image size: " + info.size() + " bytes");
        System.out.println("Architecture: " + info.architecture());
        
        // 5. Clean up old images
        cleanupOldImages(docker, repository, version);
        
        System.out.println("Pipeline completed successfully");
    }
    
    private void cleanupOldImages(DockerClient docker, String repository, String currentVersion) 
            throws DockerException, InterruptedException {
        
        List<Image> images = docker.listImages();
        for (Image image : images) {
            for (String tag : image.repoTags()) {
                if (tag.startsWith(repository + ":") && 
                    !tag.endsWith(":latest") && 
                    !tag.endsWith(":" + currentVersion)) {
                    
                    try {
                        docker.removeImage(tag);
                        System.out.println("Removed old image: " + tag);
                    } catch (DockerException e) {
                        System.err.println("Could not remove " + tag + ": " + e.getMessage());
                    }
                }
            }
        }
    }
}

The image management system provides comprehensive control over Docker images with support for building, distribution, authentication, and lifecycle management suitable for CI/CD pipelines and production deployments.

Install with Tessl CLI

npx tessl i tessl/maven-com-spotify--docker-client

docs

client-configuration.md

containers.md

images.md

index.md

networks.md

swarm.md

volumes.md

tile.json