Skip to main content

herolib_virt/nerdctl/
mod.rs

1//! Nerdctl: Container Lifecycle Management
2//!
3//! This module provides a comprehensive Rust interface for managing containers with `nerdctl`,
4//! which is a Docker-compatible CLI for containerd. Nerdctl provides access to containerd's
5//! functionality without requiring Docker daemon.
6//!
7//! # Features
8//!
9//! - **Container Management**: Create, start, stop, remove containers
10//! - **Image Operations**: Pull, push, list, and manage container images
11//! - **Container Builder**: Fluent API for building complex container configurations
12//! - **Health Checks**: Configure and monitor container health status
13//! - **Resource Limits**: Set CPU, memory, and other resource constraints
14//! - **Port Mapping**: Configure port forwarding for network access
15//! - **Environment Variables**: Manage container environment configuration
16//! - **Volumes**: Mount volumes and manage data persistence
17//! - **Networking**: Configure container networking and DNS
18//! - **Log Access**: Retrieve container logs for debugging
19//!
20//! # Requirements
21//!
22//! - `nerdctl` command-line tool must be installed and on PATH
23//! - containerd runtime properly configured
24//! - Sufficient permissions to manage containers
25//!
26//! # Quick Start
27//!
28//! ## Creating and Running a Container
29//!
30//! ```rust,no_run
31//! use herolib_virt::nerdctl;
32//!
33//! // Run a simple container
34//! let result = nerdctl::run(
35//!     "nginx:latest",
36//!     Some("my-nginx"),
37//!     true, // detach
38//!     None, // ports
39//!     None, // snapshotter
40//! )?;
41//!
42//! println!("Container run result: {:?}", result);
43//! # Ok::<(), nerdctl::NerdctlError>(())
44//! ```
45//!
46//! ## Using the Container Builder
47//!
48//! ```rust,no_run
49//! use herolib_virt::nerdctl;
50//!
51//! let container = nerdctl::Container::from_image("my-app", "node:18")?
52//!     .with_port("3000:3000")
53//!     .with_env("NODE_ENV", "production")
54//!     .with_memory_limit("512m")
55//!     .with_cpu_limit("1.0")
56//!     .build()?;
57//!
58//! println!("Created: {}", container.name);
59//! # Ok::<(), nerdctl::NerdctlError>(())
60//! ```
61//!
62//! ## Managing Container Lifecycle
63//!
64//! ```rust,no_run
65//! use herolib_virt::nerdctl;
66//!
67//! // Create a container instance
68//! let container = nerdctl::Container::from_image("my-container", "nginx:latest")?;
69//!
70//! // Start the container
71//! container.start()?;
72//!
73//! // Stop the container
74//! container.stop()?;
75//!
76//! // Remove the container
77//! container.remove()?;
78//!
79//! // Get container status
80//! let info = container.status()?;
81//! println!("Status: {:?}", info.state);
82//! # Ok::<(), nerdctl::NerdctlError>(())
83//! ```
84//!
85//! ## Working with Images
86//!
87//! ```rust,no_run
88//! use herolib_virt::nerdctl;
89//!
90//! // Pull an image from registry
91//! nerdctl::image_pull("docker.io/library/nginx:latest")?;
92//!
93//! // List available images
94//! let images = nerdctl::images()?;
95//! println!("Images result: {:?}", images);
96//!
97//! // Remove an image
98//! nerdctl::image_remove("nginx:latest")?;
99//! # Ok::<(), nerdctl::NerdctlError>(())
100//! ```
101//!
102//! # Module Organization
103//!
104//! - `cmd` - Low-level command execution and parsing
105//! - `container` - Core container type and operations
106//! - `container_builder` - Fluent builder for container creation
107//! - `container_functions` - High-level container management functions
108//! - `container_operations` - Direct container operations
109//! - `container_types` - Data types for containers and statuses
110//! - `health_check` - Health check configuration
111//! - `health_check_script` - Health check script generation
112//! - `images` - Image management operations
113//!
114//! # Common Patterns
115//!
116//! ## Pattern: Simple Web Server
117//!
118//! ```rust,no_run
119//! use herolib_virt::nerdctl;
120//!
121//! // Create and run a web server
122//! let container = nerdctl::Container::from_image("web", "nginx:latest")?
123//!     .with_port("8080:80")  // Map host port 8080 to container port 80
124//!     .with_env("TZ", "UTC")
125//!     .with_restart_policy("unless-stopped")
126//!     .build()?;
127//!
128//! println!("Web server running on: http://localhost:8080");
129//! # Ok::<(), nerdctl::NerdctlError>(())
130//! ```
131//!
132//! ## Pattern: Database with Persistent Storage
133//!
134//! ```rust,no_run
135//! use herolib_virt::nerdctl;
136//!
137//! let container = nerdctl::Container::from_image("db", "postgres:15")?
138//!     .with_env("POSTGRES_PASSWORD", "secret123")
139//!     .with_env("POSTGRES_DB", "myapp")
140//!     .with_volume("/var/lib/postgresql/data:db-volume")
141//!     .with_memory_limit("1g")
142//!     .build()?;
143//!
144//! println!("Database container created with persistent volume");
145//! # Ok::<(), nerdctl::NerdctlError>(())
146//! ```
147//!
148//! ## Pattern: Multi-Container Application Stack
149//!
150//! ```rust,no_run
151//! use herolib_virt::nerdctl;
152//!
153//! // Web server
154//! let web = nerdctl::Container::from_image("web", "nginx:latest")?
155//!     .with_port("8080:80")
156//!     .build()?;
157//!
158//! // Application server
159//! let app = nerdctl::Container::from_image("app", "node:18")?
160//!     .with_env("NODE_ENV", "production")
161//!     .with_env("DATABASE_URL", "postgres://db:5432/myapp")
162//!     .build()?;
163//!
164//! // Database
165//! let db = nerdctl::Container::from_image("db", "postgres:15")?
166//!     .with_env("POSTGRES_PASSWORD", "secret")
167//!     .with_volume("/var/lib/postgresql/data:db-volume")
168//!     .build()?;
169//!
170//! println!("Application stack deployed");
171//! # Ok::<(), nerdctl::NerdctlError>(())
172//! ```
173//!
174//! # Error Handling
175//!
176//! All operations return `Result<T, NerdctlError>`. Common errors include:
177//!
178//! - **CommandExecutionFailed**: `nerdctl` not found or cannot execute
179//! - **CommandFailed**: Nerdctl command returned an error
180//! - **JsonParseError**: Failed to parse nerdctl JSON output
181//! - **ConversionError**: Type conversion failed
182//! - **Other**: Various validation or runtime errors
183//!
184//! # Health Checks
185//!
186//! Configure container health monitoring:
187//!
188//! ```rust,no_run
189//! use herolib_virt::nerdctl;
190//!
191//! let container = nerdctl::Container::from_image("web", "nginx:latest")?
192//!     .with_health_check("curl localhost:80")
193//!     .build()?;
194//! # Ok::<(), nerdctl::NerdctlError>(())
195//! ```
196//!
197//! # Rhai Integration
198//!
199//! Nerdctl operations are fully accessible from Rhai scripts:
200//!
201//! ```rhai
202//! // Create and run a container
203//! let container = ndc("my-web", "nginx:latest");
204//! print("Container created: " + container.id);
205//!
206//! // Start and stop
207//! ndc_start("my-web");
208//! ndc_stop("my-web", 30);
209//!
210//! // List containers
211//! let containers = ndc_ps();
212//! for c in containers {
213//!     print("Container: " + c.id + " - " + c.status);
214//! }
215//! ```
216
217mod cmd;
218mod container;
219mod container_builder;
220mod container_functions;
221mod container_operations;
222#[cfg(test)]
223mod container_test;
224mod container_types;
225mod health_check;
226mod health_check_script;
227mod images;
228pub mod rhai;
229
230use std::error::Error;
231use std::fmt;
232use std::io;
233
234/// Error type for nerdctl operations
235///
236/// Represents various errors that can occur during container management operations.
237#[derive(Debug)]
238pub enum NerdctlError {
239    /// The nerdctl command failed to execute
240    CommandExecutionFailed(io::Error),
241    /// The nerdctl command executed but returned an error
242    CommandFailed(String),
243    /// Failed to parse JSON output
244    JsonParseError(String),
245    /// Failed to convert data
246    ConversionError(String),
247    /// Generic error
248    Other(String),
249}
250
251impl fmt::Display for NerdctlError {
252    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
253        match self {
254            NerdctlError::CommandExecutionFailed(e) => {
255                write!(f, "Failed to execute nerdctl command: {}", e)
256            }
257            NerdctlError::CommandFailed(e) => write!(f, "Nerdctl command failed: {}", e),
258            NerdctlError::JsonParseError(e) => write!(f, "Failed to parse JSON: {}", e),
259            NerdctlError::ConversionError(e) => write!(f, "Conversion error: {}", e),
260            NerdctlError::Other(e) => write!(f, "{}", e),
261        }
262    }
263}
264
265impl Error for NerdctlError {
266    fn source(&self) -> Option<&(dyn Error + 'static)> {
267        match self {
268            NerdctlError::CommandExecutionFailed(e) => Some(e),
269            _ => None,
270        }
271    }
272}
273
274pub use cmd::*;
275pub use container_functions::*;
276pub use container_types::{Container, ContainerStatus, HealthCheck, ResourceUsage};
277pub use health_check_script::*;
278pub use images::*;