OCI Runtime, Image and Distribution Spec in Rust

Overview

oci-spec-rs

ci gh-pages crates.io codecov docs docs.rs dependencies license

Open Container Initiative (OCI) Specifications for Rust

This library provides a convenient way to interact with the specifications defined by the Open Container Initiative (OCI).

[dependencies]
oci-spec = "0.5.1"

Compiler support: requires rustc 1.54+

Image Format Spec Examples

  • Load image manifest from filesystem
use oci_spec::image::ImageManifest;

let image_manifest = ImageManifest::from_file("manifest.json").unwrap();
assert_eq!(image_manifest.layers().len(), 5);
  • Create new image manifest using builder
= [ ( 32654, "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0", ), ( 16724, "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b", ), ( 73109, "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736", ), ] .iter() .map(|l| { DescriptorBuilder::default() .media_type(MediaType::ImageLayerGzip) .size(l.0) .digest(l.1.to_owned()) .build() .expect("build layer") }) .collect(); let image_manifest = ImageManifestBuilder::default() .schema_version(SCHEMA_VERSION) .config(config) .layers(layers) .build() .expect("build image manifest"); image_manifest.to_file_pretty("my-manifest.json").unwrap(); ">
use oci_spec::image::{
    Descriptor, 
    DescriptorBuilder, 
    ImageManifest, 
    ImageManifestBuilder, 
    MediaType, 
    SCHEMA_VERSION
};

let config = DescriptorBuilder::default()
            .media_type(MediaType::ImageConfig)
            .size(7023)
            .digest("sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7")
            .build()
            .expect("build config descriptor");

let layers: Vec<Descriptor> = [
    (
        32654,
        "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0",
    ),
    (
        16724,
        "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b",
    ),
    (
        73109,
        "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736",
    ),
]
    .iter()
    .map(|l| {
    DescriptorBuilder::default()
        .media_type(MediaType::ImageLayerGzip)
        .size(l.0)
        .digest(l.1.to_owned())
        .build()
        .expect("build layer")
    })
    .collect();

let image_manifest = ImageManifestBuilder::default()
    .schema_version(SCHEMA_VERSION)
    .config(config)
    .layers(layers)
    .build()
    .expect("build image manifest");

image_manifest.to_file_pretty("my-manifest.json").unwrap();
  • Content of my-manifest.json
{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "digest": "sha256:b5b2b2c507a0944348e0303114d8d93aaaa081732b86451d9bce1f432a537bc7",
    "size": 7023
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:9834876dcfb05cb167a5c24953eba58c4ac89b1adf57f28f2f9d09af107ee8f0",
      "size": 32654
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:3c3a4604a545cdc127456d94e421cd355bca5b528f4a9c1905b15da2eb4a4c6b",
      "size": 16724
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:ec4b8955958665577945c89419d1af06b5f7636b4ac3da7f12184802ad867736",
      "size": 73109
    }
  ]
}

Distribution Spec Examples

  • Create a list of repositories
use oci_spec::distribution::RepositoryListBuilder;

let list = RepositoryListBuilder::default()
            .repositories(vec!["busybox".to_owned()])
            .build().unwrap();

Contributing

This project welcomes your PRs and issues. Should you wish to work on an issue, please claim it first by commenting on the issue that you want to work on it. This is to prevent duplicated efforts from contributers on the same issue.

Comments
  • Implement From<Spec> for SpecBuilder

    Implement From for SpecBuilder

    We now have at least two situations we need to modify the spec. We made the tradeoff to have Spec as immutable. The missing piece is actually transfer Spec into SpecBuilder and consume the original Spec. Unfortunately, the derive-builder lib we use don't generate the From methods automatically, which I think they should. Otherwise, immutable structure becomes really hard to use. Most of the functional programming languages implement this transparently in the runtime with copy on write, but here we have to do this ourselves. There is an PR (https://github.com/colin-kiegel/rust-derive-builder/pull/215) in the derive-builder lib, but looks like it's not merging anytime soon based on the conversation. So for the moment, let's implement this and any other struct in the spec that we need to modify.

    Fix https://github.com/containers/youki/issues/351.

    opened by yihuaf 14
  • Setup CI

    Setup CI

    I think we should set up a basic CI pipeline for the crate, which does:

    • [x] build
    • [x] unit test including code coverage
    • [x] clippy lint
    • [x] rustfmt
    • [x] build docs and push to gh-pages branch
    • [x] crates.io publishing
    opened by saschagrunert 11
  • Release 0.6.0

    Release 0.6.0

    Changes:

    • https://github.com/containers/oci-spec-rs/pull/87
    • https://github.com/containers/oci-spec-rs/pull/89
    • https://github.com/containers/oci-spec-rs/pull/90
    • https://github.com/containers/oci-spec-rs/pull/91
    opened by saschagrunert 6
  • A youki member to join containers member

    A youki member to join containers member

    Hi, @rhatdan, @saschagrunert

    I'd like to invite @Furisto to the containers member. WDYT? He is a active contributor of containers/oci-spec-rs, containers/youki and `containers/containrs . He is youki's number one contributor. Of course, he has interested in containers member. There is no particular change, but I do not think there is any room for denial in my opinion for him to become a member of this group.

    opened by utam0k 5
  • Add `MediaType::to_docker_v2s2` for Docker Image Manifest V2 Schema 2 equivalents

    Add `MediaType::to_docker_v2s2` for Docker Image Manifest V2 Schema 2 equivalents

    Closes https://github.com/containers/oci-spec-rs/issues/105.

    I chose to_v2s2 over the shorter to_docker_v2s2 after I noted that v2s2 is the shorthand used by podman. But happy to change to the more explicit to_docker_v2s2 is you feel that is appropriate.

    opened by nokome 5
  • `ImageConfiguration::default()` is a trap

    `ImageConfiguration::default()` is a trap

    https://github.com/containers/oci-spec-rs/blob/2440343d3433762c359c7a096648ca685f8ddd97/src/image/config.rs#L189

    We can't just assume the world is Linux/x86_64 by default. (And definitely not x86_64 :wink: )

    I have this code in ostree-rs-ext: https://github.com/ostreedev/ostree-rs-ext/blob/bb4423d5af109cf6268e91c77cc4c9ca850e579a/lib/src/container/ocidir.rs#L26

    WDYT about having this code in this crate? Alternatively, I think we should drop the default() method.

    Or in theory, these helper methods could go in some other containers/ related crate? I hesitate at the overhead for that. Maybe we introduce a oci_spec::util module?

    opened by cgwalters 5
  • Add mutable accessors for some important Vec/HashMap fields

    Add mutable accessors for some important Vec/HashMap fields

    Part of https://github.com/containers/oci-spec-rs/issues/86

    An obvious operation to support is generating a derived container image. Here we want to take some existing data such as the image manifest and configuration, and append to key fields such as the image layers, the config diffids and the history.

    Another common operation is adding/changing labels.

    Having to create a deep-copy of all this data is unfortunate. I am not very concerned about performance here, but it's also an ergonomic hit.

    Obviously giving raw &mut access to fields means that it goes "behind the back" of the derive builder, and if we ever started trying to use more advanced things like validation, that wouldn't work.

    Honestly, I am increasingly convinced the builder thing is just not worth it and it'd be better to have plain structs with pub fields. But for now, let's allow direct mutation.

    opened by cgwalters 5
  • even with setters, the builder pattern has large ergonomic hits

    even with setters, the builder pattern has large ergonomic hits

    I know the builder pattern has been debated many times here. This is quite similar to https://github.com/containers/oci-spec-rs/pull/74

    It was concluded to add setters. But, I still see two (related) issues:

    Fallible construction and required fields

    Using .build() is a fallible operation because some fields are required. This forces use of unwrap(). I think instead we should add methods that take all the required fields to start. This is much like how std::process::Command::new() requires a single string - the binary to run. Then converting the builder into a final struct can be an infallible operation.

    What tripped me up twice is that it's needed to manually set .schema_version() e.g. on ImageManifest. I caught this in unit tests (so not the end of the world or anything) but in Rust we can do this stuff at compile time with the type system.

    Mutation requires deep-copying

    An operation like appending a layer requires deep-copying 3 Vec instances - the layers Vec and the rootfs and history in the config struct.

    This isn't terrible, but WDYT about adding a method like this?

    diff --git a/src/image/manifest.rs b/src/image/manifest.rs
    index 7fbcef49..d4a09510 100644
    --- a/src/image/manifest.rs
    +++ b/src/image/manifest.rs
    @@ -164,6 +164,10 @@ impl ImageManifest {
         pub fn to_writer_pretty<W: Write>(&self, writer: &mut W) -> Result<()> {
             to_writer(&self, writer, true)
         }
    +
    +    pub fn push_layer(&mut self, blob: Descriptor) {
    +        self.layers.push(blob)
    +    }
     }
     
     #[cfg(test)]
    

    Or to summarize, short term I think I'm arguing to keep the builder pattern, but add helper methods.

    Longer term, it's not really clear to me that all this builder stuff is adding significant value over just having a crate with struct types where all the fields are pub, and helper methods on top of that.

    opened by cgwalters 4
  • Provide the setter method

    Provide the setter method

    Make the setter method available as a library. Some of them already provide setter methods. We will use this PR as a model to provide setter methods for other structures as well. https://github.com/containers/oci-spec-rs/pull/76

    good first issue 
    opened by utam0k 4
  • derive setters for spec and mount

    derive setters for spec and mount

    As discussed in #74, this will greatly reduce the need to copy spec/mount when modifying these structures. Leaving the rest as is at the moment. Hopefully, this is enough.

    opened by yihuaf 4
  • `ErrorInfo` detail field is object in registry responses

    `ErrorInfo` detail field is object in registry responses

    Although spec says that detail field in ErrorInfo is string with unstructured data it seems that all registries make detail field an object.

    For example, Dockerhub returns this for unknown manifest:

    {
        "errors": [
            {
                "code": "MANIFEST_UNKNOWN",
                "message": "manifest unknown",
                "detail": {
                    "Tag": "lates"
                }
            }
        ]
    }
    

    Quay:

    {
        "errors": [
            {
                "code": "MANIFEST_UNKNOWN",
                "detail": {},
                "message": "manifest unknown"
            }
        ]
    }
    

    Microsoft's MCR :

    {
        "errors": [
            {
                "code": "MANIFEST_UNKNOWN",
                "message": "manifest tagged by \"lates\" is not found",
                "detail": {
                    "Tag": "lates"
                }
            }
        ]
    }
    

    This results in failure to deserialize any of the above ErrorResponse structs.

    Is this the problem of registry implementers, this library or the spec itself?

    opened by petkovicdanilo 4
  • OCI Artifact manifest specification support

    OCI Artifact manifest specification support

    Motivation

    OCI Artifact manifest specifiaction will be introduced in OCI image spec v1.1.0 (currently rc2) with referrer API in OCI distribution spec in order to store non-image artifacts, e.g. helm chart or SBOM (Software Bill Of Materials) by sigstore/cosign into OCI registry.

    Rationale and alternatives

    There are two artifact manifest specifications:

    As far as I studied (https://github.com/termoshtt/ocipkg/issues/78), ORAS project has started specifying the artifact manifest, and created own manifest "ORAS Artifact manifest" as pre-draft for submitting to OCI. It has been submitted to OCI as "OCI Artifact manifest" with some fixes, and merged to OCI image spec at 1.1.0-rc1.

    Unresolved questions

    IANA media type

    Because OCI Artifact stores several types of artifact, it stores the media type of its artifact, e.g. application/gzip when storing *.gz file. About this media type slot, OCI Artifact manifest specification says:

    https://github.com/opencontainers/image-spec/blob/main/artifact.md

    This property SHOULD be used and contain the mediaType of the referenced artifact. If defined, the value MUST comply with RFC 6838, including the naming requirements in its section 4.2, and MAY be registered with IANA.

    The media types registered by IANA (Internet Assigned Numbers Authority) is listed in https://www.iana.org/assignments/media-types/media-types.xhtml . I guess it will be updated frequently (last update is 2022-11-10). Since the media type always can be represented by a String and be managed by oci_spec::MediaType::Other, however, I hope this also be statically typed. I experimentally created iana-media-types crate which translate the media type list in IANA into Rust code automatically. I am planning to re-generate this crate using GitHub Actions as upstream IANA definition upgrades.

    So my question is

    • Using iana-media-types crate is acceptable in terms of managing oci_spec crate?

    I willing to integrate iana-media-types crate into this repository, or transfer current repository.

    opened by termoshtt 0
Releases(v0.5.8)
  • v0.5.8(Sep 6, 2022)

    What's Changed

    • Release 0.5.7 by @utam0k in https://github.com/containers/oci-spec-rs/pull/108
    • Implement ToString for ImageIndex, ImageManifest, and ImageConfiguration by @termoshtt in https://github.com/containers/oci-spec-rs/pull/109
    • runtime: Add a domainname field support by @utam0k in https://github.com/containers/oci-spec-rs/pull/111

    New Contributors

    • @termoshtt made their first contribution in https://github.com/containers/oci-spec-rs/pull/109

    Full Changelog: https://github.com/containers/oci-spec-rs/compare/v0.5.7...v0.5.8

    Source code(tar.gz)
    Source code(zip)
  • v0.5.7(Jul 6, 2022)

    What's Changed

    • add cpu.idle support by @wineway in https://github.com/containers/oci-spec-rs/pull/103
    • Release 0.5.6 by @utam0k in https://github.com/containers/oci-spec-rs/pull/104
    • Add MediaType::to_docker_v2s2 for Docker Image Manifest V2 Schema 2 equivalents by @nokome in https://github.com/containers/oci-spec-rs/pull/106
    • Support for IDMapping field. by @utam0k in https://github.com/containers/oci-spec-rs/pull/107

    New Contributors

    • @wineway made their first contribution in https://github.com/containers/oci-spec-rs/pull/103
    • @nokome made their first contribution in https://github.com/containers/oci-spec-rs/pull/106

    Full Changelog: https://github.com/containers/oci-spec-rs/compare/v0.5.6...v0.5.7

    Source code(tar.gz)
    Source code(zip)
  • v0.5.6(May 9, 2022)

    What's Changed

    • Add available LinuxSeccompFilterFlags by @saschagrunert in https://github.com/containers/oci-spec-rs/pull/96
    • Release 0.5.5 by @saschagrunert in https://github.com/containers/oci-spec-rs/pull/97
    • Update derive_builder requirement from 0.10.2 to 0.11.0 by @dependabot in https://github.com/containers/oci-spec-rs/pull/99
    • Add docs about how to cut a release by @saschagrunert in https://github.com/containers/oci-spec-rs/pull/98
    • Add missing CopyGetters by @cgwalters in https://github.com/containers/oci-spec-rs/pull/100
    • Add CFS bandwidth burst by @Furisto in https://github.com/containers/oci-spec-rs/pull/101

    New Contributors

    • @dependabot made their first contribution in https://github.com/containers/oci-spec-rs/pull/99

    Full Changelog: https://github.com/containers/oci-spec-rs/compare/v0.5.5...v0.5.6

    Source code(tar.gz)
    Source code(zip)
  • v0.5.5(Feb 28, 2022)

    What's Changed

    • Add available LinuxSeccompFilterFlags by @saschagrunert in https://github.com/containers/oci-spec-rs/pull/96

    Full Changelog: https://github.com/containers/oci-spec-rs/compare/v0.5.4...v0.5.5

    Source code(tar.gz)
    Source code(zip)
  • v0.5.4(Jan 25, 2022)

    What's Changed

    • Add mutable accessors for some important Vec/HashMap fields by @cgwalters in https://github.com/containers/oci-spec-rs/pull/87
    • Use buffered I/O for JSON by default by @cgwalters in https://github.com/containers/oci-spec-rs/pull/89
    • impl Default for Os and Arch, use in ImageConfiguration::default() by @cgwalters in https://github.com/containers/oci-spec-rs/pull/90
    • image: Fix powerpc, add a test case for arch mapping by @cgwalters in https://github.com/containers/oci-spec-rs/pull/91

    Full Changelog: https://github.com/containers/oci-spec-rs/compare/v0.5.3...v0.5.4

    Source code(tar.gz)
    Source code(zip)
  • v0.5.3(Jan 6, 2022)

    Bump to 0.5.3

    What's Changed

    • Release 0.5.2 by @saschagrunert in https://github.com/containers/oci-spec-rs/pull/75
    • derive setters for spec and mount by @yihuaf in https://github.com/containers/oci-spec-rs/pull/76
    • Add tests to load an actual spec by @yihuaf in https://github.com/containers/oci-spec-rs/pull/78
    • add missing field for seccomp by @yihuaf in https://github.com/containers/oci-spec-rs/pull/79
    • Add missing setters for structs by @TristanCacqueray in https://github.com/containers/oci-spec-rs/pull/80
    • change default_error_ret to use get_copy by @yihuaf in https://github.com/containers/oci-spec-rs/pull/83
    • fix: add missing Setters trait to LinuxPids by @knight42 in https://github.com/containers/oci-spec-rs/pull/84
    • Bump to 0.5.3 by @utam0k in https://github.com/containers/oci-spec-rs/pull/85

    New Contributors

    • @TristanCacqueray made their first contribution in https://github.com/containers/oci-spec-rs/pull/80
    • @knight42 made their first contribution in https://github.com/containers/oci-spec-rs/pull/84

    Full Changelog: https://github.com/containers/oci-spec-rs/compare/v0.5.2...v0.5.3

    Source code(tar.gz)
    Source code(zip)
Owner
Containers
Open Repository for Container Tools
Containers
A fast and minimalistic image viewer forked from the now discontinued emulsion.

Alloy Image viewer based on (now-discontinued) Emulsion. Alloy targets Windows, Mac, and Linux (with more targets to come!). A note for Linux users: W

Ardaku Systems 9 Dec 1, 2022
A simple and fast download accelerator, written in Rust

zou A simple and fast download accelerator, written in Rust Zou is a Snatch fork by @k0pernicus. Snatch is a fast and interruptable download accelerat

Antonin Carette 173 Dec 4, 2022
Untrusted IPC with maximum performance and minimum latency. On Rust, on Linux.

Untrusted IPC with maximum performance and minimum latency. On Rust, on Linux. When is this Rust crate useful? Performance or latency is crucial, and

null 72 Jan 3, 2023
A system handler to get information and interact with processes written in Rust

A system handler to get information and interact with processes written in Rust

Guillaume Gomez 1.1k Jan 3, 2023
desktop automation, screen capture, input listen/simulation, asar compress, color picker for nodejs and electron based on rust

desktop automation, screen capture, input listen/simulation, asar compress, color picker for nodejs and electron based on rust. 基于 Rust / WASM 提供截图、取色、键鼠事件监听模拟、压缩解压、图像处理、获取已安装应用等跨平台功能的现代异步 Nodejs 模块,占用空间小, 安装便捷, 使用简单, 高性能, 资源占用极小, 可取代 iohook 和 robotjs

null 48 Dec 15, 2022
GTK application for browsing and installing fonts from Google's font archive

Font Finder This project is a from-scratch implementation of TypeCatcher in Rust. It is a GTK3 application for browsing through and installing fonts f

Michael Murphy 252 Dec 26, 2022
Linux Kernel Manager and Activity Monitor 🐧💻

Linux Kernel Manager and Activity Monitor ?? ?? The kernel is the part of the operating system that facilitates interactions between hardware and soft

Orhun Parmaksız 1.7k Jan 5, 2023
Utility that takes logs from anywhere and sends them to Telegram.

logram Utility that takes logs from anywhere and sends them to Telegram. Supports log collection from files, journald and docker containers. More abou

Max Eliseev 85 Dec 22, 2022
A safe and ergonomic alternative to rm

rip (Rm ImProved) rip is a command-line deletion tool focused on safety, ergonomics, and performance. It favors a simple interface, and does not imple

Kevin Liu 781 Jan 7, 2023
A simple, fast and user-friendly alternative to 'find'

fd [中文] [한국어] fd is a program to find entries in your filesytem. It is a simple, fast and user-friendly alternative to find. While it does not aim to

David Peter 25.8k Dec 30, 2022
CLI utility to move (or rename) your files to a new location and redirect all of its symbolic links, to the new path

Move Links CLI utility to move (or rename) your files to a new location and redirect all of its symbolic links, to the new path (or name). Usage execu

Ben Mefteh 18 May 22, 2022
A tool to simplify reprovisioning a fresh OS. Installs packages and manages dotfiles.

[[TOC]] Comtrya This is better, yes? Warning This tool is ridiculously early in its development. I'm building out features as I migrate my dotfiles ov

David McKay 2 Dec 29, 2022
A tool to simplify reprovisioning a fresh OS. Installs packages and manages dotfiles.

Comtrya This is better, yes? Warning This tool is ridiculously early in its development. I'm building out features as I migrate my dotfiles over. Thos

Comtrya 272 Jan 7, 2023
Parallel finance a decentralized lending protocol built on top of the Polkadot ecosystem. Our unique approach will allow users to earn "double interests" from staking and lending their tokens simultaneously.

Parallel Finance A new Cumulus-based Substrate node, ready for hacking ?? Getting Started Follow these steps to get started with the Cumulus Template

parallel-finance 100 Dec 17, 2022
idf-env tool helps set up and manage ESP-IDF installations

idf-env Tool for maintaining ESP-IDF environment. Quick start Install serial drivers for ESP boards on Windows. Execute following command in PowerShel

Espressif Systems 19 Dec 4, 2022
It is a backup tool that creates backups and stores them on an object storage

Hold My Backup It is a backup tool that creates backups and stores them on an object storage. By default it uses minio but you can use AWS: S3 as well

Taylan Dogan 13 Feb 17, 2022
`haproxy_autconfd` is a daemon that automatically assembles a HAProxy config and restarts HAProxy if the config changes

haproxy_autconfd Welcome to haproxy_autconfd ?? haproxy_autconfd is a daemon that automatically assembles a HAProxy config and restarts HAProxy if the

null 0 Nov 9, 2021
Reproducible builds, dev envs and deployments.

?? Toros An implementation of Nix in Rust. Syntax support: With NixEL Interpreter support: Int Binding (aliasing) Let-in (flat bindings without interp

Kevin Amado 35 Dec 23, 2022
minimalistic command launcher in rust

rrun Note: Apart from the occasional fix, this project is not actively developed anymore. rrun works fine and should run/compile for the time being on

null 105 Nov 18, 2022