use docker_wrapper::{
DockerCommand, KillCommand, NetworkCreateCommand, NetworkInspectCommand, NetworkLsCommand,
NetworkRmCommand, RmCommand, RunCommand, VolumeCreateCommand, VolumeInspectCommand,
VolumeLsCommand, VolumeRmCommand,
};
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
println!("Docker Network and Volume Management Examples\n");
create_custom_network().await?;
use_named_volumes().await?;
multi_container_networking().await?;
volume_backup_pattern().await?;
cleanup().await?;
println!("\nAll examples completed successfully!");
Ok(())
}
async fn create_custom_network() -> Result<(), Box<dyn Error>> {
println!("=== Example 1: Custom Network Management ===\n");
println!("Creating custom network 'app-network'...");
NetworkCreateCommand::new("app-network")
.driver("bridge")
.subnet("172.20.0.0/16")
.ip_range("172.20.240.0/20")
.gateway("172.20.0.1")
.execute()
.await?;
println!("Listing networks...");
let output = NetworkLsCommand::new()
.format("table {{.Name}}\t{{.Driver}}\t{{.Scope}}")
.execute()
.await?;
println!("{}", output.stdout);
println!("Inspecting network details...");
let output = NetworkInspectCommand::new("app-network").execute().await?;
if !output.stdout.is_empty() {
println!("Network details available in JSON format");
}
Ok(())
}
async fn use_named_volumes() -> Result<(), Box<dyn Error>> {
println!("\n=== Example 2: Named Volume Management ===\n");
println!("Creating named volume 'app-data'...");
VolumeCreateCommand::new()
.name("app-data")
.driver("local")
.label("app", "docker-wrapper-example")
.label("environment", "development")
.execute()
.await?;
println!("Listing volumes with label filter...");
let output = VolumeLsCommand::new()
.filter("label", "app=docker-wrapper-example")
.execute()
.await?;
println!("{}", output.stdout);
println!("Running container with named volume...");
RunCommand::new("alpine:latest")
.name("volume-test")
.volume("app-data", "/data")
.cmd(vec![
"sh".to_string(),
"-c".to_string(),
"echo 'Hello from volume!' > /data/message.txt && cat /data/message.txt".to_string(),
])
.remove()
.execute()
.await?;
println!("Inspecting volume...");
let output = VolumeInspectCommand::new("app-data").execute().await?;
if !output.stdout.is_empty() {
println!("Volume details available in JSON format");
}
Ok(())
}
async fn multi_container_networking() -> Result<(), Box<dyn Error>> {
println!("\n=== Example 3: Multi-Container Networking ===\n");
println!("Starting Redis server...");
let redis_output = RunCommand::new("redis:alpine")
.name("redis-server")
.network("app-network")
.network_alias("redis")
.detach()
.execute()
.await?;
println!("Redis container: {}", &redis_output.0[..12]);
println!("Running client container...");
RunCommand::new("redis:alpine")
.name("redis-client")
.network("app-network")
.cmd(vec![
"redis-cli".to_string(),
"-h".to_string(),
"redis".to_string(),
"ping".to_string(),
])
.remove()
.execute()
.await?;
println!("Stopping Redis server...");
KillCommand::new("redis-server").execute().await?;
RmCommand::new("redis-server").execute().await?;
Ok(())
}
async fn volume_backup_pattern() -> Result<(), Box<dyn Error>> {
println!("\n=== Example 4: Volume Backup Pattern ===\n");
println!("Creating volume with sample data...");
VolumeCreateCommand::new()
.name("backup-source")
.execute()
.await?;
RunCommand::new("alpine:latest")
.volume("backup-source", "/source")
.cmd(vec![
"sh".to_string(),
"-c".to_string(),
"echo 'Important data' > /source/data.txt && echo 'Config' > /source/config.txt"
.to_string(),
])
.remove()
.execute()
.await?;
println!("Backing up volume to tar file...");
RunCommand::new("alpine:latest")
.volume("backup-source", "/source")
.volume(".", "/backup")
.cmd(vec![
"tar".to_string(),
"czf".to_string(),
"/backup/backup.tar.gz".to_string(),
"-C".to_string(),
"/source".to_string(),
".".to_string(),
])
.remove()
.execute()
.await?;
println!("Backup created: ./backup.tar.gz");
println!("Creating restore target volume...");
VolumeCreateCommand::new()
.name("backup-target")
.execute()
.await?;
println!("Restoring data to new volume...");
RunCommand::new("alpine:latest")
.volume("backup-target", "/target")
.volume(".", "/backup")
.cmd(vec![
"tar".to_string(),
"xzf".to_string(),
"/backup/backup.tar.gz".to_string(),
"-C".to_string(),
"/target".to_string(),
])
.remove()
.execute()
.await?;
println!("Verifying restored data...");
let output = RunCommand::new("alpine:latest")
.volume("backup-target", "/target")
.cmd(vec![
"ls".to_string(),
"-la".to_string(),
"/target".to_string(),
])
.remove()
.execute()
.await?;
println!("Restored files:\n{}", output.0);
Ok(())
}
async fn cleanup() -> Result<(), Box<dyn Error>> {
println!("\n=== Cleaning up resources ===\n");
println!("Removing custom network...");
let _ = NetworkRmCommand::new("app-network").execute().await;
println!("Removing volumes...");
for volume in &["app-data", "backup-source", "backup-target"] {
let _ = VolumeRmCommand::new(*volume).execute().await;
}
let _ = std::fs::remove_file("backup.tar.gz");
println!("Cleanup completed!");
Ok(())
}