# Runtime Crate - Comprehensive Integration Guide ## Overview The Runtime crate provides a unified abstraction layer for managing multiple container runtimes across different platforms and architectures. This guide covers advanced integration patterns, platform-specific considerations, and best practices for using the runtime crate in production environments. ## Table of Contents 1. [Supported Runtimes](#supported-runtimes) 2. [Platform Detection Strategy](#platform-detection-strategy) 3. [Socket Path Configuration](#socket-path-configuration) 4. [Remote Runtime Access](#remote-runtime-access) 5. [Docker Compose Integration](#docker-compose-integration) 6. [Configuration Patterns](#configuration-patterns) 7. [Error Handling](#error-handling) 8. [Performance Tuning](#performance-tuning) 9. [Security Considerations](#security-considerations) 10. [Troubleshooting](#troubleshooting) ## Supported Runtimes ### Docker **Platforms**: Linux, macOS (Docker Desktop), Windows (WSL2) **Socket Paths**: - Linux: `/var/run/docker.sock` - macOS: `~/.docker/run/docker.sock` (Docker Desktop) - Windows/WSL2: `/var/run/docker.sock` **Key Features**: - Industry-standard container runtime - Full Docker Compose support - TLS certificate support - Buildkit support **Configuration Example**: ```rust use runtime::{RuntimeConfig, RuntimeType}; let config = RuntimeConfig { runtime: RuntimeType::Docker, socket_path: "/var/run/docker.sock".to_string(), environment: [ ("DOCKER_HOST".to_string(), "unix:///var/run/docker.sock".to_string()), ].iter().cloned().collect(), ..Default::default() }; ``` ### Podman **Platforms**: Linux (all distributions), macOS (rootless mode) **Socket Paths**: - Linux root: `/run/podman/podman.sock` - Linux rootless: `$XDG_RUNTIME_DIR/podman/podman.sock` - macOS: `$XDG_RUNTIME_DIR/podman/podman.sock` **Key Features**: - Docker-compatible API - Rootless container execution - Systemd integration - Podman Compose support **Rootless Configuration**: ```rust use runtime::{RuntimeConfig, RuntimeType}; let xdg_runtime = std::env::var("XDG_RUNTIME_DIR") .unwrap_or_else(|_| format!("/run/user/{}", unsafe { libc::getuid() })); let config = RuntimeConfig { runtime: RuntimeType::Podman, socket_path: format!("{}/podman/podman.sock", xdg_runtime), ..Default::default() }; ``` ### OrbStack **Platforms**: macOS (Intel and Apple Silicon) - Default macOS runtime **Socket Path**: `~/.orbstack/run/docker.sock` **Key Features**: - Fastest macOS container runtime - Native integration with macOS filesystem - Full Docker Compose compatibility - Minimal resource overhead **Configuration Example**: ```rust use runtime::{RuntimeConfig, RuntimeType}; let home = std::env::var("HOME").expect("HOME not set"); let config = RuntimeConfig { runtime: RuntimeType::OrbStack, socket_path: format!("{}/.orbstack/run/docker.sock", home), ..Default::default() }; ``` ### Colima **Platforms**: macOS, Linux (via Lima) **Socket Paths**: - macOS: `~/.colima/docker.sock` - Linux: `/var/run/docker.sock` (proxied via Colima) **Key Features**: - Lightweight VM-based runtime - Docker CLI compatibility - Resource isolation - Cross-platform support ### nerdctl **Platforms**: Linux, macOS, Windows **Socket Path**: `unix:///run/containerd/containerd.sock` **Key Features**: - containerd-based runtime - Docker-compatible CLI - Efficient resource usage - Kubernetes integration ## Platform Detection Strategy The runtime crate implements intelligent platform-specific detection: ### Linux Detection Priority ``` 1. Docker (socket: /var/run/docker.sock) 2. Podman rootless (socket: $XDG_RUNTIME_DIR/podman/podman.sock) 3. Podman root (socket: /run/podman/podman.sock) 4. nerdctl (socket: unix:///run/containerd/containerd.sock) 5. Colima (socket: ~/.colima/docker.sock) ``` **Implementation**: ```rust use runtime::detect_runtime; #[tokio::main] async fn main() -> Result<(), Box> { let runtime = detect_runtime().await?; match runtime { RuntimeType::Docker => println!("Using Docker"), RuntimeType::Podman => println!("Using Podman"), _ => println!("Using: {}", runtime.name()), } Ok(()) } ``` ### macOS Detection Priority ``` 1. OrbStack (socket: ~/.orbstack/run/docker.sock) 2. Docker Desktop (socket: ~/.docker/run/docker.sock) 3. Colima (socket: ~/.colima/docker.sock) 4. Podman (socket: $XDG_RUNTIME_DIR/podman/podman.sock) 5. nerdctl (socket: unix:///run/containerd/containerd.sock) ``` **Rationale**: OrbStack offers superior performance on macOS compared to Docker Desktop, so it's preferred when available. ### Windows Detection Windows requires WSL2 (Windows Subsystem for Linux 2) for container support. The detection mechanism checks for available runtimes within WSL2 and follows the Linux priority list. ## Socket Path Configuration ### Standard Socket Paths Each runtime exposes a well-known socket path for communication: ```rust use runtime::RuntimeType; fn get_socket_path(runtime: RuntimeType) -> String { match runtime { RuntimeType::Docker => "/var/run/docker.sock".to_string(), RuntimeType::Podman => { std::env::var("XDG_RUNTIME_DIR") .map(|xdg| format!("{}/podman/podman.sock", xdg)) .unwrap_or_else(|_| "/run/podman/podman.sock".to_string()) } RuntimeType::OrbStack => { let home = std::env::var("HOME").expect("HOME not set"); format!("{}/.orbstack/run/docker.sock", home) } RuntimeType::Colima => { let home = std::env::var("HOME").expect("HOME not set"); format!("{}/.colima/docker.sock", home) } RuntimeType::Nerdctl => "unix:///run/containerd/containerd.sock".to_string(), } } ``` ### Custom Socket Paths For non-standard configurations (e.g., custom Docker socket location, remote access): ```rust use runtime::{RuntimeConfig, RuntimeType}; let config = RuntimeConfig { runtime: RuntimeType::Docker, socket_path: "/custom/docker.sock".to_string(), ..Default::default() }; ``` ### Environment Variable Overrides Use environment variables for dynamic configuration: ```rust use runtime::RuntimeConfig; let socket_path = std::env::var("RUNTIME_SOCKET_PATH") .unwrap_or_else(|_| "/var/run/docker.sock".to_string()); let config = RuntimeConfig { socket_path, ..Default::default() }; ``` ## Remote Runtime Access ### SSH-Based Remote Access Configure remote runtime access via SSH: ```rust use runtime::{RuntimeConfig, RemoteConfig}; let remote = RemoteConfig { enabled: true, host: "docker.example.com".to_string(), user: "docker-user".to_string(), port: 22, private_key: Some("/home/user/.ssh/id_rsa".to_string()), password: None, known_hosts: Some("/home/user/.ssh/known_hosts".to_string()), jump_host: None, // For bastion/jump host scenarios }; let config = RuntimeConfig { remote_config: Some(remote), ..Default::default() }; ``` ### Jump Host Configuration For accessing runtimes through a bastion host: ```rust use runtime::{RuntimeConfig, RemoteConfig}; let jump_host = RemoteConfig { host: "bastion.example.com".to_string(), user: "bastion-user".to_string(), private_key: Some("/home/user/.ssh/bastion_key".to_string()), ..Default::default() }; let remote = RemoteConfig { enabled: true, host: "docker.internal.example.com".to_string(), user: "docker-user".to_string(), private_key: Some("/home/user/.ssh/docker_key".to_string()), jump_host: Some(Box::new(jump_host)), ..Default::default() }; let config = RuntimeConfig { remote_config: Some(remote), ..Default::default() }; ``` ### TLS/HTTPS Remote Access ```rust use runtime::RuntimeConfig; let config = RuntimeConfig { socket_path: "tcp://docker.example.com:2376".to_string(), environment: [ ("DOCKER_HOST".to_string(), "tcp://docker.example.com:2376".to_string()), ("DOCKER_CERT_PATH".to_string(), "/path/to/certs".to_string()), ("DOCKER_TLS_VERIFY".to_string(), "1".to_string()), ].iter().cloned().collect(), ..Default::default() }; ``` ## Docker Compose Integration ### Automatic Compose Adaptation The runtime crate can adapt Docker Compose files for different runtimes: ```rust use runtime::adapt_compose; #[tokio::main] async fn main() -> Result<(), Box> { let adapted = adapt_compose( "docker-compose.yaml", RuntimeType::Podman ).await?; println!("Adapted compose: {}", adapted); Ok(()) } ``` ### Compose File Differences Different runtimes may require compose file adjustments: **Docker** (Standard): ```yaml version: '3.8' services: app: image: my-app:latest ports: - "8080:8080" ``` **Podman** (Rootless considerations): ```yaml version: '3.8' services: app: image: my-app:latest ports: - "8080:8080" # May require podman-compose specific directives ``` **OrbStack** (Filesystem integration): ```yaml version: '3.8' services: app: image: my-app:latest volumes: - ./data:/data:z # z flag for SELinux compatibility ``` ### Compose Version Support - **Version 3.x**: Fully supported across all runtimes - **Version 2.x**: Limited support; migration recommended - **Buildx Compose**: Docker and Podman only ## Configuration Patterns ### Environment-Based Configuration ```rust use runtime::{RuntimeConfig, RuntimeType}; fn load_config_from_env() -> RuntimeConfig { let runtime_type = std::env::var("CONTAINER_RUNTIME") .unwrap_or_else(|_| "docker".to_string()); let socket_path = std::env::var("CONTAINER_SOCKET") .unwrap_or_else(|_| { match runtime_type.as_str() { "podman" => "$XDG_RUNTIME_DIR/podman/podman.sock".to_string(), _ => "/var/run/docker.sock".to_string(), } }); RuntimeConfig { runtime: RuntimeType::from_str(&runtime_type).unwrap_or(RuntimeType::Docker), socket_path, ..Default::default() } } ``` ### File-Based Configuration ```rust use serde::{Deserialize, Serialize}; use std::fs; #[derive(Serialize, Deserialize)] struct RuntimeSettings { runtime: String, socket_path: String, environment: std::collections::HashMap, } fn load_config_from_file(path: &str) -> Result> { let content = fs::read_to_string(path)?; let settings: RuntimeSettings = serde_json::from_str(&content)?; Ok(settings) } ``` ### Builder Pattern Configuration ```rust use runtime::{RuntimeConfig, RuntimeType}; let config = RuntimeConfig::builder() .runtime(RuntimeType::Docker) .socket_path("/var/run/docker.sock") .with_env("DOCKER_BUILDKIT", "1") .with_env("COMPOSE_DOCKER_CLI_BUILD", "1") .build(); ``` ## Error Handling ### Common Error Scenarios **Socket Not Found**: ```rust use runtime::{detect_runtime, RuntimeError}; #[tokio::main] async fn main() -> Result<(), Box> { match detect_runtime().await { Ok(runtime) => println!("Found: {}", runtime.name()), Err(RuntimeError::SocketNotFound(path)) => { eprintln!("Docker socket not found at {}", path); eprintln!("Please ensure Docker/Podman is running"); } Err(e) => eprintln!("Error: {}", e), } Ok(()) } ``` **Permission Denied**: ```rust use runtime::RuntimeError; match some_operation().await { Err(RuntimeError::PermissionDenied) => { eprintln!("Cannot access runtime socket"); eprintln!("Try: sudo usermod -aG docker $USER"); } Err(e) => eprintln!("Error: {}", e), Ok(result) => println!("Success: {:?}", result), } ``` **Connection Timeout**: ```rust use runtime::RuntimeError; use std::time::Duration; match runtime.with_timeout(Duration::from_secs(5)).info().await { Err(RuntimeError::Timeout) => { eprintln!("Runtime unresponsive (timeout after 5s)"); eprintln!("Check if Docker/Podman is running"); } Err(e) => eprintln!("Error: {}", e), Ok(info) => println!("Runtime info: {:?}", info), } ``` ## Performance Tuning ### Connection Pooling For applications making many runtime calls: ```rust use runtime::{RuntimeConfig, RuntimePool}; let pool = RuntimePool::with_size( RuntimeConfig::default(), 10 // Pool size ); // Acquire connections from pool let runtime = pool.get().await?; runtime.info().await?; runtime.close().await?; ``` ### Caching Runtime Information ```rust use runtime::detect_runtime; use std::sync::Arc; use tokio::sync::Mutex; #[tokio::main] async fn main() -> Result<(), Box> { let runtime = Arc::new(Mutex::new(detect_runtime().await?)); // Use cached runtime across async tasks let runtime_clone = Arc::clone(&runtime); tokio::spawn(async move { let rt = runtime_clone.lock().await; // Use cached runtime }).await?; Ok(()) } ``` ### Batch Operations ```rust use runtime::RuntimeBatch; let batch = RuntimeBatch::new(runtime); batch .add_pull("image:tag") .add_build("/path/to/dockerfile", "image:tag") .add_run("image:tag", vec!["command"]) .execute() .await?; ``` ## Security Considerations ### Socket Permissions Ensure proper socket file permissions: ```bash # Docker socket (default) ls -l /var/run/docker.sock # Should be: srw-rw---- root docker # Podman socket (rootless) ls -l $XDG_RUNTIME_DIR/podman/podman.sock # Should be: srw------- (user only) ``` ### User Privileges For rootless containers: ```rust use runtime::RuntimeConfig; // Verify running as unprivileged user if unsafe { libc::getuid() } == 0 { eprintln!("Warning: Running container operations as root"); eprintln!("Consider using rootless podman for security"); } let config = RuntimeConfig { // Configure for rootless operation ..Default::default() }; ``` ### TLS Certificates For remote access with TLS: ```rust use runtime::RuntimeConfig; let config = RuntimeConfig { tls_config: Some(TlsConfig { ca_cert: "/path/to/ca.pem".to_string(), client_cert: "/path/to/cert.pem".to_string(), client_key: "/path/to/key.pem".to_string(), verify: true, }), ..Default::default() }; ``` ### Environment Variable Sanitization ```rust use runtime::RuntimeConfig; // Avoid storing sensitive data in environment variables let config = RuntimeConfig { environment: [ // Only non-sensitive variables ("DOCKER_BUILDKIT".to_string(), "1".to_string()), ].iter().cloned().collect(), // Load secrets from secure sources instead ..Default::default() }; ``` ## Troubleshooting ### Runtime Not Detected **Symptoms**: `detect_runtime()` fails or returns unexpected runtime **Diagnosis**: ```bash # Check if socket exists ls -l /var/run/docker.sock # or echo $XDG_RUNTIME_DIR ls -l $XDG_RUNTIME_DIR/podman/podman.sock ``` **Solutions**: 1. Ensure container runtime is installed 2. Start the runtime service: `systemctl start docker` or `systemctl --user start podman` 3. Check socket permissions: `sudo usermod -aG docker $USER` ### Connection Refused **Symptoms**: Operations fail with "Connection refused" **Diagnosis**: ```bash # Test socket connectivity docker ps # or podman ps # If this fails, daemon isn't running ``` **Solutions**: 1. Start Docker/Podman daemon 2. Check if socket is accessible 3. Verify firewall rules for remote access ### Compose Adaptation Issues **Symptoms**: Adapted compose file has errors **Solutions**: 1. Validate compose file: `docker compose config` 2. Check runtime-specific requirements 3. Review crate documentation for compatibility matrix ### Performance Issues **Symptoms**: Slow image pulls, container operations **Solutions**: 1. Check network connectivity 2. Monitor disk space for image storage 3. Enable BuildKit: `export DOCKER_BUILDKIT=1` 4. Consider using image registry caching ## Integration Patterns ### Kubernetes Integration For Kubernetes environments using Docker or CRI-compatible runtimes: ```rust use runtime::detect_runtime; #[tokio::main] async fn main() -> Result<(), Box> { // Detect runtime as per container spec let runtime = detect_runtime().await?; // Use for image operations before pod deployment runtime.pull("image:tag").await?; Ok(()) } ``` ### CI/CD Pipeline Integration ```rust use runtime::{detect_runtime, RuntimeConfig}; #[tokio::main] async fn main() -> Result<(), Box> { // Auto-detect available runtime in CI environment let runtime = detect_runtime().await?; // Build image runtime.build("/app", "my-image:latest").await?; // Test container runtime.run("my-image:latest", vec!["cargo", "test"]).await?; // Push to registry runtime.push("my-image:latest").await?; Ok(()) } ``` ### Multi-Environment Deployment ```rust use runtime::{RuntimeConfig, RuntimeType}; fn get_config_for_environment(env: &str) -> RuntimeConfig { match env { "development" => { // Local development: use detected runtime RuntimeConfig::default() } "staging" => { // Staging: connect to staging Docker host RuntimeConfig { socket_path: "tcp://docker.staging.internal:2376".to_string(), ..Default::default() } } "production" => { // Production: use production Docker host RuntimeConfig { socket_path: "tcp://docker.prod.internal:2376".to_string(), ..Default::default() } } _ => RuntimeConfig::default(), } } ``` ## Conclusion The Runtime crate provides flexible, production-ready container runtime abstraction. Proper configuration, error handling, and security practices ensure reliable container operations across diverse environments. For more information, see: - [Runtime README.md](README.md) - API documentation - [Examples](../../../examples/) - Complete examples - [Integration Architecture](../../../docs/integration-architecture.md) - System integration patterns