github.com/rish1988/moby@v25.0.2+incompatible/plugin/v2/plugin_linux.go (about) 1 package v2 // import "github.com/docker/docker/plugin/v2" 2 3 import ( 4 "os" 5 "path/filepath" 6 "runtime" 7 "strings" 8 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/oci" 11 specs "github.com/opencontainers/runtime-spec/specs-go" 12 "github.com/pkg/errors" 13 ) 14 15 // InitSpec creates an OCI spec from the plugin's config. 16 func (p *Plugin) InitSpec(execRoot string) (*specs.Spec, error) { 17 s := oci.DefaultSpec() 18 19 s.Root = &specs.Root{ 20 Path: p.Rootfs, 21 Readonly: false, // TODO: all plugins should be readonly? settable in config? 22 } 23 24 userMounts := make(map[string]struct{}, len(p.PluginObj.Settings.Mounts)) 25 for _, m := range p.PluginObj.Settings.Mounts { 26 userMounts[m.Destination] = struct{}{} 27 } 28 29 execRoot = filepath.Join(execRoot, p.PluginObj.ID) 30 if err := os.MkdirAll(execRoot, 0o700); err != nil { 31 return nil, errors.WithStack(err) 32 } 33 34 if p.PluginObj.Config.PropagatedMount != "" { 35 pRoot := filepath.Join(filepath.Dir(p.Rootfs), "propagated-mount") 36 s.Mounts = append(s.Mounts, specs.Mount{ 37 Source: pRoot, 38 Destination: p.PluginObj.Config.PropagatedMount, 39 Type: "bind", 40 Options: []string{"rbind", "rw", "rshared"}, 41 }) 42 s.Linux.RootfsPropagation = "rshared" 43 } 44 45 mounts := append(p.PluginObj.Config.Mounts, types.PluginMount{ 46 Source: &execRoot, 47 Destination: defaultPluginRuntimeDestination, 48 Type: "bind", 49 Options: []string{"rbind", "rshared"}, 50 }) 51 52 if p.PluginObj.Config.Network.Type != "" { 53 // TODO: if net == bridge, use libnetwork controller to create a new plugin-specific bridge, bind mount /etc/hosts and /etc/resolv.conf look at the docker code (allocateNetwork, initialize) 54 if p.PluginObj.Config.Network.Type == "host" { 55 oci.RemoveNamespace(&s, specs.LinuxNamespaceType("network")) 56 } 57 etcHosts := "/etc/hosts" 58 resolvConf := "/etc/resolv.conf" 59 mounts = append(mounts, 60 types.PluginMount{ 61 Source: &etcHosts, 62 Destination: etcHosts, 63 Type: "bind", 64 Options: []string{"rbind", "ro"}, 65 }, 66 types.PluginMount{ 67 Source: &resolvConf, 68 Destination: resolvConf, 69 Type: "bind", 70 Options: []string{"rbind", "ro"}, 71 }) 72 } 73 if p.PluginObj.Config.PidHost { 74 oci.RemoveNamespace(&s, specs.LinuxNamespaceType("pid")) 75 } 76 77 if p.PluginObj.Config.IpcHost { 78 oci.RemoveNamespace(&s, specs.LinuxNamespaceType("ipc")) 79 } 80 81 for _, mnt := range mounts { 82 m := specs.Mount{ 83 Destination: mnt.Destination, 84 Type: mnt.Type, 85 Options: mnt.Options, 86 } 87 if mnt.Source == nil { 88 return nil, errors.New("mount source is not specified") 89 } 90 m.Source = *mnt.Source 91 s.Mounts = append(s.Mounts, m) 92 } 93 94 for i, m := range s.Mounts { 95 if strings.HasPrefix(m.Destination, "/dev/") { 96 if _, ok := userMounts[m.Destination]; ok { 97 s.Mounts = append(s.Mounts[:i], s.Mounts[i+1:]...) 98 } 99 } 100 } 101 102 if p.PluginObj.Config.Linux.AllowAllDevices { 103 s.Linux.Resources.Devices = []specs.LinuxDeviceCgroup{{Allow: true, Access: "rwm"}} 104 } 105 for _, dev := range p.PluginObj.Settings.Devices { 106 path := *dev.Path 107 d, dPermissions, err := oci.DevicesFromPath(path, path, "rwm") 108 if err != nil { 109 return nil, errors.WithStack(err) 110 } 111 s.Linux.Devices = append(s.Linux.Devices, d...) 112 s.Linux.Resources.Devices = append(s.Linux.Resources.Devices, dPermissions...) 113 } 114 115 envs := make([]string, 1, len(p.PluginObj.Settings.Env)+1) 116 envs[0] = "PATH=" + oci.DefaultPathEnv(runtime.GOOS) 117 envs = append(envs, p.PluginObj.Settings.Env...) 118 119 args := append(p.PluginObj.Config.Entrypoint, p.PluginObj.Settings.Args...) 120 cwd := p.PluginObj.Config.WorkDir 121 if len(cwd) == 0 { 122 cwd = "/" 123 } 124 s.Process.Terminal = false 125 s.Process.Args = args 126 s.Process.Cwd = cwd 127 s.Process.Env = envs 128 129 caps := s.Process.Capabilities 130 caps.Bounding = append(caps.Bounding, p.PluginObj.Config.Linux.Capabilities...) 131 caps.Permitted = append(caps.Permitted, p.PluginObj.Config.Linux.Capabilities...) 132 caps.Inheritable = append(caps.Inheritable, p.PluginObj.Config.Linux.Capabilities...) 133 caps.Effective = append(caps.Effective, p.PluginObj.Config.Linux.Capabilities...) 134 135 if p.modifyRuntimeSpec != nil { 136 p.modifyRuntimeSpec(&s) 137 } 138 139 return &s, nil 140 }