| Crates.io | lmrc-docker |
| lib.rs | lmrc-docker |
| version | 0.3.16 |
| created_at | 2025-11-26 17:44:33.657954+00 |
| updated_at | 2025-12-11 13:27:11.396961+00 |
| description | Docker client library for the LMRC Stack - ergonomic fluent APIs for containers, images, networks, volumes, and registry management |
| homepage | https://gitlab.com/lemarco/lmrc-stack/tree/main/libs/docker-manager |
| repository | https://gitlab.com/lemarco/lmrc-stack |
| max_upload_size | |
| id | 1951917 |
| size | 151,854 |
Part of the LMRC Stack - Infrastructure-as-Code toolkit for building production-ready Rust applications
An ergonomic, comprehensive Docker client library for Rust with fluent builder APIs for managing containers, images, networks, volumes, and registries.
thiserrorAdd this to your Cargo.toml:
[dependencies]
lmrc-docker = "0.1"
tokio = { version = "1.0", features = ["full"] }
use lmrc_docker::{DockerClient, Result};
#[tokio::main]
async fn main() -> Result<()> {
// Create a client
let client = DockerClient::new()?;
// Check Docker is available
client.ping().await?;
// Pull an image
client.images().pull("nginx:alpine", None).await?;
// Create and start a container
let container = client.containers()
.create("nginx:alpine")
.name("my-nginx")
.port(8080, 80, "tcp")
.env("ENV", "production")
.build()
.await?;
container.start().await?;
println!("Container started: {}", container.id());
// Stop and remove the container
container.stop(Some(10)).await?;
container.remove(false, false).await?;
Ok(())
}
use lmrc_docker::DockerClient;
let client = DockerClient::new()?;
// Create a container with advanced configuration
let container = client.containers()
.create("redis:alpine")
.name("my-redis")
.port(6379, 6379, "tcp")
.env("REDIS_PASSWORD", "secret")
.restart_always()
.memory_limit(512 * 1024 * 1024) // 512MB
.build()
.await?;
// Start the container
container.start().await?;
// View logs
let logs = container.logs(true, true, true, None).await?;
println!("Logs: {}", logs);
// Execute a command
let exec_id = container.exec(vec!["redis-cli".into(), "ping".into()], false).await?;
// Stop and remove
container.stop(Some(10)).await?;
container.remove(true, true).await?;
use lmrc_docker::DockerClient;
let client = DockerClient::new()?;
// Pull an image
client.images().pull("alpine:latest", None).await?;
// Build an image from a Dockerfile
let image_id = client.images()
.build("./my-app")
.tag("my-app:latest")
.dockerfile("Dockerfile")
.cache_from(vec!["my-app:cache"])
.execute()
.await?;
// Push to registry (requires authentication)
client.images().push("username/my-app:latest", None).await?;
// List images
let images = client.images().list(false).await?;
for image in images {
println!("Image: {:?}", image.repo_tags);
}
// Remove an image
client.images().remove("my-app:latest", false, false).await?;
use lmrc_docker::{DockerClient, RegistryConfig};
let client = DockerClient::new()?;
let registry = client.registry();
// Search for images
let results = registry.search("nginx", Some(10)).await?;
for result in results {
println!("{}: {} stars", result.name, result.star_count.unwrap_or(0));
}
// Authenticate with Docker Hub
let config = RegistryConfig::docker_hub(
"username".to_string(),
"password".to_string()
);
registry.login(&config).await?;
// Authenticate with GitHub Container Registry
let config = RegistryConfig::github(
"username".to_string(),
"github_token".to_string()
);
registry.login(&config).await?;
// Check if an image exists locally
let exists = registry.image_exists_locally("alpine:latest").await?;
// Tag an image
registry.tag_image("alpine:latest", "my-alpine", Some("v1.0")).await?;
// Export/Import images
let tar_data = registry.export_image("alpine:latest").await?;
let image_id = registry.import_image(tar_data, Some("imported:latest")).await?;
// Prune unused images
let reclaimed = registry.prune_images(true).await?;
println!("Reclaimed {} bytes", reclaimed);
use lmrc_docker::DockerClient;
let client = DockerClient::new()?;
// Create a network
let network = client.networks()
.create("my-network")
.driver("bridge")
.await?;
// Connect a container to a network
network.connect("container-id", None).await?;
// Disconnect a container
network.disconnect("container-id", false).await?;
// List networks
let networks = client.networks().list().await?;
// Remove network
network.remove().await?;
use lmrc_docker::DockerClient;
let client = DockerClient::new()?;
// Create a volume
let volume = client.volumes()
.create("my-volume")
.driver("local")
.await?;
// List volumes
let volumes = client.volumes().list().await?;
// Remove volume
volume.remove(false).await?;
// Prune unused volumes
let pruned = client.volumes().prune().await?;
use lmrc_docker::{DockerClient, DockerClientConfig};
// Connect via Unix socket
let client = DockerClient::connect_with_unix("/var/run/docker.sock")?;
// Connect via TCP
let client = DockerClient::connect_with_tcp("localhost:2375")?;
// Custom configuration
let config = DockerClientConfig::new()
.timeout(60)
.api_version("1.43");
let client = DockerClient::with_config(config)?;
The client respects the DOCKER_HOST environment variable:
export DOCKER_HOST=tcp://localhost:2375
export DOCKER_HOST=unix:///var/run/docker.sock
The library uses a comprehensive error type system:
use lmrc_docker::{DockerClient, DockerError, Result};
match client.containers().get("unknown-container") {
Ok(container) => println!("Found container"),
Err(DockerError::ContainerNotFound(id)) => {
eprintln!("Container {} not found", id);
}
Err(DockerError::Connection(msg)) => {
eprintln!("Connection error: {}", msg);
}
Err(e) => eprintln!("Other error: {}", e),
}
The library is organized into modular components:
client: Docker client configuration and connection managementcontainers: Container lifecycle operations with ContainerBuilderimages: Image operations with ImageBuilder for building imagesnetworks: Network creation and managementvolumes: Volume operationsregistry: Registry authentication, search, and image managementerror: Comprehensive error typesFor operations not covered by the high-level API:
let client = DockerClient::new()?;
let bollard = client.inner();
// Use bollard directly
let info = bollard.info().await?;
use futures_util::StreamExt;
let container = client.containers().get("my-container").await?;
let mut logs_stream = container.logs_stream(true, true, true, None).await?;
while let Some(log) = logs_stream.next().await {
match log {
Ok(line) => println!("{}", line),
Err(e) => eprintln!("Error: {}", e),
}
}
See the examples directory for complete working examples:
basic_container.rs - Basic container lifecyclebuild_image.rs - Building Docker imageslist_resources.rs - Listing containers, images, networks, volumesregistry_operations.rs - Registry management operationsRun examples with:
cargo run --example basic_container
cargo run --example registry_operations
The library includes integration tests that require a running Docker daemon:
# Run tests
cargo test
# Run specific test
cargo test test_container_lifecycle
Contributions are welcome! Please feel free to submit a Pull Request.
Part of the LMRC Stack project. Licensed under either of:
at your option.
Built on top of Bollard, the excellent Docker daemon API for Rust.