oci_windows.go 3.6 KB

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