github.com/rumpl/bof@v23.0.0-rc.2+incompatible/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  	// Remove old temp directory if any
    57  	os.RemoveAll(runtimeDir + "-old")
    58  	tmpDir, err := os.MkdirTemp(daemon.configStore.Root, "gen-runtimes")
    59  	if err != nil {
    60  		return errors.Wrap(err, "failed to get temp dir to generate runtime scripts")
    61  	}
    62  	defer func() {
    63  		if err != nil {
    64  			if err1 := os.RemoveAll(tmpDir); err1 != nil {
    65  				logrus.WithError(err1).WithField("dir", tmpDir).
    66  					Warn("failed to remove tmp dir")
    67  			}
    68  			return
    69  		}
    70  
    71  		if err = os.Rename(runtimeDir, runtimeDir+"-old"); err != nil {
    72  			return
    73  		}
    74  		if err = os.Rename(tmpDir, runtimeDir); err != nil {
    75  			err = errors.Wrap(err, "failed to setup runtimes dir, new containers may not start")
    76  			return
    77  		}
    78  		if err = os.RemoveAll(runtimeDir + "-old"); err != nil {
    79  			logrus.WithError(err).WithField("dir", tmpDir).
    80  				Warn("failed to remove old runtimes dir")
    81  		}
    82  	}()
    83  
    84  	for name, rt := range runtimes {
    85  		if len(rt.Args) > 0 {
    86  			script := filepath.Join(tmpDir, name)
    87  			content := fmt.Sprintf("#!/bin/sh\n%s %s $@\n", rt.Path, strings.Join(rt.Args, " "))
    88  			if err := os.WriteFile(script, []byte(content), 0700); err != nil {
    89  				return err
    90  			}
    91  		}
    92  		if rt.Shim == nil {
    93  			rt.Shim = defaultV2ShimConfig(daemon.configStore, rt.Path)
    94  		}
    95  	}
    96  	return nil
    97  }
    98  
    99  // rewriteRuntimePath is used for runtimes which have custom arguments supplied.
   100  // This is needed because the containerd API only calls the OCI runtime binary, there is no options for extra arguments.
   101  // To support this case, the daemon wraps the specified runtime in a script that passes through those arguments.
   102  func (daemon *Daemon) rewriteRuntimePath(name, p string, args []string) (string, error) {
   103  	if len(args) == 0 {
   104  		return p, nil
   105  	}
   106  
   107  	// Check that the runtime path actually exists here so that we can return a well known error.
   108  	if _, err := exec.LookPath(p); err != nil {
   109  		return "", errors.Wrap(err, "error while looking up the specified runtime path")
   110  	}
   111  
   112  	return filepath.Join(daemon.configStore.Root, "runtimes", name), nil
   113  }
   114  
   115  func (daemon *Daemon) getRuntime(name string) (*types.Runtime, error) {
   116  	rt := daemon.configStore.GetRuntime(name)
   117  	if rt == nil {
   118  		if !config.IsPermissibleC8dRuntimeName(name) {
   119  			return nil, errdefs.InvalidParameter(errors.Errorf("unknown or invalid runtime name: %s", name))
   120  		}
   121  		return &types.Runtime{Shim: &types.ShimConfig{Binary: name}}, nil
   122  	}
   123  
   124  	if len(rt.Args) > 0 {
   125  		p, err := daemon.rewriteRuntimePath(name, rt.Path, rt.Args)
   126  		if err != nil {
   127  			return nil, err
   128  		}
   129  		rt.Path = p
   130  		rt.Args = nil
   131  	}
   132  
   133  	if rt.Shim == nil {
   134  		rt.Shim = defaultV2ShimConfig(daemon.configStore, rt.Path)
   135  	}
   136  
   137  	return rt, nil
   138  }