Skip to main content

Crate ociman

Crate ociman 

Source
Expand description

§ociman - OCI Manager

A Rust library providing a unified API for OCI container runtimes (Docker, Podman).

Status: Pre-1.0 - exists to serve mbj/mrs monorepo, expect breaking changes without notice.

§Goals

  • Unified API: Single interface for OCI-compliant container runtimes
  • Auto-detection: Automatically detects available container runtime (tries Docker first, then Podman)
  • Configuration file: Override default backend preference via ~/.config/ociman.toml
  • Environment override: Control backend selection via OCIMAN_BACKEND environment variable
  • Container lifecycle management: Run, execute commands, inspect, and manage containers
  • Image building: Build images from Dockerfiles or inline instructions
  • Content-based hashing: Automatic tag generation based on SHA256 of build context/instructions for deterministic builds

§Backend Selection

ociman resolves the container backend using this priority chain:

  1. OCIMAN_BACKEND environment variable (docker or podman) — explicit selection, errors if not found
  2. ~/.config/ociman.toml — controls auto-detection preference
  3. Default — tries Docker first, falls back to Podman
# ~/.config/ociman.toml
default_backend = "podman" # or "docker"

§Executing Commands in Containers

Use container.exec() to run commands inside a running container:

// Simple command execution
container.exec("echo")
    .argument("hello")
    .status().await?;

// Capture stdout
let output = container.exec("cat")
    .argument("/etc/os-release")
    .build()
    .stdout_capture()
    .string().await?;

// With environment variables and stdin
let result = container.exec("psql")
    .argument("--dbname=mydb")
    .environment_variable(PG_PASSWORD, "secret")
    .stdin(b"SELECT 1;")
    .build()
    .stdout_capture()
    .bytes().await?;

// Interactive shell with PTY (`-it`)
container.exec("sh")
    .tty()
    .interactive()
    .status().await?;

// Stdin pipe-through, no PTY (`-i`) — clean byte streams in both directions
container.exec("pg_dump")
    .argument("--dbname=mydb")
    .interactive()
    .status().await?;

The ExecCommand builder focuses on container exec configuration. tty() and interactive() map directly to the runtime --tty and --interactive flags and combine independently. For stream capture, use .build() to get a cmd_proc::Command, then use its stream methods.

§Container Stopping and Removal

Containers must be stopped and removed explicitly by the caller. ociman::Container intentionally does not implement Drop for automatic cleanup. This is a deliberate design decision:

  • Blocking I/O in Drop is unsafe: Stopping/removing a container shells out to docker/podman. If the subprocess fails, an unwrap() inside Drop causes a panic, which aborts the process when unwinding from another panic.
  • --rm is the correct cleanup mechanism: Use .remove() on the Definition to pass --rm to the container runtime. This ensures the runtime removes the container when it stops, even if the Rust process is killed.
  • Explicit lifecycle is clearer: Callers always know when stop/remove happens. There are no hidden side effects on scope exit.

Typical usage patterns:

// Pattern 1: Use --rm flag + with_container (most common)
// Container is explicitly stopped after the closure, and --rm handles removal.
let definition = Definition::new(backend, image).remove();
definition.with_container(async |container| {
    // use container
}).await;

// Pattern 2: Stop, commit, then remove (for snapshotting)
// Cannot use --rm here because the container must survive stop for commit.
let mut container = definition.run_detached().await;
container.stop().await;
container.commit(&snapshot_image, false).await?;
container.remove().await;

§Content-Based Image Hashing

ociman supports automatic tag generation based on content hashing (SHA256). This ensures deterministic builds where the same content always produces the same image tag.

Benefits:

  • Deterministic: Same content always produces the same tag
  • Automatic cache invalidation: Content changes automatically produce a new tag
  • No manual tag management: Hash is computed automatically
  • Reproducibility: Easy to verify if an image matches its source

Important: Content-based hashing only captures the Dockerfile and build context, not the base images. Using unspecific tags like FROM alpine:latest reduces reproducibility since latest can point to different images over time. For fully reproducible builds, use specific base image digests:

# Less reproducible - tag can change
FROM alpine:latest

# More reproducible - specific version tag
FROM alpine:3.19

# Most reproducible - pinned to specific digest
FROM alpine@sha256:6457d53fb065d6f250e1504b9bc42d5b6c65941d57532c072d929dd0628977d0

Re-exports§

pub use backend::Backend;
pub use backend::BridgeSubnetError;
pub use backend::ContainerHostnameResolver;
pub use backend::ResolveHostnameError;
pub use container::Container;
pub use container::ContainerArgument;
pub use container::ContainerId;
pub use container::ContainerName;
pub use container::ContainerNameError;
pub use container::Definition;
pub use container::Detach;
pub use container::Entrypoint;
pub use container::EnvironmentVariables;
pub use container::ExecCommand;
pub use container::InspectError;
pub use container::Mount;
pub use container::Protocol;
pub use container::Publish;
pub use container::PullPolicy;
pub use container::ReadContainerNameError;
pub use container::ReadHostTcpPortError;
pub use container::Remove;
pub use container::RunDetachedError;
pub use container::RunError;
pub use container::WithContainerError;
pub use container::Workdir;
pub use image::BuildArgumentKey;
pub use image::BuildArgumentKeyError;
pub use image::BuildArgumentValue;
pub use image::BuildDefinition;
pub use image::BuildSource;
pub use image::BuildTarget;
pub use image::Reference;

Modules§

backend
config
container
Container definitions and runtime handles.
hasher
Streaming hasher that length-prefixes each push so consecutive segments can’t blend into each other under the digest.
image
OCI image reference and build utilities.
label
OCI label types for containers and images.
platform
Platform support detection for container-based tools
reference
OCI image reference parsing and types.
testing
Testing utilities for container-based tests

Macros§

test_backend_setup
Sets up the test backend for async tests.