gopkg.in/docker/docker.v23@v23.0.11/daemon/runtime_unix.go (about) 1 //go:build !windows 2 // +build !windows 3 4 package daemon 5 6 import ( 7 "fmt" 8 "os" 9 "os/exec" 10 "path/filepath" 11 "strings" 12 13 v2runcoptions "github.com/containerd/containerd/runtime/v2/runc/options" 14 "github.com/docker/docker/api/types" 15 "github.com/docker/docker/daemon/config" 16 "github.com/docker/docker/errdefs" 17 "github.com/pkg/errors" 18 "github.com/sirupsen/logrus" 19 ) 20 21 const ( 22 defaultRuntimeName = "runc" 23 24 linuxShimV2 = "io.containerd.runc.v2" 25 ) 26 27 func configureRuntimes(conf *config.Config) { 28 if conf.DefaultRuntime == "" { 29 conf.DefaultRuntime = config.StockRuntimeName 30 } 31 if conf.Runtimes == nil { 32 conf.Runtimes = make(map[string]types.Runtime) 33 } 34 conf.Runtimes[config.LinuxV2RuntimeName] = types.Runtime{Path: defaultRuntimeName, Shim: defaultV2ShimConfig(conf, defaultRuntimeName)} 35 conf.Runtimes[config.StockRuntimeName] = conf.Runtimes[config.LinuxV2RuntimeName] 36 } 37 38 func defaultV2ShimConfig(conf *config.Config, runtimePath string) *types.ShimConfig { 39 return &types.ShimConfig{ 40 Binary: linuxShimV2, 41 Opts: &v2runcoptions.Options{ 42 BinaryName: runtimePath, 43 Root: filepath.Join(conf.ExecRoot, "runtime-"+defaultRuntimeName), 44 SystemdCgroup: UsingSystemd(conf), 45 NoPivotRoot: os.Getenv("DOCKER_RAMDISK") != "", 46 }, 47 } 48 } 49 50 func (daemon *Daemon) loadRuntimes() error { 51 return daemon.initRuntimes(daemon.configStore.Runtimes) 52 } 53 54 func (daemon *Daemon) initRuntimes(runtimes map[string]types.Runtime) (err error) { 55 runtimeDir := filepath.Join(daemon.configStore.Root, "runtimes") 56 runtimeOldDir := runtimeDir + "-old" 57 // Remove old temp directory if any 58 os.RemoveAll(runtimeOldDir) 59 tmpDir, err := os.MkdirTemp(daemon.configStore.Root, "gen-runtimes") 60 if err != nil { 61 return errors.Wrap(err, "failed to get temp dir to generate runtime scripts") 62 } 63 defer func() { 64 if err != nil { 65 if err1 := os.RemoveAll(tmpDir); err1 != nil { 66 logrus.WithError(err1).WithField("dir", tmpDir). 67 Warn("failed to remove tmp dir") 68 } 69 return 70 } 71 72 if err = os.Rename(runtimeDir, runtimeOldDir); err != nil { 73 logrus.WithError(err).WithField("dir", runtimeDir). 74 Warn("failed to rename runtimes dir to old. Will try to removing it") 75 if err = os.RemoveAll(runtimeDir); err != nil { 76 logrus.WithError(err).WithField("dir", runtimeDir). 77 Warn("failed to remove old runtimes dir") 78 return 79 } 80 } 81 if err = os.Rename(tmpDir, runtimeDir); err != nil { 82 err = errors.Wrap(err, "failed to setup runtimes dir, new containers may not start") 83 return 84 } 85 if err = os.RemoveAll(runtimeOldDir); err != nil { 86 logrus.WithError(err).WithField("dir", runtimeOldDir). 87 Warn("failed to remove old runtimes dir") 88 } 89 }() 90 91 for name, rt := range runtimes { 92 if len(rt.Args) > 0 { 93 script := filepath.Join(tmpDir, name) 94 content := fmt.Sprintf("#!/bin/sh\n%s %s $@\n", rt.Path, strings.Join(rt.Args, " ")) 95 if err := os.WriteFile(script, []byte(content), 0700); err != nil { 96 return err 97 } 98 } 99 if rt.Shim == nil { 100 rt.Shim = defaultV2ShimConfig(daemon.configStore, rt.Path) 101 } 102 } 103 return nil 104 } 105 106 // rewriteRuntimePath is used for runtimes which have custom arguments supplied. 107 // This is needed because the containerd API only calls the OCI runtime binary, there is no options for extra arguments. 108 // To support this case, the daemon wraps the specified runtime in a script that passes through those arguments. 109 func (daemon *Daemon) rewriteRuntimePath(name, p string, args []string) (string, error) { 110 if len(args) == 0 { 111 return p, nil 112 } 113 114 // Check that the runtime path actually exists here so that we can return a well known error. 115 if _, err := exec.LookPath(p); err != nil { 116 return "", errors.Wrap(err, "error while looking up the specified runtime path") 117 } 118 119 return filepath.Join(daemon.configStore.Root, "runtimes", name), nil 120 } 121 122 func (daemon *Daemon) getRuntime(name string) (*types.Runtime, error) { 123 rt := daemon.configStore.GetRuntime(name) 124 if rt == nil { 125 if !config.IsPermissibleC8dRuntimeName(name) { 126 return nil, errdefs.InvalidParameter(errors.Errorf("unknown or invalid runtime name: %s", name)) 127 } 128 return &types.Runtime{Shim: &types.ShimConfig{Binary: name}}, nil 129 } 130 131 if len(rt.Args) > 0 { 132 p, err := daemon.rewriteRuntimePath(name, rt.Path, rt.Args) 133 if err != nil { 134 return nil, err 135 } 136 rt.Path = p 137 rt.Args = nil 138 } 139 140 if rt.Shim == nil { 141 rt.Shim = defaultV2ShimConfig(daemon.configStore, rt.Path) 142 } 143 144 return rt, nil 145 }