Skip to content

arcboxlabs/oci2rootfs

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

oci2rootfs

Convert OCI container images to ext4 rootfs filesystem images.

Features

  • Local conversion — read from an OCI Image Layout directory on disk
  • Docker cache paths — convert directly from Docker overlay2 chain-id directories
  • Remote pull — pull images directly from container registries (Docker Hub, GCR, etc.)
  • Multi-arch support — resolve platform-specific manifests from image indexes
  • Layer handling — apply tar layers in order with full OCI whiteout support (.wh.* deletes, .wh..wh..opq opaque)
  • Compression — gzip, zstd, and uncompressed layers
  • Auth — automatic credential resolution from Docker config

Usage

# From a local OCI layout directory
oci2rootfs ./oci-dir --output rootfs.ext4

# From a remote registry
oci2rootfs nginx:1.21 --output rootfs.ext4

# Custom size and platform
oci2rootfs ubuntu:22.04 --output rootfs.ext4 --size 1G --platform linux/arm64

# Insecure (HTTP) registry
oci2rootfs localhost:5000/myapp:latest --output rootfs.ext4 --insecure

Options

Flag Default Description
--output, -o (required) Output ext4 image path
--size 512M Image size (128M, 1G, etc.)
--platform linux/amd64 Target platform
--insecure false Allow HTTP registry connections
--label (none) Volume label written to the superblock (≤16 bytes)
--uuid random Filesystem UUID written to the superblock

Set RUST_LOG=info (or debug, trace) to see per-layer progress and timing on stderr — the CLI installs a tracing-subscriber fmt layer wired to RUST_LOG via env-filter.

Library

use oci2rootfs::{autodetect, Converter, OciLayoutSource, Platform};

// Local OCI layout
Converter::new("rootfs.ext4")
    .size(1024 * 1024 * 1024)
    .convert(
        OciLayoutSource::open("./oci-dir")?
            .platform(Platform::new("linux", "amd64")),
    )?;

// Local auto-detect (OCI layout or overlay2 path)
Converter::new("rootfs.ext4").convert(autodetect("./some-path")?)?;

// Remote registry (default feature: `remote`)
# #[cfg(feature = "remote")]
# async fn example() -> oci2rootfs::Result<()> {
use oci2rootfs::RemoteRef;

let source = RemoteRef::new("nginx:latest")
    .platform(Platform::default())
    .fetch()
    .await?;

// Remote fetches also expose the resolved manifest digest.
println!(
    "manifest: {}",
    source
        .manifest_digest()
        .expect("remote sources always resolve to a manifest")
);

// Image config (entrypoint/cmd/env/...) is available on the source.
if let Some(cfg) = source.config() {
    if let Some(container) = &cfg.config {
        println!("entrypoint: {:?}", container.entrypoint);
    }
}

Converter::new("rootfs.ext4").convert(source)?;
# Ok(())
# }

ext4 image properties

Property Value Configurable
Block size 4 KiB No (arcbox-ext4 fixed)
Journal none (effectively mkfs.ext4 -O ^has_journal) No
Feature flags `SPARSE_SUPER2 EXT_ATTR`
Volume label empty Ext4Options::label / --label
UUID random v4 Ext4Options::uuid / --uuid
ImageConfig exposed via ImageSource::config() for OCI layout and remote pulls; None for overlay2 sources (Docker keeps the config outside the layer tree)
Manifest digest exposed via ImageSource::manifest_digest() for OCI layout and remote pulls; None for overlay2 sources

Feature flags

Feature Default Pulls in
remote yes containerregistry-registry, containerregistry-auth, tokio, reqwest, TLS stack

Add default-features = false on the library dependency to drop the remote pull stack when you only need OCI layout and Docker overlay2 support:

[dependencies]
oci2rootfs = { version = "0.2", default-features = false }

Known limitations

  • Remote pull buffers every layer blob in memory before applying. For multi-gigabyte images this requires proportional heap; prefer spooling to an OCI layout on disk for large images (e.g. via skopeo copy docker://<ref> oci:./layout:latest, then OciLayoutSource::open).
  • Layer downloads are serial. Parallel fetches could reduce wall time for images with many small layers but would complicate progress reporting.
  • No device-node support. mknod-created entries in tar layers (char/ block/FIFO) are skipped silently; overlay2 .wh.<name> files cover deletion.
  • Block size and inode ratio are not configurable. arcbox-ext4 hard-codes 4 KiB blocks and computes inode counts internally.

Build

cargo build --release

Project Structure

crates/
├── oci2rootfs/          # Library
│   └── src/
│       ├── convert.rs   # High-level Converter API
│       ├── error.rs     # Error types
│       ├── ext4.rs      # ext4 image writer (arcbox-ext4)
│       ├── layer.rs     # Tar layer application with whiteout support
│       ├── oci.rs       # OCI Image Layout resolution
│       ├── ext4_options.rs # UUID/label passed at format time
│       ├── overlay2/    # Docker overlay2 resolution and apply
│       ├── path.rs      # Shared path sanitation + whiteout parsing
│       ├── pull.rs      # Remote registry pull (feature = "remote")
│       └── tar_source.rs # Shared tar-layer source plumbing
└── oci2rootfs-cli/      # CLI binary
    └── src/
        └── main.rs

License

Licensed under either of

at your option.

About

Convert OCI container images to ext4 rootfs filesystem images.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages