Project: containerd (Runtime / Container Runtime)
File: 2017-05-26.md

Overall, containerd is very close to being feature complete. The final features like namespace support are being worked on. We have a couple consumers that are working on containerd implementations such as a CRI for kube, Docker execution, Swarmkit, and Linuxkit consuming containerd. We hope to be feature complete by the end of this month. That will leave the month of June to focus on quality of the API and making sure that client needs are met. We have some work on error codes and reviewing our protos to make sure we have an API that we can support for the life of containerd 1.x. We added a `push` and `push-object` command to the dist tool. The `push` command can be used to push a manifest and all the related objects to a registry. The `push-object` can push individual blobs from the content store to a registry. The push command does not require first tagging an image, just specify the remote name of the image as well as the local name. If the remote and local name are the same, only one argument is needed. The remote name may exclude the object identifier (Docker-style tag or digest), in which case the manifest may be repulled using the manifest digest as the object identifier. Push only handles pushing images which already exist, it will not create an image manifest if one does not exist. We will add a separate command for creating new images in the future. Example pushing image to a local registry. ``` $ dist image list REF TYPE DIGEST SIZE docker.io/library/ubuntu:latest application/vnd.docker.distribution.manifest.v2+json sha256:382452f82a8bbd34443b2c727650af46aced0f94a44463c62a9848133ecb1aa8 44.7 MiB $ dist push localhost:5000/ubuntu docker.io/library/ubuntu:latest manifest-sha256:382452f82a8bbd34443b2c727650af46aced0f94a44463c62a9848133ecb1aa8: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:cf9722e506aada1109f5c00a9ba542a81c9e109606c01c81f5991b1f93de7b66: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:b6f892c0043b37bd1834a4a1b7d68fe6421c6acbc7e7e63a4527e1d379f92c1b: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:55010f332b047687e081a9639fac04918552c144bc2da4edb3422ce8efcc1fb1: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:3deef3fcbd3072b45771bd0d192d4e5ff2b7310b99ea92bce062e01097953505: done |++++++++++++++++++++++++++++++++++++++| config-sha256:ebcd9d4fca80e9e8afc525d8a38e7c56825dfb4a220ed77156f9fb13b14d4ab7: done |++++++++++++++++++++++++++++++++++++++| layer-sha256:2955fb827c947b782af190a759805d229cfebc75978dba2d01b4a59e6a333845: done |++++++++++++++++++++++++++++++++++++++| elapsed: 6.5 s total: 44.7 M (6.9 MiB/s) ``` We started work on the initial containerd client. Since we will have multiple consumers using the API, we want to reduce duplicated code for users of containerd. Another goal for our client is to give users a stable client API that does not feel like they are working with a remote daemon. Containers are already complex for most people but this does not need to be the case. Building a platform on top of containerd should be

We want to handle the low level system aspects so that you can build a platform for your users and not worry about the underlying system, unless you want to. ```go client, err := containerd.New(address, containerd.WithNamespace("docker")) if err != nil { return err } defer client.Close() ``` ```go // pull && unpack the image to your snapshot ( overlayfs default ) of choice image, err := client.Pull(ctx, "docker.io/library/redis:alpine", containerd.WithPullUnpack) if err != nil { return err } ``` ```go // generate the spec based on the image that we pulled spec, err := containerd.GenerateSpec(containerd.WithImageConfig(ctx, image)) if err != nil { return err } ``` ```go // create the container with a persistent ReadWrite layer based on the image and spec container, err := client.NewContainer(ctx, "redis", spec, containerd.WithNewRootFS("redis-rootfs", image)) if err != nil { return err } defer container.Delete(ctx) ``` ```go // use the current process's stdio task, err := container.NewTask(ctx, containerd.Stdio) if err != nil { return err } defer task.Delete(ctx) pid := task.Pid() // start the redis process if err := task.Start(ctx); err != nil { return err } task.Kill(ctx, syscall.SIGTERM) status, err := task.Wait(ctx) os.Exit(status) ``` This is a very simple but common usecase for containerd. Pull an image and run a container based on that image. The client lets you write code, use `defer` statements and any other logic you want without having to do complex filesystem operations, deal with tar files or setting up root filesystems. The API is split up and allows you to look into the lifecycle of an executing container without the need to register hooks and provide callbacks. Over the next few weeks we will be expanding the client to support the full containerd feature set. With the initial client merged into the code base we are also starting work on integration tests. We have full integration tests running on travis ci. You don't have to mess with any other test frameworks to write tests for containerd, just the standard Go testing package. We also designed the client to allow mocking of calls so that our tests can be mocked out or users of our client to easily mock their own code for testing. You can view the PR . We still need to finish Events. This is one of the last major features that we need before we consider containerd feature complete. The namespace work is in progress with the initial service spec'd. Within the next few weeks we should have namespaces done, a complete client, and hopefully a stable events service.