The sections below cover core features of containerd.
containerd offers a full client package to help you integrate containerd into your platform.
import ( "context" containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/containerd/v2/pkg/namespaces" ) func main() { client, err := containerd.New("/run/containerd/containerd.sock") defer client.Close() }
Namespaces allow multiple consumers to use the same containerd without conflicting with each other. It has the benefit of sharing content while maintaining separation with containers and images.
To set a namespace for requests to the API:
context = context.Background() // create a context for docker docker = namespaces.WithNamespace(context, "docker") containerd, err := client.NewContainer(docker, "id")
To set a default namespace on the client:
client, err := containerd.New(address, containerd.WithDefaultNamespace("docker"))
// pull an image image, err := client.Pull(context, "docker.io/library/redis:latest") // push an image err := client.Push(context, "docker.io/library/redis:latest", image.Target())
In containerd, a container is a metadata object. Resources such as an OCI runtime specification, image, root filesystem, and other metadata can be attached to a container.
redis, err := client.NewContainer(context, "redis-master")
defer redis.Delete(context)
containerd fully supports the OCI runtime specification for running containers. We have built-in functions to help you generate runtime specifications based on images as well as custom parameters.
You can specify options when creating a container about how to modify the specification.
redis, err := client.NewContainer(context, "redis-master", containerd.WithNewSpec(oci.WithImageConfig(image)))
containerd allows you to use overlay or snapshot filesystems with your containers. It comes with built-in support for overlayfs and btrfs.
// pull an image and unpack it into the configured snapshotter image, err := client.Pull(context, "docker.io/library/redis:latest", containerd.WithPullUnpack) // allocate a new RW root filesystem for a container based on the image redis, err := client.NewContainer(context, "redis-master", containerd.WithNewSnapshot("redis-rootfs", image), containerd.WithNewSpec(oci.WithImageConfig(image)), ) // use a readonly filesystem with multiple containers for i := 0; i < 10; i++ { id := fmt.Sprintf("id-%s", i) container, err := client.NewContainer(ctx, id, containerd.WithNewSnapshotView(id, image), containerd.WithNewSpec(oci.WithImageConfig(image)), ) }
Taking a container object and turning it into a runnable process on a system is done by creating a new Task from the container. A task represents the runnable object within containerd.
// create a new task task, err := redis.NewTask(context, cio.NewCreator(cio.WithStdio)) defer task.Delete(context) // the task is now running and has a pid that can be used to setup networking // or other runtime settings outside of containerd pid := task.Pid() // start the redis-server process inside the container err := task.Start(context) // wait for the task to exit and get the exit status status, err := task.Wait(context)
If you have criu installed on your machine you can checkpoint and restore containers and their tasks. This allows you to clone and/or live migrate containers to other machines.
// checkpoint the task then push it to a registry checkpoint, err := task.Checkpoint(context) err := client.Push(context, "myregistry/checkpoints/redis:master", checkpoint) // on a new machine pull the checkpoint and restore the redis container checkpoint, err := client.Pull(context, "myregistry/checkpoints/redis:master") redis, err = client.NewContainer(context, "redis-master", containerd.WithNewSnapshot("redis-rootfs", checkpoint)) defer container.Delete(context) task, err = redis.NewTask(context, cio.NewCreator(cio.WithStdio), containerd.WithTaskCheckpoint(checkpoint)) defer task.Delete(context) err := task.Start(context)
In addition to the built-in Snapshot plugins in containerd, additional external plugins can be configured using GRPC. An external plugin is made available using the configured name and appears as a plugin alongside the built-in ones.
To add an external snapshot plugin, add the plugin to containerd‘s config file (by default at /etc/containerd/config.toml). The string following proxy_plugin. will be used as the name of the snapshotter and the address should refer to a socket with a GRPC listener serving containerd’s Snapshot GRPC API. Remember to restart containerd for any configuration changes to take effect.
[proxy_plugins]
[proxy_plugins.customsnapshot]
type = "snapshot"
address = "/var/run/mysnapshotter.sock"
See PLUGINS.md for how to create plugins