# lmrc-docker
> Part of the [LMRC Stack](https://gitlab.com/lemarco/lmrc-stack) - Infrastructure-as-Code toolkit for building production-ready Rust applications
[](https://crates.io/crates/lmrc-docker)
[](https://docs.rs/lmrc-docker)
[](https://github.com/lemarco/lmrc-docker)
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`:
```toml
[dependencies]
lmrc-docker = "0.1"
tokio = { version = "1.0", features = ["full"] }
```
## Quick Start
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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
```rust
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:
```bash
export DOCKER_HOST=tcp://localhost:2375
export DOCKER_HOST=unix:///var/run/docker.sock
```
## Error Handling
The library uses a comprehensive error type system:
```rust
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:
```rust
let client = DockerClient::new()?;
let bollard = client.inner();
// Use bollard directly
let info = bollard.info().await?;
```
### Streaming Logs
```rust
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](examples/) directory for complete working examples:
- [`basic_container.rs`](examples/basic_container.rs) - Basic container lifecycle
- [`build_image.rs`](examples/build_image.rs) - Building Docker images
- [`list_resources.rs`](examples/list_resources.rs) - Listing containers, images, networks, volumes
- [`registry_operations.rs`](examples/registry_operations.rs) - Registry management operations
Run examples with:
```bash
cargo run --example basic_container
cargo run --example registry_operations
```
## Testing
The library includes integration tests that require a running Docker daemon:
```bash
# 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:
- Apache License, Version 2.0 ([LICENSE-APACHE](../../LICENSE-APACHE) or <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](../../LICENSE-MIT) or <http://opensource.org/licenses/MIT>)
at your option.
## Acknowledgments
Built on top of [Bollard](https://github.com/fussybeaver/bollard), the excellent Docker daemon API for Rust.
## Related Projects
- [bollard](https://crates.io/crates/bollard) - Lower-level Docker API
- [shiplift](https://crates.io/crates/shiplift) - Alternative Docker API client
- [dockworker](https://crates.io/crates/dockworker) - Docker daemon API wrapper