164 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			164 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
 | 
						|
# Features
 | 
						|
 | 
						|
The sections below cover core features of `containerd`.
 | 
						|
 | 
						|
## Client
 | 
						|
 | 
						|
containerd offers a full client package to help you integrate containerd into your platform.
 | 
						|
 | 
						|
```go
 | 
						|
 | 
						|
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
 | 
						|
 | 
						|
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:
 | 
						|
 | 
						|
```go
 | 
						|
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:
 | 
						|
 | 
						|
```go
 | 
						|
client, err := containerd.New(address, containerd.WithDefaultNamespace("docker"))
 | 
						|
```
 | 
						|
 | 
						|
## Distribution
 | 
						|
 | 
						|
```go
 | 
						|
// 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())
 | 
						|
```
 | 
						|
 | 
						|
## Containers
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
```go
 | 
						|
redis, err := client.NewContainer(context, "redis-master")
 | 
						|
defer redis.Delete(context)
 | 
						|
```
 | 
						|
 | 
						|
## OCI Runtime Specification
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
```go
 | 
						|
redis, err := client.NewContainer(context, "redis-master", containerd.WithNewSpec(oci.WithImageConfig(image)))
 | 
						|
```
 | 
						|
 | 
						|
## Root Filesystems
 | 
						|
 | 
						|
containerd allows you to use overlay or snapshot filesystems with your containers.  It comes with built-in support for overlayfs and btrfs.
 | 
						|
 | 
						|
```go
 | 
						|
// 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)),
 | 
						|
	)
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
## Tasks
 | 
						|
 | 
						|
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.
 | 
						|
 | 
						|
```go
 | 
						|
// 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)
 | 
						|
```
 | 
						|
 | 
						|
## Checkpoint and Restore
 | 
						|
 | 
						|
If you have [criu](https://criu.org/Main_Page) 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.
 | 
						|
 | 
						|
```go
 | 
						|
// 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)
 | 
						|
```
 | 
						|
 | 
						|
## Snapshot Plugins
 | 
						|
 | 
						|
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](PLUGINS.md) for how to create plugins
 |