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

volumes.mddocs/

Volume Operations

This document covers Docker volume management including creation, inspection, mounting, and lifecycle operations for persistent data storage.

Volume Listing and Inspection

Listing Volumes

import com.spotify.docker.client.DockerClient;
import com.spotify.docker.client.messages.Volume;
import com.spotify.docker.client.messages.VolumeList;

// List all volumes
VolumeList volumeList = docker.listVolumes();
List<Volume> volumes = volumeList.volumes();
List<String> warnings = volumeList.warnings();

// Display volume information
for (Volume volume : volumes) {
    System.out.println("Volume: " + volume.name());
    System.out.println("Driver: " + volume.driver());
    System.out.println("Mountpoint: " + volume.mountpoint());
    System.out.println("Scope: " + volume.scope());
}

// Check for warnings
if (!warnings.isEmpty()) {
    System.out.println("Warnings: " + warnings);
}

Volume Filtering

// Filter volumes by name
VolumeList namedVolumes = docker.listVolumes(
    ListVolumesParam.name("my-data-volume")
);

// Filter dangling volumes (not attached to any container)
VolumeList danglingVolumes = docker.listVolumes(
    ListVolumesParam.dangling(true)
);

// Filter by driver
VolumeList localVolumes = docker.listVolumes(
    ListVolumesParam.driver("local")
);

// Custom filters
VolumeList filtered = docker.listVolumes(
    ListVolumesParam.filter("label", "environment=production")
);

Volume Inspection

// Inspect specific volume
Volume volume = docker.inspectVolume("volume-name-or-id");

System.out.println("Name: " + volume.name());
System.out.println("Driver: " + volume.driver());
System.out.println("Mountpoint: " + volume.mountpoint());
System.out.println("Scope: " + volume.scope());

// Volume labels
Map<String, String> labels = volume.labels();
if (labels != null) {
    System.out.println("Labels:");
    for (Map.Entry<String, String> entry : labels.entrySet()) {
        System.out.println("  " + entry.getKey() + ": " + entry.getValue());
    }
}

// Driver options
Map<String, String> options = volume.options();
if (options != null) {
    System.out.println("Driver Options:");
    for (Map.Entry<String, String> entry : options.entrySet()) {
        System.out.println("  " + entry.getKey() + ": " + entry.getValue());
    }
}

Volume Creation

Anonymous Volume Creation

// Create anonymous volume (Docker generates name)
Volume anonymousVolume = docker.createVolume();
System.out.println("Created anonymous volume: " + anonymousVolume.name());

Named Volume Creation

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

// Create simple named volume
Volume simpleVolume = Volume.builder()
    .name("my-data-volume")
    .build();

Volume created = docker.createVolume(simpleVolume);
System.out.println("Created volume: " + created.name());

Advanced Volume Configuration

// Create volume with custom driver and options
Volume advancedVolume = Volume.builder()
    .name("production-data")
    .driver("local")
    .labels(Map.of(
        "environment", "production",
        "application", "database",
        "backup", "enabled"
    ))
    .options(Map.of(
        "type", "tmpfs",
        "device", "tmpfs",
        "o", "size=500m,uid=1000,gid=1000"
    ))
    .build();

Volume created = docker.createVolume(advancedVolume);

Driver-Specific Volume Creation

// Local driver with bind mount
Volume bindVolume = Volume.builder()
    .name("host-bind-volume")
    .driver("local")
    .options(Map.of(
        "type", "bind",
        "o", "bind",
        "device", "/host/path/data"
    ))
    .build();

// NFS volume
Volume nfsVolume = Volume.builder()
    .name("nfs-shared-volume")
    .driver("local")
    .options(Map.of(
        "type", "nfs",
        "o", "addr=nfs.example.com,rw",
        "device", ":/path/to/shared/data"
    ))
    .build();

// tmpfs volume for temporary data
Volume tmpfsVolume = Volume.builder()
    .name("temp-volume")
    .driver("local")
    .options(Map.of(
        "type", "tmpfs",
        "device", "tmpfs",
        "o", "size=1g,mode=1777"
    ))
    .build();

docker.createVolume(bindVolume);
docker.createVolume(nfsVolume);
docker.createVolume(tmpfsVolume);

Volume Usage in Containers

Container Volume Mounts

// Using volumes in container configuration
ContainerConfig config = ContainerConfig.builder()
    .image("postgres:13")
    .env("POSTGRES_DB=myapp", "POSTGRES_PASSWORD=secret")
    
    // Volume mount points (creates anonymous volumes)
    .volumes("/var/lib/postgresql/data", "/var/log/postgresql")
    
    .build();

// Host configuration with volume binds
HostConfig hostConfig = HostConfig.builder()
    // Named volume mounts
    .binds(
        "postgres-data:/var/lib/postgresql/data",
        "postgres-logs:/var/log/postgresql",
        "/host/config:/etc/postgresql/conf.d:ro"  // Read-only bind
    )
    
    // Alternative: using Mount objects for more control
    .mounts(
        Mount.builder()
            .type("volume")
            .source("postgres-data")
            .target("/var/lib/postgresql/data")
            .build(),
        Mount.builder()
            .type("bind")
            .source("/host/backup")
            .target("/backup")
            .readOnly(true)
            .build()
    )
    
    .build();

ContainerConfig fullConfig = config.toBuilder()
    .hostConfig(hostConfig)
    .build();

ContainerCreation container = docker.createContainer(fullConfig);

Advanced Mount Configuration

// Mount with detailed configuration
Mount dataMount = Mount.builder()
    .type("volume")
    .source("app-data")
    .target("/app/data")
    .readOnly(false)
    
    // Volume options
    .volumeOptions(VolumeOptions.builder()
        .noCopy(false)  // Copy data from container to volume on first mount
        .labels(Map.of("mount-type", "data"))
        .driverConfig(Driver.builder()
            .name("local")
            .options(Map.of("type", "ext4"))
            .build())
        .build())
    
    // Bind options (for bind mounts)
    .bindOptions(BindOptions.builder()
        .propagation("rprivate")
        .build())
    
    // tmpfs options (for tmpfs mounts)
    .tmpfsOptions(TmpfsOptions.builder()
        .sizeBytes(1024L * 1024 * 1024)  // 1GB
        .mode(0755)
        .build())
    
    .build();

HostConfig hostConfig = HostConfig.builder()
    .mounts(dataMount)
    .build();

Volume Binding Patterns

public class VolumeBindingPatterns {
    
    public void demonstrateBindPatterns(DockerClient docker) 
            throws DockerException, InterruptedException {
        
        // 1. Named volume for persistent data
        Volume dataVolume = Volume.builder()
            .name("app-persistent-data")
            .labels(Map.of("purpose", "application-data"))
            .build();
        docker.createVolume(dataVolume);
        
        // 2. Bind mount for configuration
        String configBind = "/host/app/config:/app/config:ro";
        
        // 3. tmpfs for temporary/cache data
        String tmpfsBind = "tmpfs:/tmp:tmpfs,size=500m";
        
        // 4. Anonymous volume for logs
        ContainerConfig config = ContainerConfig.builder()
            .image("myapp:latest")
            .volumes("/app/logs")  // Anonymous volume
            .hostConfig(HostConfig.builder()
                .binds(
                    "app-persistent-data:/app/data",  // Named volume
                    configBind,                       // Read-only bind
                    tmpfsBind                         // tmpfs mount
                )
                .build())
            .build();
            
        ContainerCreation container = docker.createContainer(config);
    }
}

Volume Removal

Basic Volume Removal

// Remove volume by name
docker.removeVolume("volume-name");

// Remove volume object
Volume volume = docker.inspectVolume("my-volume");
docker.removeVolume(volume);

Safe Volume Removal

public void safeVolumeRemoval(DockerClient docker, String volumeName) {
    try {
        // Check if volume exists
        Volume volume = docker.inspectVolume(volumeName);
        
        // Check if volume is in use by any containers
        List<Container> containers = docker.listContainers(
            DockerClient.ListContainersParam.allContainers()
        );
        
        boolean inUse = false;
        for (Container container : containers) {
            ContainerInfo info = docker.inspectContainer(container.id());
            
            // Check mounts
            for (ContainerMount mount : info.mounts()) {
                if (volumeName.equals(mount.name()) || 
                    volumeName.equals(mount.source())) {
                    System.out.println("Volume in use by container: " + container.id());
                    inUse = true;
                    break;
                }
            }
        }
        
        if (!inUse) {
            docker.removeVolume(volumeName);
            System.out.println("Successfully removed volume: " + volumeName);
        } else {
            System.out.println("Volume is in use and cannot be removed");
        }
        
    } catch (DockerException | InterruptedException e) {
        System.err.println("Error removing volume: " + e.getMessage());
    }
}

Bulk Volume Cleanup

public void cleanupUnusedVolumes(DockerClient docker) 
        throws DockerException, InterruptedException {
    
    // Get all dangling volumes
    VolumeList danglingList = docker.listVolumes(
        ListVolumesParam.dangling(true)
    );
    
    List<Volume> danglingVolumes = danglingList.volumes();
    System.out.println("Found " + danglingVolumes.size() + " dangling volumes");
    
    for (Volume volume : danglingVolumes) {
        try {
            docker.removeVolume(volume.name());
            System.out.println("Removed dangling volume: " + volume.name());
        } catch (DockerException e) {
            System.err.println("Failed to remove volume " + volume.name() + ": " + e.getMessage());
        }
    }
    
    // Remove volumes with specific labels (e.g., temporary volumes)
    VolumeList allVolumes = docker.listVolumes();
    for (Volume volume : allVolumes.volumes()) {
        Map<String, String> labels = volume.labels();
        if (labels != null && "true".equals(labels.get("temporary"))) {
            try {
                docker.removeVolume(volume.name());
                System.out.println("Removed temporary volume: " + volume.name());
            } catch (DockerException e) {
                System.err.println("Failed to remove temporary volume " + volume.name() + ": " + e.getMessage());
            }
        }
    }
}

Volume Backup and Restore

Volume Backup Strategy

public void backupVolume(DockerClient docker, String volumeName, String backupPath) 
        throws DockerException, InterruptedException {
    
    System.out.println("Starting backup of volume: " + volumeName);
    
    // Create a temporary container to access the volume
    ContainerConfig backupConfig = ContainerConfig.builder()
        .image("alpine:latest")
        .cmd("tar", "czf", "/backup/volume-backup.tar.gz", "-C", "/data", ".")
        .volumes("/backup")
        .hostConfig(HostConfig.builder()
            .binds(
                volumeName + ":/data:ro",  // Mount volume as read-only
                backupPath + ":/backup"    // Mount backup destination
            )
            .autoRemove(AutoRemove.always())  // Auto-remove when done
            .build())
        .build();
    
    ContainerCreation backupContainer = docker.createContainer(backupConfig);
    
    try {
        // Start backup process
        docker.startContainer(backupContainer.id());
        
        // Wait for completion
        ContainerExit exit = docker.waitContainer(backupContainer.id());
        
        if (exit.statusCode() == 0) {
            System.out.println("Volume backup completed successfully");
        } else {
            System.err.println("Backup failed with exit code: " + exit.statusCode());
        }
        
    } finally {
        // Container is auto-removed due to autoRemove setting
        System.out.println("Backup container cleaned up");
    }
}

Volume Restore Strategy

public void restoreVolume(DockerClient docker, String volumeName, String backupFile) 
        throws DockerException, InterruptedException {
    
    System.out.println("Restoring volume: " + volumeName + " from " + backupFile);
    
    // Ensure target volume exists
    try {
        docker.inspectVolume(volumeName);
    } catch (Exception e) {
        // Create volume if it doesn't exist
        Volume newVolume = Volume.builder()
            .name(volumeName)
            .build();
        docker.createVolume(newVolume);
        System.out.println("Created new volume: " + volumeName);
    }
    
    // Create restore container
    ContainerConfig restoreConfig = ContainerConfig.builder()
        .image("alpine:latest")
        .cmd("tar", "xzf", "/backup/" + new File(backupFile).getName(), "-C", "/data")
        .volumes("/backup", "/data")
        .hostConfig(HostConfig.builder()
            .binds(
                new File(backupFile).getParent() + ":/backup:ro",
                volumeName + ":/data"
            )
            .autoRemove(AutoRemove.always())
            .build())
        .build();
    
    ContainerCreation restoreContainer = docker.createContainer(restoreConfig);
    
    try {
        docker.startContainer(restoreContainer.id());
        ContainerExit exit = docker.waitContainer(restoreContainer.id());
        
        if (exit.statusCode() == 0) {
            System.out.println("Volume restore completed successfully");
        } else {
            System.err.println("Restore failed with exit code: " + exit.statusCode());
        }
        
    } finally {
        System.out.println("Restore container cleaned up");
    }
}

Volume Migration

Volume Data Migration

public void migrateVolumeData(DockerClient docker, String sourceVolume, String targetVolume) 
        throws DockerException, InterruptedException {
    
    System.out.println("Migrating data from " + sourceVolume + " to " + targetVolume);
    
    // Ensure target volume exists
    Volume target = Volume.builder()
        .name(targetVolume)
        .build();
    docker.createVolume(target);
    
    // Create migration container
    ContainerConfig migrationConfig = ContainerConfig.builder()
        .image("alpine:latest")
        .cmd("sh", "-c", "cp -av /source/. /target/")
        .volumes("/source", "/target")
        .hostConfig(HostConfig.builder()
            .binds(
                sourceVolume + ":/source:ro",
                targetVolume + ":/target"
            )
            .autoRemove(AutoRemove.always())
            .build())
        .build();
    
    ContainerCreation migrationContainer = docker.createContainer(migrationConfig);
    
    try {
        docker.startContainer(migrationContainer.id());
        
        // Monitor progress with logs
        try (LogStream logs = docker.logs(migrationContainer.id(),
            DockerClient.LogsParam.follow(),
            DockerClient.LogsParam.stdout(),
            DockerClient.LogsParam.stderr())) {
            
            logs.forEachRemaining(logMessage -> {
                System.out.println("Migration: " + logMessage.content().toStringUtf8().trim());
            });
        }
        
        ContainerExit exit = docker.waitContainer(migrationContainer.id());
        
        if (exit.statusCode() == 0) {
            System.out.println("Volume migration completed successfully");
            
            // Verify migration
            verifyVolumeMigration(docker, sourceVolume, targetVolume);
        } else {
            System.err.println("Migration failed with exit code: " + exit.statusCode());
        }
        
    } finally {
        System.out.println("Migration container cleaned up");
    }
}

private void verifyVolumeMigration(DockerClient docker, String sourceVolume, String targetVolume) 
        throws DockerException, InterruptedException {
    
    // Create verification container
    ContainerConfig verifyConfig = ContainerConfig.builder()
        .image("alpine:latest")
        .cmd("sh", "-c", 
            "echo 'Source files:' && find /source -type f | wc -l && " +
            "echo 'Target files:' && find /target -type f | wc -l && " +
            "echo 'Source size:' && du -sh /source && " +
            "echo 'Target size:' && du -sh /target")
        .hostConfig(HostConfig.builder()
            .binds(
                sourceVolume + ":/source:ro",
                targetVolume + ":/target:ro"
            )
            .autoRemove(AutoRemove.always())
            .build())
        .build();
    
    ContainerCreation verifyContainer = docker.createContainer(verifyConfig);
    docker.startContainer(verifyContainer.id());
    
    try (LogStream logs = docker.logs(verifyContainer.id(),
        DockerClient.LogsParam.stdout(),
        DockerClient.LogsParam.stderr())) {
        
        String verification = logs.readFully();
        System.out.println("Migration verification:\n" + verification);
    }
    
    docker.waitContainer(verifyContainer.id());
}

Volume Monitoring and Management

Volume Usage Analysis

public void analyzeVolumeUsage(DockerClient docker) 
        throws DockerException, InterruptedException {
    
    VolumeList volumeList = docker.listVolumes();
    System.out.println("Volume Usage Analysis:");
    System.out.println("Total volumes: " + volumeList.volumes().size());
    
    Map<String, Integer> driverCount = new HashMap<>();
    Map<String, List<Volume>> volumesByLabel = new HashMap<>();
    
    for (Volume volume : volumeList.volumes()) {
        // Count by driver
        driverCount.merge(volume.driver(), 1, Integer::sum);
        
        // Group by labels
        Map<String, String> labels = volume.labels();
        if (labels != null) {
            for (String labelValue : labels.values()) {
                volumesByLabel.computeIfAbsent(labelValue, k -> new ArrayList<>()).add(volume);
            }
        }
        
        // Get size information (requires container to check)
        getVolumeSize(docker, volume);
    }
    
    System.out.println("Volumes by driver:");
    driverCount.forEach((driver, count) -> 
        System.out.println("  " + driver + ": " + count));
    
    System.out.println("Volumes by label value:");
    volumesByLabel.forEach((label, volumes) -> 
        System.out.println("  " + label + ": " + volumes.size() + " volumes"));
}

private void getVolumeSize(DockerClient docker, Volume volume) {
    try {
        ContainerConfig sizeCheckConfig = ContainerConfig.builder()
            .image("alpine:latest")
            .cmd("du", "-sh", "/data")
            .hostConfig(HostConfig.builder()
                .binds(volume.name() + ":/data:ro")
                .autoRemove(AutoRemove.always())
                .build())
            .build();
        
        ContainerCreation container = docker.createContainer(sizeCheckConfig);
        docker.startContainer(container.id());
        
        try (LogStream logs = docker.logs(container.id(),
            DockerClient.LogsParam.stdout())) {
            String sizeOutput = logs.readFully().trim();
            System.out.println("Volume " + volume.name() + " size: " + sizeOutput);
        }
        
        docker.waitContainer(container.id());
        
    } catch (Exception e) {
        System.err.println("Could not get size for volume " + volume.name() + ": " + e.getMessage());
    }
}

Volume Filtering Parameters

ListVolumesParam Options

// Filter by volume name
ListVolumesParam.name("exact-volume-name")

// Filter dangling volumes
ListVolumesParam.dangling()
ListVolumesParam.dangling(true)

// Filter by driver
ListVolumesParam.driver("local")
ListVolumesParam.driver("nfs")

// Custom filters
ListVolumesParam.filter("scope", "local")
ListVolumesParam.filter("label", "environment=production")
ListVolumesParam.filter("label", "backup")  // Has label key

Complete Volume Management Example

public class VolumeManagementExample {
    
    public void demonstrateVolumeManagement(DockerClient docker) 
            throws DockerException, InterruptedException {
        
        System.out.println("Starting comprehensive volume management demo...");
        
        // 1. Create volumes for different purposes
        createApplicationVolumes(docker);
        
        // 2. Deploy application with volume mounts
        deployApplicationWithVolumes(docker);
        
        // 3. Perform volume operations
        performVolumeOperations(docker);
        
        // 4. Cleanup
        cleanupVolumeDemo(docker);
    }
    
    private void createApplicationVolumes(DockerClient docker) 
            throws DockerException, InterruptedException {
        
        System.out.println("Creating application volumes...");
        
        // Database data volume
        Volume dbData = Volume.builder()
            .name("webapp-db-data")
            .driver("local")
            .labels(Map.of(
                "application", "webapp",
                "tier", "database",
                "backup", "enabled"
            ))
            .build();
        
        // Application logs volume
        Volume appLogs = Volume.builder()
            .name("webapp-logs")
            .driver("local")
            .labels(Map.of(
                "application", "webapp",
                "tier", "application", 
                "retention", "30days"
            ))
            .build();
        
        // Cache volume (tmpfs)
        Volume cacheVolume = Volume.builder()
            .name("webapp-cache")
            .driver("local")
            .options(Map.of(
                "type", "tmpfs",
                "device", "tmpfs",
                "o", "size=1g,mode=0755"
            ))
            .labels(Map.of(
                "application", "webapp",
                "tier", "cache",
                "temporary", "true"
            ))
            .build();
        
        docker.createVolume(dbData);
        docker.createVolume(appLogs);
        docker.createVolume(cacheVolume);
        
        System.out.println("Created application volumes successfully");
    }
    
    private void deployApplicationWithVolumes(DockerClient docker) 
            throws DockerException, InterruptedException {
        
        System.out.println("Deploying application with volume mounts...");
        
        // Database container
        ContainerConfig dbConfig = ContainerConfig.builder()
            .image("postgres:13")
            .env("POSTGRES_DB=webapp", "POSTGRES_USER=app", "POSTGRES_PASSWORD=secret")
            .hostConfig(HostConfig.builder()
                .binds("webapp-db-data:/var/lib/postgresql/data")
                .build())
            .build();
        
        // Application container
        ContainerConfig appConfig = ContainerConfig.builder()
            .image("nginx:latest")
            .hostConfig(HostConfig.builder()
                .binds(
                    "webapp-logs:/var/log/nginx",
                    "webapp-cache:/var/cache/nginx"
                )
                .portBindings(Map.of("80/tcp", 
                    List.of(PortBinding.of("0.0.0.0", "8080"))))
                .build())
            .build();
        
        ContainerCreation dbContainer = docker.createContainer(dbConfig, "webapp-db");
        ContainerCreation appContainer = docker.createContainer(appConfig, "webapp-app");
        
        docker.startContainer(dbContainer.id());
        docker.startContainer(appContainer.id());
        
        System.out.println("Application deployed with volume mounts");
        
        // Verify mounts
        verifyContainerMounts(docker, appContainer.id());
    }
    
    private void verifyContainerMounts(DockerClient docker, String containerId) 
            throws DockerException, InterruptedException {
        
        ContainerInfo info = docker.inspectContainer(containerId);
        
        System.out.println("Container mounts for " + containerId + ":");
        for (ContainerMount mount : info.mounts()) {
            System.out.println("  Type: " + mount.type());
            System.out.println("  Source: " + mount.source());
            System.out.println("  Destination: " + mount.destination());
            System.out.println("  Mode: " + mount.mode());
            System.out.println("  RW: " + mount.rw());
            System.out.println("  ---");
        }
    }
    
    private void performVolumeOperations(DockerClient docker) 
            throws DockerException, InterruptedException {
        
        System.out.println("Performing volume operations...");
        
        // Backup database volume
        backupVolume(docker, "webapp-db-data", "/tmp/backup");
        
        // Analyze volume usage
        analyzeVolumeUsage(docker);
        
        // List volumes with specific labels
        VolumeList webappVolumes = docker.listVolumes(
            ListVolumesParam.filter("label", "application=webapp")
        );
        
        System.out.println("Webapp volumes:");
        for (Volume volume : webappVolumes.volumes()) {
            System.out.println("  " + volume.name() + " (" + volume.driver() + ")");
        }
    }
    
    private void cleanupVolumeDemo(DockerClient docker) {
        try {
            System.out.println("Cleaning up volume demo...");
            
            // Stop and remove containers
            List<Container> containers = docker.listContainers(
                DockerClient.ListContainersParam.allContainers()
            );
            
            for (Container container : containers) {
                if (container.names().stream().anyMatch(name -> name.contains("webapp-"))) {
                    docker.stopContainer(container.id(), 5);
                    docker.removeContainer(container.id());
                    System.out.println("Removed container: " + container.id());
                }
            }
            
            // Remove demo volumes
            String[] volumesToRemove = {"webapp-db-data", "webapp-logs", "webapp-cache"};
            for (String volumeName : volumesToRemove) {
                try {
                    docker.removeVolume(volumeName);
                    System.out.println("Removed volume: " + volumeName);
                } catch (Exception e) {
                    System.err.println("Could not remove volume " + volumeName + ": " + e.getMessage());
                }
            }
            
        } catch (Exception e) {
            System.err.println("Cleanup error: " + e.getMessage());
        }
    }
}

The volume management system provides comprehensive control over persistent storage with support for multiple storage drivers, backup strategies, data migration, and lifecycle management for containerized applications.

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