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 {
|
||||
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:
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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,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
|
||||
}
|
||||
|
||||
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
|
||||
func verifyDaemonSettings(conf *config.Config) error {
|
||||
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")
|
||||
}
|
||||
|
||||
if conf.DefaultRuntime == "" {
|
||||
conf.DefaultRuntime = config.StockRuntimeName
|
||||
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)
|
||||
}
|
||||
}
|
||||
if conf.Runtimes == nil {
|
||||
conf.Runtimes = make(map[string]types.Runtime)
|
||||
}
|
||||
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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ func (daemon *Daemon) reloadPlatform(conf *config.Config, attributes map[string]
|
|||
if runtimeList.Len() > 0 {
|
||||
runtimeList.WriteRune(' ')
|
||||
}
|
||||
runtimeList.WriteString(fmt.Sprintf("%s:%s", name, rt))
|
||||
runtimeList.WriteString(fmt.Sprintf("%s:%s", name, rt.Path))
|
||||
}
|
||||
|
||||
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 {
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
rt.Shim = getShimConfig(daemon.configStore, p)
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
||||
return opts, nil
|
||||
|
||||
}
|
||||
opts := &runctypes.RuncOptions{
|
||||
Runtime: path,
|
||||
RuntimeRoot: filepath.Join(daemon.configStore.ExecRoot,
|
||||
fmt.Sprintf("runtime-%s", 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) {
|
||||
opts.SystemdCgroup = true
|
||||
}
|
||||
|
||||
return opts, nil
|
||||
return rt.Shim.Binary, rt.Shim.Opts, nil
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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")))
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue