oci_windows.go 3.7 KB

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