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