mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	Merge pull request #41182 from cpuguy83/runtime_configure_shim
This commit is contained in:
		
						commit
						61b73ee714
					
				
					 18 changed files with 239 additions and 179 deletions
				
			
		| 
						 | 
					@ -511,6 +511,16 @@ type Checkpoint struct {
 | 
				
			||||||
type Runtime struct {
 | 
					type Runtime struct {
 | 
				
			||||||
	Path string   `json:"path"`
 | 
						Path string   `json:"path"`
 | 
				
			||||||
	Args []string `json:"runtimeArgs,omitempty"`
 | 
						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:
 | 
					// DiskUsage contains response of Engine API:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,9 +36,6 @@ const (
 | 
				
			||||||
	// maximum number of attempts that
 | 
						// maximum number of attempts that
 | 
				
			||||||
	// may take place at a time for each pull when the connection is lost.
 | 
						// may take place at a time for each pull when the connection is lost.
 | 
				
			||||||
	DefaultDownloadAttempts = 5
 | 
						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 is the default value for container's shm size
 | 
				
			||||||
	DefaultShmSize = int64(67108864)
 | 
						DefaultShmSize = int64(67108864)
 | 
				
			||||||
	// DefaultNetworkMtu is the default value for network MTU
 | 
						// DefaultNetworkMtu is the default value for network MTU
 | 
				
			||||||
| 
						 | 
					@ -47,8 +44,24 @@ const (
 | 
				
			||||||
	DisableNetworkBridge = "none"
 | 
						DisableNetworkBridge = "none"
 | 
				
			||||||
	// DefaultInitBinary is the name of the default init binary
 | 
						// DefaultInitBinary is the name of the default init binary
 | 
				
			||||||
	DefaultInitBinary = "docker-init"
 | 
						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
 | 
					// flatOptions contains configuration keys
 | 
				
			||||||
// that MUST NOT be parsed as deep structures.
 | 
					// that MUST NOT be parsed as deep structures.
 | 
				
			||||||
// Use this to differentiate these options
 | 
					// Use this to differentiate these options
 | 
				
			||||||
| 
						 | 
					@ -571,12 +584,14 @@ func Validate(config *Config) error {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if defaultRuntime := config.GetDefaultRuntimeName(); defaultRuntime != "" && defaultRuntime != StockRuntimeName {
 | 
						if defaultRuntime := config.GetDefaultRuntimeName(); defaultRuntime != "" {
 | 
				
			||||||
 | 
							if !builtinRuntimes[defaultRuntime] {
 | 
				
			||||||
			runtimes := config.GetAllRuntimes()
 | 
								runtimes := config.GetAllRuntimes()
 | 
				
			||||||
			if _, ok := runtimes[defaultRuntime]; !ok {
 | 
								if _, ok := runtimes[defaultRuntime]; !ok {
 | 
				
			||||||
				return fmt.Errorf("specified default runtime '%s' does not exist", defaultRuntime)
 | 
									return fmt.Errorf("specified default runtime '%s' does not exist", defaultRuntime)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// validate platform-specific settings
 | 
						// validate platform-specific settings
 | 
				
			||||||
	return config.ValidatePlatformConfig()
 | 
						return config.ValidatePlatformConfig()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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.
 | 
						// 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()
 | 
						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 {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,7 +30,6 @@ import (
 | 
				
			||||||
	"github.com/docker/docker/opts"
 | 
						"github.com/docker/docker/opts"
 | 
				
			||||||
	"github.com/docker/docker/pkg/containerfs"
 | 
						"github.com/docker/docker/pkg/containerfs"
 | 
				
			||||||
	"github.com/docker/docker/pkg/idtools"
 | 
						"github.com/docker/docker/pkg/idtools"
 | 
				
			||||||
	"github.com/docker/docker/pkg/ioutils"
 | 
					 | 
				
			||||||
	"github.com/docker/docker/pkg/parsers"
 | 
						"github.com/docker/docker/pkg/parsers"
 | 
				
			||||||
	"github.com/docker/docker/pkg/parsers/kernel"
 | 
						"github.com/docker/docker/pkg/parsers/kernel"
 | 
				
			||||||
	"github.com/docker/docker/pkg/sysinfo"
 | 
						"github.com/docker/docker/pkg/sysinfo"
 | 
				
			||||||
| 
						 | 
					@ -78,10 +77,6 @@ const (
 | 
				
			||||||
	cgroupFsDriver      = "cgroupfs"
 | 
						cgroupFsDriver      = "cgroupfs"
 | 
				
			||||||
	cgroupSystemdDriver = "systemd"
 | 
						cgroupSystemdDriver = "systemd"
 | 
				
			||||||
	cgroupNoneDriver    = "none"
 | 
						cgroupNoneDriver    = "none"
 | 
				
			||||||
 | 
					 | 
				
			||||||
	// DefaultRuntimeName is the default runtime to be used by
 | 
					 | 
				
			||||||
	// containerd if none is specified
 | 
					 | 
				
			||||||
	DefaultRuntimeName = "runc"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type containerGetter interface {
 | 
					type containerGetter interface {
 | 
				
			||||||
| 
						 | 
					@ -729,57 +724,13 @@ func verifyPlatformContainerSettings(daemon *Daemon, hostConfig *containertypes.
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return warnings, nil
 | 
						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")
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	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
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// verifyDaemonSettings performs validation of daemon config struct
 | 
					// verifyDaemonSettings performs validation of daemon config struct
 | 
				
			||||||
func verifyDaemonSettings(conf *config.Config) error {
 | 
					func verifyDaemonSettings(conf *config.Config) error {
 | 
				
			||||||
	if conf.ContainerdNamespace == conf.ContainerdPluginNamespace {
 | 
						if conf.ContainerdNamespace == conf.ContainerdPluginNamespace {
 | 
				
			||||||
| 
						 | 
					@ -808,14 +759,15 @@ func verifyDaemonSettings(conf *config.Config) error {
 | 
				
			||||||
		return fmt.Errorf("exec-opt native.cgroupdriver=systemd requires cgroup v2 for rootless mode")
 | 
							return fmt.Errorf("exec-opt native.cgroupdriver=systemd requires cgroup v2 for rootless mode")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if conf.DefaultRuntime == "" {
 | 
						configureRuntimes(conf)
 | 
				
			||||||
		conf.DefaultRuntime = config.StockRuntimeName
 | 
						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)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	if conf.Runtimes == nil {
 | 
					 | 
				
			||||||
		conf.Runtimes = make(map[string]types.Runtime)
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	conf.Runtimes[config.StockRuntimeName] = types.Runtime{Path: DefaultRuntimeName}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1756,10 +1708,6 @@ func (daemon *Daemon) setupSeccompProfile() error {
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (daemon *Daemon) useShimV2() bool {
 | 
					 | 
				
			||||||
	return cgroups.IsCgroup2UnifiedMode()
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// RawSysInfo returns *sysinfo.SysInfo .
 | 
					// RawSysInfo returns *sysinfo.SysInfo .
 | 
				
			||||||
func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
 | 
					func (daemon *Daemon) RawSysInfo(quiet bool) *sysinfo.SysInfo {
 | 
				
			||||||
	var opts []sysinfo.Opt
 | 
						var opts []sysinfo.Opt
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,6 +11,7 @@ import (
 | 
				
			||||||
	"github.com/docker/docker/api"
 | 
						"github.com/docker/docker/api"
 | 
				
			||||||
	"github.com/docker/docker/api/types"
 | 
						"github.com/docker/docker/api/types"
 | 
				
			||||||
	"github.com/docker/docker/cli/debug"
 | 
						"github.com/docker/docker/cli/debug"
 | 
				
			||||||
 | 
						"github.com/docker/docker/daemon/config"
 | 
				
			||||||
	"github.com/docker/docker/daemon/logger"
 | 
						"github.com/docker/docker/daemon/logger"
 | 
				
			||||||
	"github.com/docker/docker/dockerversion"
 | 
						"github.com/docker/docker/dockerversion"
 | 
				
			||||||
	"github.com/docker/docker/pkg/fileutils"
 | 
						"github.com/docker/docker/pkg/fileutils"
 | 
				
			||||||
| 
						 | 
					@ -78,6 +79,10 @@ func (daemon *Daemon) SystemInfo() *types.Info {
 | 
				
			||||||
	daemon.fillSecurityOptions(v, sysInfo)
 | 
						daemon.fillSecurityOptions(v, sysInfo)
 | 
				
			||||||
	daemon.fillLicense(v)
 | 
						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
 | 
						return v
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -48,7 +48,7 @@ func (daemon *Daemon) reloadPlatform(conf *config.Config, attributes map[string]
 | 
				
			||||||
		if runtimeList.Len() > 0 {
 | 
							if runtimeList.Len() > 0 {
 | 
				
			||||||
			runtimeList.WriteRune(' ')
 | 
								runtimeList.WriteRune(' ')
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		runtimeList.WriteString(fmt.Sprintf("%s:%s", name, rt))
 | 
							runtimeList.WriteString(fmt.Sprintf("%s:%s", name, rt.Path))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	attributes["runtimes"] = runtimeList.String()
 | 
						attributes["runtimes"] = runtimeList.String()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										134
									
								
								daemon/runtime_unix.go
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										134
									
								
								daemon/runtime_unix.go
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -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
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -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 {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -187,7 +187,7 @@ func (daemon *Daemon) containerStart(container *container.Container, checkpoint
 | 
				
			||||||
		return err
 | 
							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 err != nil {
 | 
				
			||||||
		if errdefs.IsConflict(err) {
 | 
							if errdefs.IsConflict(err) {
 | 
				
			||||||
			logrus.WithError(err).WithField("container", container.ID).Error("Container not cleaned up from containerd from previous run")
 | 
								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) {
 | 
								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")
 | 
									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 {
 | 
							if err != nil {
 | 
				
			||||||
			return translateContainerdStartErr(container.Path, container.SetExitCode, err)
 | 
								return translateContainerdStartErr(container.Path, container.SetExitCode, err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,70 +3,35 @@
 | 
				
			||||||
package daemon // import "github.com/docker/docker/daemon"
 | 
					package daemon // import "github.com/docker/docker/daemon"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					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/container"
 | 
				
			||||||
	"github.com/docker/docker/errdefs"
 | 
						"github.com/docker/docker/errdefs"
 | 
				
			||||||
 | 
						"github.com/opencontainers/runc/libcontainer/cgroups"
 | 
				
			||||||
	"github.com/pkg/errors"
 | 
						"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
 | 
					// 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
 | 
						// Ensure a runtime has been assigned to this container
 | 
				
			||||||
	if container.HostConfig.Runtime == "" {
 | 
						if container.HostConfig.Runtime == "" {
 | 
				
			||||||
		container.HostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
 | 
							container.HostConfig.Runtime = daemon.configStore.GetDefaultRuntimeName()
 | 
				
			||||||
		container.CheckpointTo(daemon.containersReplica)
 | 
							container.CheckpointTo(daemon.containersReplica)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	path, err := daemon.getRuntimeScript(container)
 | 
						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 {
 | 
							if err != nil {
 | 
				
			||||||
		return nil, err
 | 
								return "", nil, translateContainerdStartErr(container.Path, container.SetExitCode, err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	if daemon.useShimV2() {
 | 
							rt.Shim = getShimConfig(daemon.configStore, p)
 | 
				
			||||||
		opts := &v2runcoptions.Options{
 | 
						}
 | 
				
			||||||
			BinaryName: path,
 | 
						if rt.Shim.Binary == linuxShimV1 {
 | 
				
			||||||
			Root: filepath.Join(daemon.configStore.ExecRoot,
 | 
							if cgroups.IsCgroup2UnifiedMode() {
 | 
				
			||||||
				fmt.Sprintf("runtime-%s", container.HostConfig.Runtime)),
 | 
								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)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if UsingSystemd(daemon.configStore) {
 | 
						return rt.Shim.Binary, rt.Shim.Opts, nil
 | 
				
			||||||
			opts.SystemdCgroup = true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return opts, nil
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	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
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return opts, nil
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,12 +7,12 @@ import (
 | 
				
			||||||
	"github.com/docker/docker/pkg/system"
 | 
						"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.
 | 
						// Set the runtime options to debug regardless of current logging level.
 | 
				
			||||||
	if system.ContainerdRuntimeSupported() {
 | 
						if system.ContainerdRuntimeSupported() {
 | 
				
			||||||
		opts := &options.Options{Debug: true}
 | 
							opts := &options.Options{Debug: true}
 | 
				
			||||||
		return opts, nil
 | 
							return "", opts, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// TODO (containerd) - Probably need to revisit LCOW options here
 | 
						// TODO (containerd) - Probably need to revisit LCOW options here
 | 
				
			||||||
| 
						 | 
					@ -22,7 +22,7 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
 | 
				
			||||||
	if container.OS == "linux" {
 | 
						if container.OS == "linux" {
 | 
				
			||||||
		config := &client.Config{}
 | 
							config := &client.Config{}
 | 
				
			||||||
		if err := config.GenerateDefault(daemon.configStore.GraphOptions); err != nil {
 | 
							if err := config.GenerateDefault(daemon.configStore.GraphOptions); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return "", nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		// Override from user-supplied options.
 | 
							// Override from user-supplied options.
 | 
				
			||||||
		for k, v := range container.HostConfig.StorageOpt {
 | 
							for k, v := range container.HostConfig.StorageOpt {
 | 
				
			||||||
| 
						 | 
					@ -34,11 +34,11 @@ func (daemon *Daemon) getLibcontainerdCreateOptions(container *container.Contain
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if err := config.Validate(); err != nil {
 | 
							if err := config.Validate(); err != nil {
 | 
				
			||||||
			return nil, err
 | 
								return "", nil, err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return config, nil
 | 
							return "", config, nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil, nil
 | 
						return "", nil, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) {
 | 
					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
 | 
						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
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (c *MockContainerdClient) Start(ctx context.Context, containerID, checkpointDir string, withStdin bool, attachStdio libcontainerdtypes.StdioCallback) (pid int, err error) {
 | 
					func (c *MockContainerdClient) Start(ctx context.Context, containerID, checkpointDir string, withStdin bool, attachStdio libcontainerdtypes.StdioCallback) (pid int, err error) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,6 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewClient creates a new libcontainerd client from a containerd client
 | 
					// 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) {
 | 
				
			||||||
	return remote.NewClient(ctx, cli, stateDir, ns, b, useShimV2)
 | 
						return remote.NewClient(ctx, cli, stateDir, ns, b)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,10 +11,10 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewClient creates a new libcontainerd client from a containerd client
 | 
					// 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() {
 | 
						if !system.ContainerdRuntimeSupported() {
 | 
				
			||||||
		// useShimV2 is ignored for windows
 | 
							// useShimV2 is ignored for windows
 | 
				
			||||||
		return local.NewClient(ctx, cli, stateDir, ns, b)
 | 
							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)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -153,7 +153,7 @@ func (c *client) Version(ctx context.Context) (containerd.Version, error) {
 | 
				
			||||||
// 		"ImagePath": "C:\\\\control\\\\windowsfilter\\\\65bf96e5760a09edf1790cb229e2dfb2dbd0fcdc0bf7451bae099106bfbfea0c\\\\UtilityVM"
 | 
					// 		"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 {
 | 
						if ctr := c.getContainer(id); ctr != nil {
 | 
				
			||||||
		return errors.WithStack(errdefs.Conflict(errors.New("id already in use")))
 | 
							return errors.WithStack(errdefs.Conflict(errors.New("id already in use")))
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,14 +50,13 @@ type client struct {
 | 
				
			||||||
	eventQ          queue.Queue
 | 
						eventQ          queue.Queue
 | 
				
			||||||
	oomMu           sync.Mutex
 | 
						oomMu           sync.Mutex
 | 
				
			||||||
	oom             map[string]bool
 | 
						oom             map[string]bool
 | 
				
			||||||
	useShimV2       bool
 | 
					 | 
				
			||||||
	v2runcoptionsMu sync.Mutex
 | 
						v2runcoptionsMu sync.Mutex
 | 
				
			||||||
	// v2runcoptions is used for copying options specified on Create() to Start()
 | 
						// v2runcoptions is used for copying options specified on Create() to Start()
 | 
				
			||||||
	v2runcoptions map[string]v2runcoptions.Options
 | 
						v2runcoptions map[string]v2runcoptions.Options
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// NewClient creates a new libcontainerd client from a containerd client
 | 
					// 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{
 | 
						c := &client{
 | 
				
			||||||
		client:        cli,
 | 
							client:        cli,
 | 
				
			||||||
		stateDir:      stateDir,
 | 
							stateDir:      stateDir,
 | 
				
			||||||
| 
						 | 
					@ -65,7 +64,6 @@ func NewClient(ctx context.Context, cli *containerd.Client, stateDir, ns string,
 | 
				
			||||||
		ns:            ns,
 | 
							ns:            ns,
 | 
				
			||||||
		backend:       b,
 | 
							backend:       b,
 | 
				
			||||||
		oom:           make(map[string]bool),
 | 
							oom:           make(map[string]bool),
 | 
				
			||||||
		useShimV2:     useShimV2,
 | 
					 | 
				
			||||||
		v2runcoptions: make(map[string]v2runcoptions.Options),
 | 
							v2runcoptions: make(map[string]v2runcoptions.Options),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -129,17 +127,13 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio libcontaine
 | 
				
			||||||
	}, nil
 | 
						}, 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)
 | 
						bdir := c.bundleDir(id)
 | 
				
			||||||
	c.logger.WithField("bundle", bdir).WithField("root", ociSpec.Root.Path).Debug("bundle dir created")
 | 
						c.logger.WithField("bundle", bdir).WithField("root", ociSpec.Root.Path).Debug("bundle dir created")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rt := runtimeName
 | 
					 | 
				
			||||||
	if c.useShimV2 {
 | 
					 | 
				
			||||||
		rt = shimV2RuntimeName
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	newOpts := []containerd.NewContainerOpts{
 | 
						newOpts := []containerd.NewContainerOpts{
 | 
				
			||||||
		containerd.WithSpec(ociSpec),
 | 
							containerd.WithSpec(ociSpec),
 | 
				
			||||||
		containerd.WithRuntime(rt, runtimeOptions),
 | 
							containerd.WithRuntime(shim, runtimeOptions),
 | 
				
			||||||
		WithBundle(bdir, ociSpec),
 | 
							WithBundle(bdir, ociSpec),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	opts = append(opts, newOpts...)
 | 
						opts = append(opts, newOpts...)
 | 
				
			||||||
| 
						 | 
					@ -151,13 +145,11 @@ func (c *client) Create(ctx context.Context, id string, ociSpec *specs.Spec, run
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return wrapError(err)
 | 
							return wrapError(err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if c.useShimV2 {
 | 
					 | 
				
			||||||
	if x, ok := runtimeOptions.(*v2runcoptions.Options); ok {
 | 
						if x, ok := runtimeOptions.(*v2runcoptions.Options); ok {
 | 
				
			||||||
		c.v2runcoptionsMu.Lock()
 | 
							c.v2runcoptionsMu.Lock()
 | 
				
			||||||
		c.v2runcoptions[id] = *x
 | 
							c.v2runcoptions[id] = *x
 | 
				
			||||||
		c.v2runcoptionsMu.Unlock()
 | 
							c.v2runcoptionsMu.Unlock()
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -218,17 +210,12 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if runtime.GOOS != "windows" {
 | 
						if runtime.GOOS != "windows" {
 | 
				
			||||||
		taskOpts = append(taskOpts, func(_ context.Context, _ *containerd.Client, info *containerd.TaskInfo) error {
 | 
							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()
 | 
								c.v2runcoptionsMu.Lock()
 | 
				
			||||||
			opts, ok := c.v2runcoptions[id]
 | 
								opts, ok := c.v2runcoptions[id]
 | 
				
			||||||
			c.v2runcoptionsMu.Unlock()
 | 
								c.v2runcoptionsMu.Unlock()
 | 
				
			||||||
				if !ok {
 | 
								if ok {
 | 
				
			||||||
					opts = v2runcoptions.Options{}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				opts.IoUid = uint32(uid)
 | 
									opts.IoUid = uint32(uid)
 | 
				
			||||||
				opts.IoGid = uint32(gid)
 | 
									opts.IoGid = uint32(gid)
 | 
				
			||||||
				opts.NoPivotRoot = os.Getenv("DOCKER_RAMDISK") != ""
 | 
					 | 
				
			||||||
				info.Options = &opts
 | 
									info.Options = &opts
 | 
				
			||||||
			} else {
 | 
								} else {
 | 
				
			||||||
				info.Options = &runctypes.CreateOptions{
 | 
									info.Options = &runctypes.CreateOptions{
 | 
				
			||||||
| 
						 | 
					@ -237,7 +224,6 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin
 | 
				
			||||||
					NoPivotRoot: os.Getenv("DOCKER_RAMDISK") != "",
 | 
										NoPivotRoot: os.Getenv("DOCKER_RAMDISK") != "",
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			return nil
 | 
								return nil
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -16,11 +16,6 @@ import (
 | 
				
			||||||
	"github.com/sirupsen/logrus"
 | 
						"github.com/sirupsen/logrus"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					 | 
				
			||||||
	runtimeName       = "io.containerd.runtime.v1.linux"
 | 
					 | 
				
			||||||
	shimV2RuntimeName = "io.containerd.runc.v2"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func summaryFromInterface(i interface{}) (*libcontainerdtypes.Summary, error) {
 | 
					func summaryFromInterface(i interface{}) (*libcontainerdtypes.Summary, error) {
 | 
				
			||||||
	return &libcontainerdtypes.Summary{}, nil
 | 
						return &libcontainerdtypes.Summary{}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,7 +52,7 @@ type Client interface {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	Restore(ctx context.Context, containerID string, attachStdio StdioCallback) (alive bool, pid int, p Process, err error)
 | 
						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)
 | 
						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
 | 
						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)
 | 
						Exec(ctx context.Context, containerID, processID string, spec *specs.Process, withStdin bool, attachStdio StdioCallback) (int, error)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,12 +3,11 @@ package containerd // import "github.com/docker/docker/plugin/executor/container
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"path/filepath"
 | 
					 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/containerd/containerd"
 | 
						"github.com/containerd/containerd"
 | 
				
			||||||
	"github.com/containerd/containerd/cio"
 | 
						"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/errdefs"
 | 
				
			||||||
	"github.com/docker/docker/libcontainerd"
 | 
						"github.com/docker/docker/libcontainerd"
 | 
				
			||||||
	libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
 | 
						libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
 | 
				
			||||||
| 
						 | 
					@ -26,13 +25,14 @@ type ExitHandler interface {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// New creates a new containerd plugin executor
 | 
					// 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{
 | 
						e := &Executor{
 | 
				
			||||||
		rootDir:     rootDir,
 | 
							rootDir:     rootDir,
 | 
				
			||||||
		exitHandler: exitHandler,
 | 
							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 {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, errors.Wrap(err, "error creating containerd exec client")
 | 
							return nil, errors.Wrap(err, "error creating containerd exec client")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -45,6 +45,7 @@ type Executor struct {
 | 
				
			||||||
	rootDir     string
 | 
						rootDir     string
 | 
				
			||||||
	client      libcontainerdtypes.Client
 | 
						client      libcontainerdtypes.Client
 | 
				
			||||||
	exitHandler ExitHandler
 | 
						exitHandler ExitHandler
 | 
				
			||||||
 | 
						runtime     types.Runtime
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// deleteTaskAndContainer deletes plugin task and then plugin container from containerd
 | 
					// 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
 | 
					// Create creates a new container
 | 
				
			||||||
func (e *Executor) Create(id string, spec specs.Spec, stdout, stderr io.WriteCloser) error {
 | 
					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()
 | 
						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 {
 | 
						if err != nil {
 | 
				
			||||||
		status, err2 := e.client.Status(ctx, id)
 | 
							status, err2 := e.client.Status(ctx, id)
 | 
				
			||||||
		if err2 != nil {
 | 
							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) {
 | 
									if err2 := e.client.Delete(ctx, id); err2 != nil && !errdefs.IsNotFound(err2) {
 | 
				
			||||||
					logrus.WithError(err2).WithField("plugin", id).Error("Error cleaning up containerd container")
 | 
										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)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue