ab35df454d
Removed pre-go1.17 build-tags with go fix; go mod init go fix -mod=readonly ./... rm go.mod Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
169 lines
5.6 KiB
Go
169 lines
5.6 KiB
Go
//go:build !windows
|
|
|
|
package daemon
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
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/errdefs"
|
|
"github.com/docker/docker/libcontainerd/shimopts"
|
|
"github.com/pkg/errors"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
const (
|
|
defaultRuntimeName = "runc"
|
|
|
|
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.LinuxV2RuntimeName] = types.Runtime{Path: defaultRuntimeName, ShimConfig: defaultV2ShimConfig(conf, defaultRuntimeName)}
|
|
conf.Runtimes[config.StockRuntimeName] = conf.Runtimes[config.LinuxV2RuntimeName]
|
|
}
|
|
|
|
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 (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")
|
|
runtimeOldDir := runtimeDir + "-old"
|
|
// Remove old temp directory if any
|
|
os.RemoveAll(runtimeOldDir)
|
|
tmpDir, err := os.MkdirTemp(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, runtimeOldDir); err != nil {
|
|
logrus.WithError(err).WithField("dir", runtimeDir).
|
|
Warn("failed to rename runtimes dir to old. Will try to removing it")
|
|
if err = os.RemoveAll(runtimeDir); err != nil {
|
|
logrus.WithError(err).WithField("dir", runtimeDir).
|
|
Warn("failed to remove old runtimes dir")
|
|
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(runtimeOldDir); err != nil {
|
|
logrus.WithError(err).WithField("dir", runtimeOldDir).
|
|
Warn("failed to remove old runtimes dir")
|
|
}
|
|
}()
|
|
|
|
for name := range runtimes {
|
|
rt := runtimes[name]
|
|
if rt.Path == "" && rt.Type == "" {
|
|
return errors.Errorf("runtime %s: either a runtimeType or a path must be configured", name)
|
|
}
|
|
if rt.Path != "" {
|
|
if rt.Type != "" {
|
|
return errors.Errorf("runtime %s: cannot configure both path and runtimeType for the same runtime", name)
|
|
}
|
|
if len(rt.Options) > 0 {
|
|
return errors.Errorf("runtime %s: options cannot be used with a path runtime", name)
|
|
}
|
|
|
|
if len(rt.Args) > 0 {
|
|
script := filepath.Join(tmpDir, name)
|
|
content := fmt.Sprintf("#!/bin/sh\n%s %s $@\n", rt.Path, strings.Join(rt.Args, " "))
|
|
if err := os.WriteFile(script, []byte(content), 0700); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
rt.ShimConfig = defaultV2ShimConfig(daemon.configStore, daemon.rewriteRuntimePath(name, rt.Path, rt.Args))
|
|
} else {
|
|
if len(rt.Args) > 0 {
|
|
return errors.Errorf("runtime %s: args cannot be used with a runtimeType runtime", name)
|
|
}
|
|
// Unlike implicit runtimes, there is no restriction on configuring a shim by path.
|
|
rt.ShimConfig = &types.ShimConfig{Binary: rt.Type}
|
|
if len(rt.Options) > 0 {
|
|
// It has to be a pointer type or there'll be a panic in containerd/typeurl when we try to start the container.
|
|
rt.ShimConfig.Opts, err = shimopts.Generate(rt.Type, rt.Options)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "runtime %v", name)
|
|
}
|
|
}
|
|
}
|
|
runtimes[name] = rt
|
|
}
|
|
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 {
|
|
if len(args) == 0 {
|
|
return p
|
|
}
|
|
|
|
return filepath.Join(daemon.configStore.Root, "runtimes", name)
|
|
}
|
|
|
|
func (daemon *Daemon) getRuntime(name string) (shim string, opts interface{}, err error) {
|
|
rt := daemon.configStore.GetRuntime(name)
|
|
if rt == nil {
|
|
if !config.IsPermissibleC8dRuntimeName(name) {
|
|
return "", nil, errdefs.InvalidParameter(errors.Errorf("unknown or invalid runtime name: %s", name))
|
|
}
|
|
return name, nil, nil
|
|
}
|
|
|
|
if len(rt.Args) > 0 {
|
|
// Check that the path of the runtime which the script wraps actually exists so
|
|
// that we can return a well known error which references the configured path
|
|
// instead of the wrapper script's.
|
|
if _, err := exec.LookPath(rt.Path); err != nil {
|
|
return "", nil, errors.Wrap(err, "error while looking up the specified runtime path")
|
|
}
|
|
}
|
|
|
|
if rt.ShimConfig == nil {
|
|
// Should never happen as daemon.initRuntimes always sets
|
|
// ShimConfig and config reloading is synchronized.
|
|
err := errdefs.System(errors.Errorf("BUG: runtime %s: rt.ShimConfig == nil", name))
|
|
logrus.Error(err)
|
|
return "", nil, err
|
|
}
|
|
|
|
return rt.ShimConfig.Binary, rt.ShimConfig.Opts, nil
|
|
}
|