github.com/jen20/docker@v1.13.1/daemon/oci_windows.go (about) 1 package daemon 2 3 import ( 4 "syscall" 5 6 containertypes "github.com/docker/docker/api/types/container" 7 "github.com/docker/docker/container" 8 "github.com/docker/docker/oci" 9 "github.com/docker/docker/pkg/sysinfo" 10 "github.com/opencontainers/runtime-spec/specs-go" 11 ) 12 13 func (daemon *Daemon) createSpec(c *container.Container) (*specs.Spec, error) { 14 s := oci.DefaultSpec() 15 16 linkedEnv, err := daemon.setupLinkedContainers(c) 17 if err != nil { 18 return nil, err 19 } 20 21 // Note, unlike Unix, we do NOT call into SetupWorkingDirectory as 22 // this is done in VMCompute. Further, we couldn't do it for Hyper-V 23 // containers anyway. 24 25 // In base spec 26 s.Hostname = c.FullHostname() 27 28 // In s.Mounts 29 mounts, err := daemon.setupMounts(c) 30 if err != nil { 31 return nil, err 32 } 33 for _, mount := range mounts { 34 m := specs.Mount{ 35 Source: mount.Source, 36 Destination: mount.Destination, 37 } 38 if !mount.Writable { 39 m.Options = append(m.Options, "ro") 40 } 41 s.Mounts = append(s.Mounts, m) 42 } 43 44 // In s.Process 45 s.Process.Args = append([]string{c.Path}, c.Args...) 46 if !c.Config.ArgsEscaped { 47 s.Process.Args = escapeArgs(s.Process.Args) 48 } 49 s.Process.Cwd = c.Config.WorkingDir 50 if len(s.Process.Cwd) == 0 { 51 // We default to C:\ to workaround the oddity of the case that the 52 // default directory for cmd running as LocalSystem (or 53 // ContainerAdministrator) is c:\windows\system32. Hence docker run 54 // <image> cmd will by default end in c:\windows\system32, rather 55 // than 'root' (/) on Linux. The oddity is that if you have a dockerfile 56 // which has no WORKDIR and has a COPY file ., . will be interpreted 57 // as c:\. Hence, setting it to default of c:\ makes for consistency. 58 s.Process.Cwd = `C:\` 59 } 60 s.Process.Env = c.CreateDaemonEnvironment(c.Config.Tty, linkedEnv) 61 s.Process.ConsoleSize.Height = c.HostConfig.ConsoleSize[0] 62 s.Process.ConsoleSize.Width = c.HostConfig.ConsoleSize[1] 63 s.Process.Terminal = c.Config.Tty 64 s.Process.User.Username = c.Config.User 65 66 // In spec.Root. This is not set for Hyper-V containers 67 isHyperV := false 68 if c.HostConfig.Isolation.IsDefault() { 69 // Container using default isolation, so take the default from the daemon configuration 70 isHyperV = daemon.defaultIsolation.IsHyperV() 71 } else { 72 // Container may be requesting an explicit isolation mode. 73 isHyperV = c.HostConfig.Isolation.IsHyperV() 74 } 75 if !isHyperV { 76 s.Root.Path = c.BaseFS 77 } 78 s.Root.Readonly = false // Windows does not support a read-only root filesystem 79 80 // In s.Windows.Resources 81 // @darrenstahlmsft implement these resources 82 cpuShares := uint16(c.HostConfig.CPUShares) 83 cpuPercent := uint8(c.HostConfig.CPUPercent) 84 if c.HostConfig.NanoCPUs > 0 { 85 cpuPercent = uint8(c.HostConfig.NanoCPUs * 100 / int64(sysinfo.NumCPU()) / 1e9) 86 } 87 cpuCount := uint64(c.HostConfig.CPUCount) 88 memoryLimit := uint64(c.HostConfig.Memory) 89 s.Windows.Resources = &specs.WindowsResources{ 90 CPU: &specs.WindowsCPUResources{ 91 Percent: &cpuPercent, 92 Shares: &cpuShares, 93 Count: &cpuCount, 94 }, 95 Memory: &specs.WindowsMemoryResources{ 96 Limit: &memoryLimit, 97 //TODO Reservation: ..., 98 }, 99 Network: &specs.WindowsNetworkResources{ 100 //TODO Bandwidth: ..., 101 }, 102 Storage: &specs.WindowsStorageResources{ 103 Bps: &c.HostConfig.IOMaximumBandwidth, 104 Iops: &c.HostConfig.IOMaximumIOps, 105 }, 106 } 107 return (*specs.Spec)(&s), nil 108 } 109 110 func escapeArgs(args []string) []string { 111 escapedArgs := make([]string, len(args)) 112 for i, a := range args { 113 escapedArgs[i] = syscall.EscapeArg(a) 114 } 115 return escapedArgs 116 } 117 118 // mergeUlimits merge the Ulimits from HostConfig with daemon defaults, and update HostConfig 119 // It will do nothing on non-Linux platform 120 func (daemon *Daemon) mergeUlimits(c *containertypes.HostConfig) { 121 return 122 }