func (cli *Client) NewContainer(ctx context.Context, id string) error {
	ctx = namespaces.WithNamespace(ctx, namespaces.Default)
	spec, err := oci.GenerateSpec(ctx, nil, &containers.Container{ID: id})
	if err != nil {
		return fmt.Errorf("fail to generate spec for container %s: %v", id, err)
	}
	options := []containerd.NewContainerOpts{
		containerd.WithSpec(spec),
		containerd.WithRuntime(fmt.Sprintf("io.containerd.runtime.v1.%s", runtime.GOOS), &runctypes.RuncOptions{
			Runtime: "docker-runc",
		}),
	}
	if _, err := cli.client.NewContainer(ctx, id, options...); err != nil {
		return fmt.Errorf("failed to create new containerd container %s: %v", id, err)
	}
	return nil
}
NewContainer just create a very simple container for migration
just load container id to boltdb
package ctrd
import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"path"
	"runtime"
	"strings"
	"syscall"
	"github.com/pouchcontainer/d2p-migrator/ctrd/image"
	"github.com/pouchcontainer/d2p-migrator/utils"
	pouchtypes "github.com/alibaba/pouch/apis/types"
	"github.com/alibaba/pouch/pkg/reference"
	"github.com/containerd/containerd"
	"github.com/containerd/containerd/containers"
	"github.com/containerd/containerd/leases"
	"github.com/containerd/containerd/linux/runctypes"
	"github.com/containerd/containerd/mount"
	"github.com/containerd/containerd/namespaces"
	"github.com/containerd/containerd/oci"
	"github.com/containerd/containerd/platforms"
	"github.com/containerd/containerd/snapshots"
	"github.com/opencontainers/image-spec/identity"
)
const (
	defaultSnapshotterName = "overlayfs"
	socketAddr             = "/tmp/containerd-migrator.sock"
	defaultRegistry        = "registry.hub.docker.com"
	defaultNamespace       = "library"
)
func StartContainerd(homeDir string, debug bool) (int, error) {
	if _, err := os.Stat(socketAddr); err == nil {
		os.RemoveAll(socketAddr)
	}
	containerdPath, err := exec.LookPath("d2p-containerd")
	if err != nil {
		return -1, fmt.Errorf("failed to find containerd binary %v", err)
	}
	cmd, err := newContainerdCmd(homeDir, containerdPath, debug)
	if err != nil {
		return -1, err
	}
	go cmd.Wait()
	return cmd.Process.Pid, nil
}
func newContainerdCmd(homeDir, containerdPath string, debug bool) (*exec.Cmd, error) {
	args := []string{
		"-a", socketAddr,
		"--root", path.Join(homeDir, "containerd/root"),
		"--state", path.Join(homeDir, "containerd/state"),
		"-l", utils.IfThenElse(debug, "debug", "info").(string),
	}
	cmd := exec.Command(containerdPath, args...)
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	cmd.SysProcAttr = &syscall.SysProcAttr{Setsid: true, Pdeathsig: syscall.SIGKILL}
	cmd.Env = nil
	for _, e := range os.Environ() {
		if !strings.HasPrefix(e, "NOTIFY_SOCKET") {
			cmd.Env = append(cmd.Env, e)
		}
	}
	if err := cmd.Start(); err != nil {
		return nil, err
	}
	return cmd, nil
}
func Cleanup(pid int) error {
	if pid != -1 {
		syscall.Kill(pid, syscall.SIGKILL)
	}
	os.Remove(socketAddr)
	return nil
}
type Client struct {
	client *containerd.Client
	lease  *containerd.Lease
}
func NewCtrdClient() (*Client, error) {
	client, err := containerd.New(socketAddr, containerd.WithDefaultNamespace("default"))
	if err != nil {
		return nil, err
	}
	var lease containerd.Lease
	leases, err := client.ListLeases(context.TODO())
	if err != nil {
		return nil, err
	}
	if len(leases) != 0 {
		lease = leases[0]
	} else {
		if lease, err = client.CreateLease(context.TODO()); err != nil {
			return nil, err
		}
	}
	return &Client{
		client: client,
		lease:  &lease,
	}, nil
}
func (cli *Client) CreateSnapshot(ctx context.Context, id, ref string) error {
	ctx = leases.WithLease(ctx, cli.lease.ID())
	image, err := cli.client.ImageService().Get(ctx, ref)
	if err != nil {
		return err
	}
	diffIDs, err := image.RootFS(ctx, cli.client.ContentStore(), platforms.Default())
	if err != nil {
		return err
	}
	parent := identity.ChainID(diffIDs).String()
	_, err = cli.client.SnapshotService(defaultSnapshotterName).Prepare(ctx, id, parent)
	return err
}
func (cli *Client) GetSnapshot(ctx context.Context, id string) (snapshots.Info, error) {
	service := cli.client.SnapshotService(defaultSnapshotterName)
	defer service.Close()
	return service.Stat(ctx, id)
}
func (cli *Client) GetMounts(ctx context.Context, id string) ([]mount.Mount, error) {
	service := cli.client.SnapshotService(defaultSnapshotterName)
	defer service.Close()
	return service.Mounts(ctx, id)
}
func (cli *Client) RemoveSnapshot(ctx context.Context, id string) error {
	service := cli.client.SnapshotService(defaultSnapshotterName)
	defer service.Close()
	return service.Remove(ctx, id)
}