#[cfg(feature = "templates")]
use docker_wrapper::{
DockerCommand, MongodbConnectionString, MongodbTemplate, MysqlConnectionString, MysqlTemplate,
NetworkCreateCommand, NginxTemplate, PostgresConnectionString, PostgresTemplate, RedisTemplate,
Template, VolumeCreateCommand, VolumeRmCommand,
};
#[cfg(feature = "templates")]
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
println!("๐ Docker Template Showcase\n");
println!("This example demonstrates a complete microservices setup with:");
println!("- Custom networking for container communication");
println!("- Persistent data volumes");
println!("- Health checks and readiness probes");
println!("- Resource limits");
println!("- Connection management\n");
let unique_id = uuid::Uuid::new_v4();
println!("Creating application network...");
let network_name = format!("showcase-network-{}", unique_id);
NetworkCreateCommand::new(&network_name)
.driver("bridge")
.execute()
.await?;
println!(" Network '{}' created", network_name);
println!("\nCreating persistent volumes...");
let postgres_volume = format!("showcase-postgres-{}", unique_id);
let mongo_volume = format!("showcase-mongo-{}", unique_id);
let redis_volume = format!("showcase-redis-{}", unique_id);
let redis_name = format!("showcase-redis-{}", unique_id);
let postgres_name = format!("showcase-postgres-{}", unique_id);
let mysql_name = format!("showcase-mysql-{}", unique_id);
let mongodb_name = format!("showcase-mongodb-{}", unique_id);
let nginx_name = format!("showcase-nginx-{}", unique_id);
VolumeCreateCommand::new()
.name(&postgres_volume)
.execute()
.await?;
VolumeCreateCommand::new()
.name(&mongo_volume)
.execute()
.await?;
VolumeCreateCommand::new()
.name(&redis_volume)
.execute()
.await?;
println!(" Volumes created");
println!("\nDeploying Redis cache...");
let redis = RedisTemplate::new(&redis_name)
.port(16379)
.password("redis_secure_pass")
.with_persistence(&redis_volume)
.memory_limit("256m")
.network(&network_name);
let redis_id = redis.start_and_wait().await?;
println!(" Redis ready (Container: {})", &redis_id[..12]);
let ping_result = redis
.exec(vec!["redis-cli", "-a", "redis_secure_pass", "ping"])
.await?;
println!(" Redis PING: {}", ping_result.stdout.trim());
println!("\nDeploying PostgreSQL database...");
let postgres = PostgresTemplate::new(&postgres_name)
.port(15432)
.database("showcase_db")
.user("app_user")
.password("postgres_secure_pass")
.with_persistence(&postgres_volume)
.memory_limit("512m")
.network(&network_name)
.postgres_args("--max_connections=100");
let postgres_id = postgres.start_and_wait().await?;
println!(" PostgreSQL ready (Container: {})", &postgres_id[..12]);
let pg_conn = PostgresConnectionString::from_template(&postgres);
println!(" ๐ Connection URL: {}", pg_conn.url());
println!(" ๐ Connection String: {}", pg_conn.key_value());
println!(" ๐จ Creating sample schema...");
postgres
.exec(vec![
"psql",
"-U",
"app_user",
"-d",
"showcase_db",
"-c",
"CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
username VARCHAR(50) UNIQUE NOT NULL,
email VARCHAR(100) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);",
])
.await?;
postgres
.exec(vec![
"psql",
"-U",
"app_user",
"-d",
"showcase_db",
"-c",
"INSERT INTO users (username, email) VALUES
('alice', 'alice@example.com'),
('bob', 'bob@example.com')
ON CONFLICT DO NOTHING;",
])
.await?;
println!(" โ
Schema created and sample data inserted");
println!("\n๐ฌ Deploying MySQL database...");
let mysql = MysqlTemplate::new(&mysql_name)
.port(13306)
.database("analytics_db")
.user("analytics_user")
.password("mysql_secure_pass")
.root_password("mysql_root_pass")
.character_set("utf8mb4")
.collation("utf8mb4_unicode_ci")
.memory_limit("512m")
.network(&network_name);
let mysql_id = mysql.start_and_wait().await?;
println!(" โ
MySQL ready (Container: {})", &mysql_id[..12]);
let mysql_conn = MysqlConnectionString::from_template(&mysql);
println!(" ๐ Connection URL: {}", mysql_conn.url());
println!(" ๐ JDBC URL: {}", mysql_conn.jdbc());
println!("\n๐ Deploying MongoDB...");
let mongodb = MongodbTemplate::new(&mongodb_name)
.port(27018)
.root_username("mongo_admin")
.root_password("mongo_secure_pass")
.database("documents_db")
.with_auth()
.with_persistence(&mongo_volume)
.memory_limit("512m")
.network(&network_name);
let mongodb_id = mongodb.start_and_wait().await?;
println!(" โ
MongoDB ready (Container: {})", &mongodb_id[..12]);
let mongo_conn = MongodbConnectionString::from_template(&mongodb);
println!(" ๐ Connection URL: {}", mongo_conn.url());
println!("\n๐ Deploying Nginx reverse proxy...");
let html_content = r#"<!DOCTYPE html>
<html>
<head>
<title>Docker Template Showcase</title>
<style>
body { font-family: Arial, sans-serif; margin: 40px; }
h1 { color: #333; }
.service {
background: #f0f0f0;
padding: 15px;
margin: 10px 0;
border-radius: 5px;
}
.status { color: green; font-weight: bold; }
</style>
</head>
<body>
<h1>๐ Docker Template Showcase</h1>
<p>All services are running successfully!</p>
<div class="service">
<h3>๐ด Redis Cache</h3>
<p class="status">โ
Running on port 16379</p>
</div>
<div class="service">
<h3>๐ PostgreSQL Database</h3>
<p class="status">โ
Running on port 15432</p>
</div>
<div class="service">
<h3>๐ฌ MySQL Database</h3>
<p class="status">โ
Running on port 13306</p>
</div>
<div class="service">
<h3>๐ MongoDB</h3>
<p class="status">โ
Running on port 27018</p>
</div>
</body>
</html>"#;
use std::io::Write;
let temp_dir = std::env::temp_dir();
let html_file = temp_dir.join("showcase-index.html");
let mut file = std::fs::File::create(&html_file)?;
file.write_all(html_content.as_bytes())?;
file.sync_all()?;
let nginx = NginxTemplate::new(&nginx_name)
.port(8080)
.content(html_file.to_str().unwrap())
.memory_limit("128m")
.network(&network_name);
let nginx_id = nginx.start_and_wait().await?;
println!(" โ
Nginx ready (Container: {})", &nginx_id[..12]);
println!(" ๐ Access the dashboard at: http://localhost:8080");
println!("\nโจ Verifying all services...");
let mut all_running = true;
if redis.is_running().await? {
println!(" โ
Redis is healthy");
} else {
println!(" โ Redis is not running");
all_running = false;
}
if postgres.is_running().await? {
println!(" โ
PostgreSQL is healthy");
} else {
println!(" โ PostgreSQL is not running");
all_running = false;
}
if mysql.is_running().await? {
println!(" โ
MySQL is healthy");
} else {
println!(" โ MySQL is not running");
all_running = false;
}
if mongodb.is_running().await? {
println!(" โ
MongoDB is healthy");
} else {
println!(" โ MongoDB is not running");
all_running = false;
}
if nginx.is_running().await? {
println!(" โ
Nginx is healthy");
} else {
println!(" โ Nginx is not running");
all_running = false;
}
if all_running {
println!("\n๐ All services are running successfully!");
} else {
println!("\nโ ๏ธ Some services failed to start properly");
}
println!("\n๐ Testing inter-container communication...");
let redis_ping_cmd = format!(
"apt-get update -qq && apt-get install -qq -y redis-tools > /dev/null 2>&1 && redis-cli -h {} -a redis_secure_pass ping",
redis_name
);
let redis_internal_test = postgres.exec(vec!["sh", "-c", &redis_ping_cmd]).await;
if let Ok(result) = redis_internal_test {
if result.stdout.contains("PONG") {
println!(" โ
PostgreSQL can connect to Redis via network");
}
}
println!("\n๐ Sample logs from services:");
let redis_logs = redis.logs(false, Some("5")).await?;
println!("\n Redis logs (last 5 lines):");
for line in redis_logs.stdout.lines().take(5) {
println!(" {}", line);
}
println!("\n๐ก Services are running. Press Enter to clean up...");
let mut input = String::new();
std::io::stdin().read_line(&mut input)?;
println!("\n๐งน Cleaning up...");
println!(" Stopping containers...");
nginx.stop().await?;
mongodb.stop().await?;
mysql.stop().await?;
postgres.stop().await?;
redis.stop().await?;
println!(" Removing containers...");
nginx.remove().await?;
mongodb.remove().await?;
mysql.remove().await?;
postgres.remove().await?;
redis.remove().await?;
println!(" Removing volumes...");
VolumeRmCommand::new(&redis_volume)
.force()
.execute()
.await?;
VolumeRmCommand::new(&postgres_volume)
.force()
.execute()
.await?;
VolumeRmCommand::new(&mongo_volume)
.force()
.execute()
.await?;
println!(" Removing network...");
use docker_wrapper::NetworkRmCommand;
NetworkRmCommand::new(&network_name).execute().await?;
println!("\nโ
All resources cleaned up successfully!");
println!("๐ Thank you for trying the Docker Template Showcase!");
Ok(())
}
#[cfg(not(feature = "templates"))]
fn main() {
eprintln!("This example requires the 'templates' feature to be enabled.");
eprintln!("Run with: cargo run --features templates --example template_showcase");
}