summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrian Goff <cpuguy83@gmail.com>2020-07-07 13:33:46 -0700
committerBrian Goff <cpuguy83@gmail.com>2020-07-13 14:18:02 -0700
commitf63f73a4a8f531813d6b46a2347cab4bfd210df7 (patch)
tree7723cae5a0560466972f3c45d3a10d109a2b18e6
parent6fd94aa933f774dc6f582a96f800b1e875628be3 (diff)
downloaddocker-f63f73a4a8f531813d6b46a2347cab4bfd210df7.tar.gz
Configure shims from runtime config
In dockerd we already have a concept of a "runtime", which specifies the OCI runtime to use (e.g. runc). This PR extends that config to add containerd shim configuration. This option is only exposed within the daemon itself (cannot be configured in daemon.json). This is due to issues in supporting unknown shims which will require more design work. What this change allows us to do is keep all the runtime config in one place. So the default "runc" runtime will just have it's already existing shim config codified within the runtime config alone. I've also added 2 more "stock" runtimes which are basically runc+shimv1 and runc+shimv2. These new runtime configurations are: - io.containerd.runtime.v1.linux - runc + v1 shim using the V1 shim API - io.containerd.runc.v2 - runc + shim v2 These names coincide with the actual names of the containerd shims. This allows the user to essentially control what shim is going to be used by either specifying these as a `--runtime` on container create or by setting `--default-runtime` on the daemon. For custom/user-specified runtimes, the default shim config (currently shim v1) is used. Signed-off-by: Brian Goff <cpuguy83@gmail.com>
-rw-r--r--api/types/types.go10
-rw-r--r--daemon/config/config.go29
-rw-r--r--daemon/daemon.go8
-rw-r--r--daemon/daemon_unix.go74
-rw-r--r--daemon/info.go5
-rw-r--r--daemon/runtime_unix.go134
-rw-r--r--daemon/start.go6
-rw-r--r--daemon/start_unix.go65
-rw-r--r--daemon/start_windows.go12
-rw-r--r--daemon/util_test.go2
-rw-r--r--libcontainerd/libcontainerd_linux.go4
-rw-r--r--libcontainerd/libcontainerd_windows.go4
-rw-r--r--libcontainerd/local/local_windows.go2
-rw-r--r--libcontainerd/remote/client.go36
-rw-r--r--libcontainerd/remote/client_linux.go5
-rw-r--r--libcontainerd/types/types.go2
-rw-r--r--plugin/executor/containerd/containerd.go16
17 files changed, 237 insertions, 177 deletions
diff --git a/api/types/types.go b/api/types/types.go
index a6ed75de3e..dd5f2aff8a 100644
--- a/api/types/types.go
+++ b/api/types/types.go
@@ -511,6 +511,16 @@ type Checkpoint struct {
type Runtime struct {
Path string `json:"path"`
Args []string `json:"runtimeArgs,omitempty"`
+
+ // This is exposed here only for internal use
+ // It is not currently supported to specify custom shim configs
+ Shim *ShimConfig `json:"-"`
+}
+
+// ShimConfig is used by runtime to configure containerd shims
+type ShimConfig struct {
+ Binary string
+ Opts interface{}
}
// DiskUsage contains response of Engine API:
diff --git a/daemon/config/config.go b/daemon/config/config.go
index 26614d37c4..bcecd36356 100644
--- a/daemon/config/config.go
+++ b/daemon/config/config.go
@@ -36,9 +36,6 @@ const (
// maximum number of attempts that
// may take place at a time for each pull when the connection is lost.
DefaultDownloadAttempts = 5
- // StockRuntimeName is the reserved name/alias used to represent the
- // OCI runtime being shipped with the docker daemon package.
- StockRuntimeName = "runc"
// DefaultShmSize is the default value for container's shm size
DefaultShmSize = int64(67108864)
// DefaultNetworkMtu is the default value for network MTU
@@ -47,8 +44,24 @@ const (
DisableNetworkBridge = "none"
// DefaultInitBinary is the name of the default init binary
DefaultInitBinary = "docker-init"
+
+ // StockRuntimeName is the reserved name/alias used to represent the
+ // OCI runtime being shipped with the docker daemon package.
+ StockRuntimeName = "runc"
+ // LinuxV1RuntimeName is the runtime used to specify the containerd v1 shim with the runc binary
+ // Note this is different than io.containerd.runc.v1 which would be the v1 shim using the v2 shim API.
+ // This is specifically for the v1 shim using the v1 shim API.
+ LinuxV1RuntimeName = "io.containerd.runtime.v1.linux"
+ // LinuxV2RuntimeName is the runtime used to specify the containerd v2 runc shim
+ LinuxV2RuntimeName = "io.containerd.runc.v2"
)
+var builtinRuntimes = map[string]bool{
+ StockRuntimeName: true,
+ LinuxV1RuntimeName: true,
+ LinuxV2RuntimeName: true,
+}
+
// flatOptions contains configuration keys
// that MUST NOT be parsed as deep structures.
// Use this to differentiate these options
@@ -571,10 +584,12 @@ func Validate(config *Config) error {
return err
}
- if defaultRuntime := config.GetDefaultRuntimeName(); defaultRuntime != "" && defaultRuntime != StockRuntimeName {
- runtimes := config.GetAllRuntimes()
- if _, ok := runtimes[defaultRuntime]; !ok {
- return fmt.Errorf("specified default runtime '%s' does not exist", defaultRuntime)
+ if defaultRuntime := config.GetDefaultRuntimeName(); defaultRuntime != "" {
+ if !builtinRuntimes[defaultRuntime] {
+ runtimes := config.GetAllRuntimes()
+ if _, ok := runtimes[defaultRuntime]; !ok {
+ return fmt.Errorf("specified default runtime '%s' does not exist", defaultRuntime)
+ }
}
}
diff --git a/daemon/daemon.go b/daemon/daemon.go
index 3ea3069888..98c852b425 100644
--- a/daemon/daemon.go
+++ b/daemon/daemon.go
@@ -932,7 +932,11 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
}
}
- return pluginexec.New(ctx, getPluginExecRoot(config.Root), pluginCli, config.ContainerdPluginNamespace, m, d.useShimV2())
+ var rt types.Runtime
+ if runtime := config.GetRuntime(config.GetDefaultRuntimeName()); runtime != nil {
+ rt = *runtime
+ }
+ return pluginexec.New(ctx, getPluginExecRoot(config.Root), pluginCli, config.ContainerdPluginNamespace, m, rt)
}
// Plugin system initialization should happen before restore. Do not change order.
@@ -1081,7 +1085,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S
go d.execCommandGC()
- d.containerd, err = libcontainerd.NewClient(ctx, d.containerdCli, filepath.Join(config.ExecRoot, "containerd"), config.ContainerdNamespace, d, d.useShimV2())
+ d.containerd, err = libcontainerd.NewClient(ctx, d.containerdCli, filepath.Join(config.ExecRoot, "containerd"), config.ContainerdNamespace, d)
if err != nil {
return nil, err
}
diff --git a/daemon/daemon_unix.go b/daemon/daemon_unix.go
index 1a577276ef..e3cf60e7fd 100644
--- a/daemon/daemon_unix.go
+++ b/daemon/daemon_unix.go
@@ -30,7 +30,6 @@ import (
"github.com/docker/docker/opts"
"github.com/docker/docker/pkg/containerfs"
"github.com/docker/docker/pkg/idtools"
- "github.com/docker/docker/pkg/ioutils"
"github.com/docker/docker/pkg/parsers"
"github.com/docker/docker/pkg/parsers/kernel"
"github.com/docker/docker/pkg/sysinfo"
@@ -78,10 +77,6 @@ const (
cgroupFsDriver = "cgroupfs"
cgroupSystemdDriver = "systemd"
cgroupNoneDriver = "none"
-
- // DefaultRuntimeName is the default runtime to be used by
- // containerd if none is specified
- DefaultRuntimeName = "runc"
)
type containerGetter interface {
@@ -729,55 +724,11 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
}
}
- return warnings, nil
-}
-
-func (daemon *Daemon) loadRuntimes() error {
- return daemon.initRuntimes(daemon.configStore.Runtimes)
-}
-
-func (daemon *Daemon) initRuntimes(runtimes map[string]types.Runtime) (err error) {
- runtimeDir := filepath.Join(daemon.configStore.Root, "runtimes")
- // Remove old temp directory if any
- os.RemoveAll(runtimeDir + "-old")
- tmpDir, err := ioutils.TempDir(daemon.configStore.Root, "gen-runtimes")
- if err != nil {
- return errors.Wrap(err, "failed to get temp dir to generate runtime scripts")
+ if hostConfig.Runtime == config.LinuxV1RuntimeName || (hostConfig.Runtime == "" && daemon.configStore.DefaultRuntime == config.LinuxV1RuntimeName) {
+ warnings = append(warnings, fmt.Sprintf("Configured runtime %q is deprecated and will be removed in the next release.", config.LinuxV1RuntimeName))
}
- defer func() {
- if err != nil {
- if err1 := os.RemoveAll(tmpDir); err1 != nil {
- logrus.WithError(err1).WithField("dir", tmpDir).
- Warn("failed to remove tmp dir")
- }
- return
- }
-
- if err = os.Rename(runtimeDir, runtimeDir+"-old"); err != nil {
- return
- }
- if err = os.Rename(tmpDir, runtimeDir); err != nil {
- err = errors.Wrap(err, "failed to setup runtimes dir, new containers may not start")
- return
- }
- if err = os.RemoveAll(runtimeDir + "-old"); err != nil {
- logrus.WithError(err).WithField("dir", tmpDir).
- Warn("failed to remove old runtimes dir")
- }
- }()
- for name, rt := range runtimes {
- if len(rt.Args) == 0 {
- continue
- }
-
- script := filepath.Join(tmpDir, name)
- content := fmt.Sprintf("#!/bin/sh\n%s %s $@\n", rt.Path, strings.Join(rt.Args, " "))
- if err := ioutil.WriteFile(script, []byte(content), 0700); err != nil {
- return err
- }
- }
- return nil
+ return warnings, nil
}
// verifyDaemonSettings performs validation of daemon config struct
@@ -808,14 +759,15 @@ func verifyDaemonSettings(conf *config.Config) error {
return fmt.Errorf("exec-opt native.cgroupdriver=systemd requires cgroup v2 for rootless mode")
}
- if conf.DefaultRuntime == "" {
- conf.DefaultRuntime = config.StockRuntimeName
- }
- if conf.Runtimes == nil {
- conf.Runtimes = make(map[string]types.Runtime)
+ configureRuntimes(conf)
+ if rtName := conf.GetDefaultRuntimeName(); rtName != "" {
+ if conf.GetRuntime(rtName) == nil {
+ return fmt.Errorf("specified default runtime '%s' does not exist", rtName)
+ }
+ if rtName == config.LinuxV1RuntimeName {
+ logrus.Warnf("Configured default runtime %q is deprecated and will be removed in the next release.", config.LinuxV1RuntimeName)
+ }
}
- conf.Runtimes[config.StockRuntimeName] = types.Runtime{Path: DefaultRuntimeName}
-
return nil
}
@@ -1756,10 +1708,6 @@ func (daemon *Daemon) setupSeccompProfile() error {
return nil
}
-func (daemon *Daemon) useShimV2() bool {
- return cgroups.IsCgroup2UnifiedMode()
-}
-
// RawSysInfo returns *sysinfo.SysInfo .
func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
var opts []sysinfo.Opt
diff --git a/daemon/info.go b/daemon/info.go
index 72f30cdd00..cbae94ec47 100644
--- a/daemon/info.go
+++ b/daemon/info.go
@@ -11,6 +11,7 @@ import (
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/cli/debug"
+ "github.com/docker/docker/daemon/config"
"github.com/docker/docker/daemon/logger"
"github.com/docker/docker/dockerversion"
"github.com/docker/docker/pkg/fileutils"
@@ -78,6 +79,10 @@ func (daemon *Daemon) SystemInfo() *types.Info {
daemon.fillSecurityOptions(v, sysInfo)
daemon.fillLicense(v)
+ if v.DefaultRuntime == config.LinuxV1RuntimeName {
+ v.Warnings = append(v.Warnings, fmt.Sprintf("Configured default runtime %q is deprecated and will be removed in the next release.", config.LinuxV1RuntimeName))
+ }
+
return v
}
diff --git a/daemon/runtime_unix.go b/daemon/runtime_unix.go
new file mode 100644
index 0000000000..17e2b15d49
--- /dev/null
+++ b/daemon/runtime_unix.go
@@ -0,0 +1,134 @@
+// +build !windows
+
+package daemon
+
+import (
+ "fmt"
+ "io/ioutil"
+ "os"
+ "os/exec"
+ "path/filepath"
+ "strings"
+
+ "github.com/containerd/containerd/runtime/linux/runctypes"
+ v2runcoptions "github.com/containerd/containerd/runtime/v2/runc/options"
+ "github.com/docker/docker/api/types"
+ "github.com/docker/docker/daemon/config"
+ "github.com/docker/docker/pkg/ioutils"
+ "github.com/opencontainers/runc/libcontainer/cgroups"
+ "github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
+)
+
+const (
+ defaultRuntimeName = "runc"
+
+ linuxShimV1 = "io.containerd.runtime.v1.linux"
+ linuxShimV2 = "io.containerd.runc.v2"
+)
+
+func configureRuntimes(conf *config.Config) {
+ if conf.DefaultRuntime == "" {
+ conf.DefaultRuntime = config.StockRuntimeName
+ }
+ if conf.Runtimes == nil {
+ conf.Runtimes = make(map[string]types.Runtime)
+ }
+ conf.Runtimes[config.StockRuntimeName] = types.Runtime{Path: defaultRuntimeName, Shim: getShimConfig(conf, defaultRuntimeName)}
+ conf.Runtimes[config.LinuxV1RuntimeName] = types.Runtime{Path: defaultRuntimeName, Shim: defaultV1ShimConfig(conf, defaultRuntimeName)}
+ conf.Runtimes[config.LinuxV2RuntimeName] = types.Runtime{Path: defaultRuntimeName, Shim: defaultV2ShimConfig(conf, defaultRuntimeName)}
+}
+
+func getShimConfig(conf *config.Config, runtimePath string) *types.ShimConfig {
+ if cgroups.IsCgroup2UnifiedMode() {
+ return defaultV2ShimConfig(conf, runtimePath)
+ }
+ return defaultV1ShimConfig(conf, runtimePath)
+}
+
+func defaultV2ShimConfig(conf *config.Config, runtimePath string) *types.ShimConfig {
+ return &types.ShimConfig{
+ Binary: linuxShimV2,
+ Opts: &v2runcoptions.Options{
+ BinaryName: runtimePath,
+ Root: filepath.Join(conf.ExecRoot, "runtime-"+defaultRuntimeName),
+ SystemdCgroup: UsingSystemd(conf),
+ NoPivotRoot: os.Getenv("DOCKER_RAMDISK") != "",
+ },
+ }
+}
+
+func defaultV1ShimConfig(conf *config.Config, runtimePath string) *types.ShimConfig {
+ return &types.ShimConfig{
+ Binary: linuxShimV1,
+ Opts: &runctypes.RuncOptions{
+ Runtime: runtimePath,
+ RuntimeRoot: filepath.Join(conf.ExecRoot, "runtime-"+defaultRuntimeName),
+ SystemdCgroup: UsingSystemd(conf),
+ },
+ }
+}
+
+func (daemon *Daemon) loadRuntimes() error {
+ return daemon.initRuntimes(daemon.configStore.Runtimes)
+}
+
+func (daemon *Daemon) initRuntimes(runtimes map[string]types.Runtime) (err error) {
+ runtimeDir := filepath.Join(daemon.configStore.Root, "runtimes")
+ // Remove old temp directory if any
+ os.RemoveAll(runtimeDir + "-old")
+ tmpDir, err := ioutils.TempDir(daemon.configStore.Root, "gen-runtimes")
+ if err != nil {
+ return errors.Wrap(err, "failed to get temp dir to generate runtime scripts")
+ }
+ defer func() {
+ if err != nil {
+ if err1 := os.RemoveAll(tmpDir); err1 != nil {
+ logrus.WithError(err1).WithField("dir", tmpDir).
+ Warn("failed to remove tmp dir")
+ }
+ return
+ }
+
+ if err = os.Rename(runtimeDir, runtimeDir+"-old"); err != nil {
+ return
+ }
+ if err = os.Rename(tmpDir, runtimeDir); err != nil {
+ err = errors.Wrap(err, "failed to setup runtimes dir, new containers may not start")
+ return
+ }
+ if err = os.RemoveAll(runtimeDir + "-old"); err != nil {
+ logrus.WithError(err).WithField("dir", tmpDir).
+ Warn("failed to remove old runtimes dir")
+ }
+ }()
+
+ for name, rt := range runtimes {
+ if len(rt.Args) == 0 {
+ continue
+ }
+
+ script := filepath.Join(tmpDir, name)
+ content := fmt.Sprintf("#!/bin/sh\n%s %s $@\n", rt.Path, strings.Join(rt.Args, " "))
+ if err := ioutil.WriteFile(script, []byte(content), 0700); err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+// rewriteRuntimePath is used for runtimes which have custom arguments supplied.
+// This is needed because the containerd API only calls the OCI runtime binary, there is no options for extra arguments.
+// To support this case, the daemon wraps the specified runtime in a script that passes through those arguments.
+func (daemon *Daemon) rewriteRuntimePath(name, p string, args []string) (string, error) {
+ if len(args) == 0 {
+ return p, nil
+ }
+
+ // Check that the runtime path actually exists here so that we can return a well known error.
+ if _, err := exec.LookPath(p); err != nil {
+ return "", errors.Wrap(err, "error while looking up the specified runtime path")
+ }
+
+ return filepath.Join(daemon.configStore.Root, "runtimes", name), nil
+}
diff --git a/daemon/start.go b/daemon/start.go
index 857b5fb80b..6126efacbf 100644
--- a/daemon/start.go
+++ b/daemon/start.go
@@ -175,7 +175,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
}
}
- createOptions, err := daemon.getLibcontainerdCreateOptions(container)
+ shim, createOptions, err := daemon.getLibcontainerdCreateOptions(container)
if err != nil {
return err
}
@@ -187,7 +187,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
return err
}
- err = daemon.containerd.Create(ctx, container.ID, spec, createOptions, withImageName(imageRef.String()))
+ err = daemon.containerd.Create(ctx, container.ID, spec, shim, createOptions, withImageName(imageRef.String()))
if err != nil {
if errdefs.IsConflict(err) {
logrus.WithError(err).WithField("container", container.ID).Error("Container not cleaned up from containerd from previous run")
@@ -196,7 +196,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
if err := daemon.containerd.Delete(ctx, container.ID); err != nil && !errdefs.IsNotFound(err) {
logrus.WithError(err).WithField("container", container.ID).Error("Error cleaning up stale containerd container object")
}
- err = daemon.containerd.Create(ctx, container.ID, spec, createOptions, withImageName(imageRef.String()))
+ err = daemon.containerd.Create(ctx, container.ID, spec, shim, createOptions, withImageName(imageRef.String()))
}
if err != nil {
return translateContainerdStartErr(container.Path, container.SetExitCode, err)
diff --git a/daemon/start_unix.go b/daemon/start_unix.go
index 73963b9cf6..4373a97d83 100644
--- a/daemon/start_unix.go
+++ b/daemon/start_unix.go
@@ -3,70 +3,35 @@
package daemon // import "github.com/docker/docker/daemon"
import (
- "fmt"
- "os/exec"
- "path/filepath"
-
- "github.com/containerd/containerd/runtime/linux/runctypes"
- v2runcoptions "github.com/containerd/containerd/runtime/v2/runc/options"
"github.com/docker/docker/container"
"github.com/docker/docker/errdefs"
+ "github.com/opencontainers/runc/libcontainer/cgroups"
"github.com/pkg/errors"
+ "github.com/sirupsen/logrus"
)
-func (daemon *Daemon) getRuntimeScript(container *container.Container) (string, error) {
- name := container.HostConfig.Runtime
- rt := daemon.configStore.GetRuntime(name)
- if rt == nil {
- return "", errdefs.InvalidParameter(errors.Errorf("no such runtime '%s'", name))
- }
-
- if len(rt.Args) > 0 {
- // First check that the target exist, as using it in a script won't
- // give us the right error
- if _, err := exec.LookPath(rt.Path); err != nil {
- return "", translateContainerdStartErr(container.Path, container.SetExitCode, err)
- }
- return filepath.Join(daemon.configStore.Root, "runtimes", name), nil
- }
- return rt.Path, nil
-}
-
// getLibcontainerdCreateOptions callers must hold a lock on the container
-func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Container) (interface{}, error) {
+func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Container) (string, interface{}, error) {
// Ensure a runtime has been assigned to this container
if container.HostConfig.Runtime == "" {
container.HostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
container.CheckpointTo(daemon.containersReplica)
}
- path, err := daemon.getRuntimeScript(container)
- if err != nil {
- return nil, err
- }
- if daemon.useShimV2() {
- opts := &v2runcoptions.Options{
- BinaryName: path,
- Root: filepath.Join(daemon.configStore.ExecRoot,
- fmt.Sprintf("runtime-%s", container.HostConfig.Runtime)),
+ rt := daemon.configStore.GetRuntime(container.HostConfig.Runtime)
+ if rt.Shim == nil {
+ p, err := daemon.rewriteRuntimePath(container.HostConfig.Runtime, rt.Path, rt.Args)
+ if err != nil {
+ return "", nil, translateContainerdStartErr(container.Path, container.SetExitCode, err)
}
-
- if UsingSystemd(daemon.configStore) {
- opts.SystemdCgroup = true
- }
-
- return opts, nil
-
+ rt.Shim = getShimConfig(daemon.configStore, p)
}
- opts := &runctypes.RuncOptions{
- Runtime: path,
- RuntimeRoot: filepath.Join(daemon.configStore.ExecRoot,
- fmt.Sprintf("runtime-%s", container.HostConfig.Runtime)),
- }
-
- if UsingSystemd(daemon.configStore) {
- opts.SystemdCgroup = true
+ if rt.Shim.Binary == linuxShimV1 {
+ if cgroups.IsCgroup2UnifiedMode() {
+ return "", nil, errdefs.InvalidParameter(errors.Errorf("runtime %q is not supported while cgroups v2 (unified hierarchy) is being used", container.HostConfig.Runtime))
+ }
+ logrus.Warnf("Configured runtime %q is deprecated and will be removed in the next release", container.HostConfig.Runtime)
}
- return opts, nil
+ return rt.Shim.Binary, rt.Shim.Opts, nil
}
diff --git a/daemon/start_windows.go b/daemon/start_windows.go
index fc34375e7e..d21fec5d70 100644
--- a/daemon/start_windows.go
+++ b/daemon/start_windows.go
@@ -7,12 +7,12 @@ import (
"github.com/docker/docker/pkg/system"
)
-func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Container) (interface{}, error) {
+func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Container) (string, interface{}, error) {
// Set the runtime options to debug regardless of current logging level.
if system.ContainerdRuntimeSupported() {
opts := &options.Options{Debug: true}
- return opts, nil
+ return "", opts, nil
}
// TODO (containerd) - Probably need to revisit LCOW options here
@@ -22,7 +22,7 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
if container.OS == "linux" {
config := &client.Config{}
if err := config.GenerateDefault(daemon.configStore.GraphOptions); err != nil {
- return nil, err
+ return "", nil, err
}
// Override from user-supplied options.
for k, v := range container.HostConfig.StorageOpt {
@@ -34,11 +34,11 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
}
}
if err := config.Validate(); err != nil {
- return nil, err
+ return "", nil, err
}
- return config, nil
+ return "", config, nil
}
- return nil, nil
+ return "", nil, nil
}
diff --git a/daemon/util_test.go b/daemon/util_test.go
index 6ef9ba682b..05cf1dd344 100644
--- a/daemon/util_test.go
+++ b/daemon/util_test.go
@@ -28,7 +28,7 @@ func (c *MockContainerdClient) Version(ctx context.Context) (containerd.Version,
func (c *MockContainerdClient) Restore(ctx context.Context, containerID string, attachStdio libcontainerdtypes.StdioCallback) (alive bool, pid int, p libcontainerdtypes.Process, err error) {
return false, 0, &mockProcess{}, nil
}
-func (c *MockContainerdClient) Create(ctx context.Context, containerID string, spec *specs.Spec, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) error {
+func (c *MockContainerdClient) Create(ctx context.Context, containerID string, spec *specs.Spec, shim string, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) error {
return nil
}
func (c *MockContainerdClient) Start(ctx context.Context, containerID, checkpointDir string, withStdin bool, attachStdio libcontainerdtypes.StdioCallback) (pid int, err error) {
diff --git a/libcontainerd/libcontainerd_linux.go b/libcontainerd/libcontainerd_linux.go
index 3b008fe256..ec195a7905 100644
--- a/libcontainerd/libcontainerd_linux.go
+++ b/libcontainerd/libcontainerd_linux.go
@@ -9,6 +9,6 @@ import (
)
// NewClient creates a new libcontainerd client from a containerd client
-func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend, useShimV2 bool) (libcontainerdtypes.Client, error) {
- return remote.NewClient(ctx, cli, stateDir, ns, b, useShimV2)
+func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend) (libcontainerdtypes.Client, error) {
+ return remote.NewClient(ctx, cli, stateDir, ns, b)
}
diff --git a/libcontainerd/libcontainerd_windows.go b/libcontainerd/libcontainerd_windows.go
index 5a64180be4..e7f0bc9d30 100644
--- a/libcontainerd/libcontainerd_windows.go
+++ b/libcontainerd/libcontainerd_windows.go
@@ -11,10 +11,10 @@ import (
)
// NewClient creates a new libcontainerd client from a containerd client
-func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend, useShimV2 bool) (libcontainerdtypes.Client, error) {
+func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend) (libcontainerdtypes.Client, error) {
if !system.ContainerdRuntimeSupported() {
// useShimV2 is ignored for windows
return local.NewClient(ctx, cli, stateDir, ns, b)
}
- return remote.NewClient(ctx, cli, stateDir, ns, b, useShimV2)
+ return remote.NewClient(ctx, cli, stateDir, ns, b)
}
diff --git a/libcontainerd/local/local_windows.go b/libcontainerd/local/local_windows.go
index 67592e54e8..85e1d8c772 100644
--- a/libcontainerd/local/local_windows.go
+++ b/libcontainerd/local/local_windows.go
@@ -153,7 +153,7 @@ func (c *client) Version(ctx context.Context) (containerd.Version, error) {
// "ImagePath": "C:\\\\control\\\\windowsfilter\\\\65bf96e5760a09edf1790cb229e2dfb2dbd0fcdc0bf7451bae099106bfbfea0c\\\\UtilityVM"
// },
// }
-func (c *client) Create(_ context.Context, id string, spec *specs.Spec, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) error {
+func (c *client) Create(_ context.Context, id string, spec *specs.Spec, shim string, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) error {
if ctr := c.getContainer(id); ctr != nil {
return errors.WithStack(errdefs.Conflict(errors.New("id already in use")))
}
diff --git a/libcontainerd/remote/client.go b/libcontainerd/remote/client.go
index 9bc4ffde02..11a5990a7b 100644
--- a/libcontainerd/remote/client.go
+++ b/libcontainerd/remote/client.go
@@ -50,14 +50,13 @@ type client struct {
eventQ queue.Queue
oomMu sync.Mutex
oom map[string]bool
- useShimV2 bool
v2runcoptionsMu sync.Mutex
// v2runcoptions is used for copying options specified on Create() to Start()
v2runcoptions map[string]v2runcoptions.Options
}
// NewClient creates a new libcontainerd client from a containerd client
-func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend, useShimV2 bool) (libcontainerdtypes.Client, error) {
+func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string, b libcontainerdtypes.Backend) (libcontainerdtypes.Client, error) {
c := &client{
client: cli,
stateDir: stateDir,
@@ -65,7 +64,6 @@ func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string,
ns: ns,
backend: b,
oom: make(map[string]bool),
- useShimV2: useShimV2,
v2runcoptions: make(map[string]v2runcoptions.Options),
}
@@ -129,17 +127,13 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio libcontaine
}, nil
}
-func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) error {
+func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, shim string, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) error {
bdir := c.bundleDir(id)
c.logger.WithField("bundle", bdir).WithField("root", ociSpec.Root.Path).Debug("bundle dir created")
- rt := runtimeName
- if c.useShimV2 {
- rt = shimV2RuntimeName
- }
newOpts := []containerd.NewContainerOpts{
containerd.WithSpec(ociSpec),
- containerd.WithRuntime(rt, runtimeOptions),
+ containerd.WithRuntime(shim, runtimeOptions),
WithBundle(bdir, ociSpec),
}
opts = append(opts, newOpts...)
@@ -151,12 +145,10 @@ func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, run
}
return wrapError(err)
}
- if c.useShimV2 {
- if x, ok := runtimeOptions.(*v2runcoptions.Options); ok {
- c.v2runcoptionsMu.Lock()
- c.v2runcoptions[id] = *x
- c.v2runcoptionsMu.Unlock()
- }
+ if x, ok := runtimeOptions.(*v2runcoptions.Options); ok {
+ c.v2runcoptionsMu.Lock()
+ c.v2runcoptions[id] = *x
+ c.v2runcoptionsMu.Unlock()
}
return nil
}
@@ -218,17 +210,12 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin
if runtime.GOOS != "windows" {
taskOpts = append(taskOpts, func(_ context.Context, _ *containerd.Client, info *containerd.TaskInfo) error {
- if c.useShimV2 {
- // For v2, we need to inherit options specified on Create
- c.v2runcoptionsMu.Lock()
- opts, ok := c.v2runcoptions[id]
- c.v2runcoptionsMu.Unlock()
- if !ok {
- opts = v2runcoptions.Options{}
- }
+ c.v2runcoptionsMu.Lock()
+ opts, ok := c.v2runcoptions[id]
+ c.v2runcoptionsMu.Unlock()
+ if ok {
opts.IoUid = uint32(uid)
opts.IoGid = uint32(gid)
- opts.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
info.Options = &opts
} else {
info.Options = &runctypes.CreateOptions{
@@ -237,7 +224,6 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin
NoPivotRoot: os.Getenv("DOCKER_RAMDISK") != "",
}
}
-
return nil
})
} else {
diff --git a/libcontainerd/remote/client_linux.go b/libcontainerd/remote/client_linux.go
index 637ac94d82..e45d140b2f 100644
--- a/libcontainerd/remote/client_linux.go
+++ b/libcontainerd/remote/client_linux.go
@@ -16,11 +16,6 @@ import (
"github.com/sirupsen/logrus"
)
-const (
- runtimeName = "io.containerd.runtime.v1.linux"
- shimV2RuntimeName = "io.containerd.runc.v2"
-)
-
func summaryFromInterface(i interface{}) (*libcontainerdtypes.Summary, error) {
return &libcontainerdtypes.Summary{}, nil
}
diff --git a/libcontainerd/types/types.go b/libcontainerd/types/types.go
index ba88e4db6f..1d1a420e79 100644
--- a/libcontainerd/types/types.go
+++ b/libcontainerd/types/types.go
@@ -52,7 +52,7 @@ type Client interface {
Restore(ctx context.Context, containerID string, attachStdio StdioCallback) (alive bool, pid int, p Process, err error)
- Create(ctx context.Context, containerID string, spec *specs.Spec, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) error
+ Create(ctx context.Context, containerID string, spec *specs.Spec, shim string, runtimeOptions interface{}, opts ...containerd.NewContainerOpts) error
Start(ctx context.Context, containerID, checkpointDir string, withStdin bool, attachStdio StdioCallback) (pid int, err error)
SignalProcess(ctx context.Context, containerID, processID string, signal int) error
Exec(ctx context.Context, containerID, processID string, spec *specs.Process, withStdin bool, attachStdio StdioCallback) (int, error)
diff --git a/plugin/executor/containerd/containerd.go b/plugin/executor/containerd/containerd.go
index aeeb2184ec..8354745990 100644
--- a/plugin/executor/containerd/containerd.go
+++ b/plugin/executor/containerd/containerd.go
@@ -3,12 +3,11 @@ package containerd // import "github.com/docker/docker/plugin/executor/container
import (
"context"
"io"
- "path/filepath"
"sync"
"github.com/containerd/containerd"
"github.com/containerd/containerd/cio"
- "github.com/containerd/containerd/runtime/linux/runctypes"
+ "github.com/docker/docker/api/types"
"github.com/docker/docker/errdefs"
"github.com/docker/docker/libcontainerd"
libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
@@ -26,13 +25,14 @@ type ExitHandler interface {
}
// New creates a new containerd plugin executor
-func New(ctx context.Context, rootDir string, cli *containerd.Client, ns string, exitHandler ExitHandler, useShimV2 bool) (*Executor, error) {
+func New(ctx context.Context, rootDir string, cli *containerd.Client, ns string, exitHandler ExitHandler, runtime types.Runtime) (*Executor, error) {
e := &Executor{
rootDir: rootDir,
exitHandler: exitHandler,
+ runtime: runtime,
}
- client, err := libcontainerd.NewClient(ctx, cli, rootDir, ns, e, useShimV2)
+ client, err := libcontainerd.NewClient(ctx, cli, rootDir, ns, e)
if err != nil {
return nil, errors.Wrap(err, "error creating containerd exec client")
}
@@ -45,6 +45,7 @@ type Executor struct {
rootDir string
client libcontainerdtypes.Client
exitHandler ExitHandler
+ runtime types.Runtime
}
// deleteTaskAndContainer deletes plugin task and then plugin container from containerd
@@ -66,11 +67,8 @@ func deleteTaskAndContainer(ctx context.Context, cli libcontainerdtypes.Client,
// Create creates a new container
func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteCloser) error {
- opts := runctypes.RuncOptions{
- RuntimeRoot: filepath.Join(e.rootDir, "runtime-root"),
- }
ctx := context.Background()
- err := e.client.Create(ctx, id, &spec, &opts)
+ err := e.client.Create(ctx, id, &spec, e.runtime.Shim.Binary, e.runtime.Shim.Opts)
if err != nil {
status, err2 := e.client.Status(ctx, id)
if err2 != nil {
@@ -82,7 +80,7 @@ func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteClo
if err2 := e.client.Delete(ctx, id); err2 != nil && !errdefs.IsNotFound(err2) {
logrus.WithError(err2).WithField("plugin", id).Error("Error cleaning up containerd container")
}
- err = e.client.Create(ctx, id, &spec, &opts)
+ err = e.client.Create(ctx, id, &spec, e.runtime.Shim.Binary, e.runtime.Shim.Opts)
}
}