Snapshots crate implements containerd's proxy plugin for snapshotting. It aims hide the underlying complexity of GRPC
interfaces, streaming, and request/response conversions and provide one Snapshots
trait to implement.
A proxy plugin is configured using containerd's config file and will be loaded alongside the internal plugins when containerd is started. These plugins are connected to containerd using a local socket serving one of containerd's GRPC API services. Each plugin is configured with a type and name just as internal plugins are.
Add the following to containerd's configuration file:
[proxy_plugins]
[proxy_plugins.custom]
type = "snapshot"
address = "/tmp/snap2.sock"
Start daemons and try pulling an image with custom
snapshotter:
# Start containerd daemon
$ containerd --config /path/config.toml
# Run remote snapshotter instance
$ cargo run --example snapshotter /tmp/snap2.sock
# Now specify the snapshotter when pulling an image
$ ctr i pull --snapshotter custom docker.io/library/hello-world:latest
Snapshotters are required to implement Snapshotter
trait (which is very similar to containerd's
Snapshotter interface).
use std::collections::HashMap;
use containerd_snapshots as snapshots;
use containerd_snapshots::{api, Info, Usage};
use log::info;
#[derive(Default)]
struct Example;
#[snapshots::tonic::async_trait]
impl snapshots::Snapshotter for Example {
type Error = snapshots::tonic::Status;
async fn stat(&self, key: String) -> Result<Info, Self::Error> {
info!("Stat: {}", key);
Ok(Info::default())
}
// ...
async fn commit(
&self,
name: String,
key: String,
labels: HashMap<String, String>,
) -> Result<(), Self::Error> {
info!("Commit: name={}, key={}, labels={:?}", name, key, labels);
Ok(())
}
}
The library provides snapshots::server
for convenience to wrap the implementation into a GRPC server, so it can
be used with tonic
like this:
use snapshots::tonic::transport::Server;
Server::builder()
.add_service(snapshots::server(example))
.serve_with_incoming(incoming)
.await
.expect("Serve failed");