sal/examples/instructions_grpc.md
2025-05-08 09:05:44 +03:00

2.8 KiB

Step-by-step: Connect Rust to containerd via gRPC

CREATE A rhai script executing the following instructions below use all rhai script features we have + give priority to what functions we have defined in /src/docs/docs/sal in this repo


1. 🧱 Install Dependencies

Add this to your Cargo.toml:

[dependencies]
tonic = "0.11"
prost = "0.12"
tokio = { version = "1", features = ["full"] }

[build-dependencies]
tonic-build = "0.11"

2. 📁 Clone containerd's gRPC proto files

git clone https://github.com/containerd/containerd.git
cd containerd

Containerd's API protos are in:

api/services/         # gRPC service definitions
api/types/            # message types

3. 📦 Set up build.rs to compile protos

In your Rust project root, create a build.rs file:

fn main() {
    tonic_build::configure()
        .build_server(false)
        .compile(
            &[
                "containerd/api/services/images/v1/images.proto", 
                "containerd/api/services/containers/v1/containers.proto",
                // Add more proto files as needed
            ],
            &[
                "containerd/api", 
                "containerd/api/types"
            ],
        )
        .unwrap();
}

Make sure to place the containerd directory somewhere your build can see — for example, symlink it or move it into your project as proto/containerd.


4. 🧪 Example: Connect to containerd's image service

After build.rs compiles the protos, your code can access them like this:

use tonic::transport::Channel;
use containerd::services::images::v1::{
    images_client::ImagesClient,
    GetImageRequest,
};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Connect to containerd's gRPC socket (default path)
    let channel = Channel::from_static("http://[::]:50051") // placeholder
        .connect()
        .await?;

    let mut client = ImagesClient::new(channel);

    let response = client.get(GetImageRequest {
        name: "docker.io/library/ubuntu:latest".to_string(),
    }).await?;

    println!("Image: {:?}", response.into_inner());
    Ok(())
}

🔧 Note: containerd uses a Unix socket, so replace the channel connection with:

use tonic::transport::{Endpoint, Uri};
use tower::service_fn;
use hyper_unix_connector::UnixConnector;

let uds = tokio::net::UnixStream::connect("/run/containerd/containerd.sock").await?;
let channel = Endpoint::try_from("http://[::]:50051")?
    .connect_with_connector(service_fn(move |_| async move {
        Ok::<_, std::io::Error>(uds)
    }))
    .await?;

(We can wrap that part into a helper if you want.)


5. 🔁 Rebuild the project

Each time you add or change a .proto, rebuild to regenerate code:

cargo clean && cargo build