A comprehensive Docker client library for Java applications providing programmatic Docker API access with container lifecycle management, image operations, and Docker Swarm support.
—
This document covers comprehensive Docker image management including building, pulling, pushing, tagging, searching, and lifecycle operations.
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()
);// 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());// 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("---");
}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"))
);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
);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 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"))
);// 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);
}
}
});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());
}
});// 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);// 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");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);
}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());
}
});
}// 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);
}// 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");
}
}
}// 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));
}
}
}// 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());// 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);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;
}
}
}
}// 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
);// 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());
}// 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")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