#docker #devops #container-registry #bollard #api-bindings

lmrc-docker

Docker client library for the LMRC Stack - ergonomic fluent APIs for containers, images, networks, volumes, and registry management

26 releases

Uses new Rust 2024

new 0.3.14 Dec 3, 2025
0.3.13 Dec 2, 2025
0.3.9 Nov 30, 2025
0.2.12 Nov 27, 2025

#175 in Development tools


Used in 2 crates (via lmrc-pipeline)

MIT/Apache

99KB
1.5K SLoC

lmrc-docker

Part of the LMRC Stack - Infrastructure-as-Code toolkit for building production-ready Rust applications

Crates.io Documentation License

An ergonomic, comprehensive Docker client library for Rust with fluent builder APIs for managing containers, images, networks, volumes, and registries.

Features

  • Fluent Builder APIs: Ergonomic, chainable methods for creating and configuring Docker resources
  • Full Docker API Coverage: Complete support for containers, images, networks, and volumes
  • Registry Management: Search, authenticate, and manage images across multiple registries (Docker Hub, GitHub Container Registry, custom registries)
  • Async/Await: Built on Tokio for modern async Rust
  • Type-Safe: Leverages Rust's type system for compile-time safety
  • Comprehensive Error Handling: Detailed error types using thiserror
  • Well Documented: Extensive documentation and examples

Installation

Add this to your Cargo.toml:

[dependencies]
lmrc-docker = "0.1"
tokio = { version = "1.0", features = ["full"] }

Quick Start

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(())
}

Examples

Container Management

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?;

Image Operations

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?;

Registry Management

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);

Network Management

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?;

Volume Management

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?;

Configuration

Custom Docker Connection

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)?;

Environment Variables

The client respects the DOCKER_HOST environment variable:

export DOCKER_HOST=tcp://localhost:2375
export DOCKER_HOST=unix:///var/run/docker.sock

Error Handling

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),
}

Architecture

The library is organized into modular components:

  • client: Docker client configuration and connection management
  • containers: Container lifecycle operations with ContainerBuilder
  • images: Image operations with ImageBuilder for building images
  • networks: Network creation and management
  • volumes: Volume operations
  • registry: Registry authentication, search, and image management
  • error: Comprehensive error types

Advanced Usage

Direct Bollard Access

For operations not covered by the high-level API:

let client = DockerClient::new()?;
let bollard = client.inner();

// Use bollard directly
let info = bollard.info().await?;

Streaming Logs

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),
    }
}

Requirements

  • Rust 1.70 or later
  • Docker daemon running and accessible

Examples

See the examples directory for complete working examples:

Run examples with:

cargo run --example basic_container
cargo run --example registry_operations

Testing

The library includes integration tests that require a running Docker daemon:

# Run tests
cargo test

# Run specific test
cargo test test_container_lifecycle

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

Part of the LMRC Stack project. Licensed under either of:

at your option.

Acknowledgments

Built on top of Bollard, the excellent Docker daemon API for Rust.

Dependencies

~14–31MB
~441K SLoC