A Java library to manage Docker, Podman, and Buildah through a unified interface.
This library provides a consistent API for working with different container technologies:
- Docker
- Podman
- Buildah
The Unified Container Manager Library simplifies container operations by abstracting away the differences between container tools. It allows developers to:
- Build, run, and manage containers using a single API
- Switch between container technologies without changing code
- Automatically detect available container tools on the system
- Execute container operations with proper error handling and logging
- Support for both CLI-based and API-based container tool interactions
- Java 21 or higher
- Maven 3.6 or higher
- One or more container tools (Docker, Podman, or Buildah) installed on your system
To build the project locally:
mvn clean packageThe JAR file will be created in the target directory.
This project includes a GitHub Actions workflow that automatically builds the JAR file and generates JavaDocs when code is pushed to the main/master branch or when a pull request is created against these branches.
The workflow:
- Sets up a Java 21 environment
- Builds the project with Maven
- Generates JavaDocs
- Uploads the resulting JAR and JavaDocs as build artifacts
- Deploys the JavaDocs to GitHub Pages (only on push to main/master)
To access the built JAR from GitHub Actions:
- Go to your GitHub repository
- Navigate to the Actions tab
- Select the latest workflow run
- Download the artifact from the Artifacts section
The project's JavaDocs are automatically generated and published to GitHub Pages on every push to the main/master branch. You can access the latest JavaDocs at:
https://[your-github-username].github.io/container-manager-lib/
Replace [your-github-username] with your actual GitHub username or organization name.
This project includes a GitHub Actions workflow that automatically deploys the library to Maven Central when a new GitHub release is created.
To release a new version:
- Update the version in
pom.xml - Create a new release in GitHub with an appropriate tag (e.g., v0.1.0)
- The GitHub Actions workflow will automatically build and deploy the library to Maven Central
The following secrets must be configured in your GitHub repository settings:
OSS_NEXUS_USER: Your Sonatype OSSRH usernameOSS_NEXUS_PASS: Your Sonatype OSSRH passwordGPG_PRIVATE_KEY: Your GPG private key for signing artifactsGPG_PASSPHRASE: The passphrase for your GPG key
These secrets are used by the GitHub Actions workflow to authenticate with Maven Central and sign the artifacts.
Add the JAR to your project's dependencies and use the container management API as shown in the examples below:
import Strategy.io.github.randomcodespace.ContainerService;
import Enums.io.github.randomcodespace.ToolType;
import DTOs.io.github.randomcodespace.ContainerConfig;
import DTOs.io.github.randomcodespace.ImageBuildConfig;
import DTOs.io.github.randomcodespace.ContainerInfo;
import DTOs.io.github.randomcodespace.ImageInfo;
import Exceptions.io.github.randomcodespace.ContainerManagerException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
public class ContainerExample {
public static void main(String[] args) {
// Create a ContainerService with preferred tool order
ContainerService service = new ContainerService(
Arrays.asList(ToolType.DOCKER, ToolType.PODMAN, ToolType.BUILDAH)
);
try {
// Initialize the service (detects available tools)
service.initialize();
// Get information about the active tool
service.getActiveToolType().ifPresent(
toolType -> System.out.println("Using: " + toolType)
);
// Use the service for container and image operations
runContainerExample(service);
buildImageExample(service);
} catch (ContainerManagerException e) {
System.err.println("Container operation failed: " + e.getMessage());
} finally {
try {
service.close();
} catch (Exception e) {
System.err.println("Error closing service: " + e.getMessage());
}
}
}
private static void runContainerExample(ContainerService service) throws ContainerManagerException {
// Create a container configuration
ContainerConfig config = new ContainerConfig.ContainerConfigBuilder()
.imageName("nginx")
.tag("latest")
.name("web-server")
.portBindings(Arrays.asList("8080:80"))
.build();
// Create and start a container
String containerId = service.createContainer(config).join();
System.out.println("Created container: " + containerId);
service.startContainer(containerId).join();
System.out.println("Container started");
// List running containers
List<ContainerInfo> containers = service.listContainers(false).join();
containers.forEach(container ->
System.out.println("Running container: " + container.getId() + " - " + container.getName())
);
// Stop and remove the container
service.stopContainer(containerId, 10).join();
service.removeContainer(containerId, true, true).join();
System.out.println("Container stopped and removed");
}
private static void buildImageExample(ContainerService service) throws ContainerManagerException {
// Pull an image
CompletableFuture<Void> pullFuture = service.pullImage("alpine", "latest",
progress -> System.out.println("Pull progress: " + progress)
);
pullFuture.join();
// Build a custom image
ImageBuildConfig buildConfig = new ImageBuildConfig.ImageBuildConfigBuilder()
.dockerfilePath("./Dockerfile")
.tag("my-custom-image:latest")
.build();
String imageId = service.buildImage(buildConfig,
output -> System.out.println("Build output: " + output)
).join();
System.out.println("Built image: " + imageId);
// List available images
List<ImageInfo> images = service.listImages().join();
images.forEach(image ->
System.out.println("Image: " + image.getId() + " - " + image.getName())
);
}
}The library provides a fully asynchronous API using CompletableFuture:
// Initialize the service asynchronously
ContainerService service = new ContainerService();
service.initializeAsync()
.thenCompose(v -> {
// Create a container
ContainerConfig config = new ContainerConfig.ContainerConfigBuilder()
.imageName("redis")
.tag("latest")
.name("cache-server")
.build();
return service.createContainer(config);
})
.thenCompose(containerId -> {
System.out.println("Container created: " + containerId);
return service.startContainer(containerId)
.thenApply(v -> containerId);
})
.thenCompose(containerId -> {
System.out.println("Container started");
// Do something with the running container
// Then stop and remove it
return service.stopContainer(containerId, null)
.thenCompose(v -> service.removeContainer(containerId, true, true));
})
.exceptionally(ex -> {
System.err.println("Operation failed: " + ex.getMessage());
return null;
})
.join();The library automatically detects available container tools:
// Create service with default tool detection
ContainerService service = new ContainerService();
service.initialize();
// Check which tool was detected and is being used
service.getActiveToolType().ifPresent(toolType -> {
switch (toolType) {
case DOCKER:
System.out.println("Using Docker");
break;
case PODMAN:
System.out.println("Using Podman");
break;
case BUILDAH:
System.out.println("Using Buildah");
break;
default:
System.out.println("Unknown tool");
}
});This project is licensed under the MIT License - see the LICENSE file for details.
The MIT License is a permissive license that is short and to the point. It lets people do anything with your code with proper attribution and without warranty.