container_windows.go 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. // +build windows
  2. package container
  3. import (
  4. "fmt"
  5. "os"
  6. "path/filepath"
  7. containertypes "github.com/docker/docker/api/types/container"
  8. "github.com/docker/docker/pkg/system"
  9. )
  10. const (
  11. containerSecretMountPath = `C:\ProgramData\Docker\secrets`
  12. containerInternalSecretMountPath = `C:\ProgramData\Docker\internal\secrets`
  13. containerInternalConfigsDirPath = `C:\ProgramData\Docker\internal\configs`
  14. )
  15. // Container holds fields specific to the Windows implementation. See
  16. // CommonContainer for standard fields common to all containers.
  17. type Container struct {
  18. CommonContainer
  19. // Fields below here are platform specific.
  20. NetworkSharedContainerID string
  21. }
  22. // ExitStatus provides exit reasons for a container.
  23. type ExitStatus struct {
  24. // The exit code with which the container exited.
  25. ExitCode int
  26. }
  27. // CreateDaemonEnvironment creates a new environment variable slice for this container.
  28. func (container *Container) CreateDaemonEnvironment(_ bool, linkedEnv []string) []string {
  29. // because the env on the container can override certain default values
  30. // we need to replace the 'env' keys where they match and append anything
  31. // else.
  32. return ReplaceOrAppendEnvValues(linkedEnv, container.Config.Env)
  33. }
  34. // UnmountIpcMounts unmounts Ipc related mounts.
  35. // This is a NOOP on windows.
  36. func (container *Container) UnmountIpcMounts(unmount func(pth string) error) {
  37. }
  38. // IpcMounts returns the list of Ipc related mounts.
  39. func (container *Container) IpcMounts() []Mount {
  40. return nil
  41. }
  42. // CreateSecretSymlinks creates symlinks to files in the secret mount.
  43. func (container *Container) CreateSecretSymlinks() error {
  44. for _, r := range container.SecretReferences {
  45. if r.File == nil {
  46. continue
  47. }
  48. resolvedPath, _, err := container.ResolvePath(getSecretTargetPath(r))
  49. if err != nil {
  50. return err
  51. }
  52. if err := system.MkdirAll(filepath.Dir(resolvedPath), 0); err != nil {
  53. return err
  54. }
  55. if err := os.Symlink(filepath.Join(containerInternalSecretMountPath, r.SecretID), resolvedPath); err != nil {
  56. return err
  57. }
  58. }
  59. return nil
  60. }
  61. // SecretMounts returns the mount for the secret path.
  62. // All secrets are stored in a single mount on Windows. Target symlinks are
  63. // created for each secret, pointing to the files in this mount.
  64. func (container *Container) SecretMounts() []Mount {
  65. var mounts []Mount
  66. if len(container.SecretReferences) > 0 {
  67. mounts = append(mounts, Mount{
  68. Source: container.SecretMountPath(),
  69. Destination: containerInternalSecretMountPath,
  70. Writable: false,
  71. })
  72. }
  73. return mounts
  74. }
  75. // UnmountSecrets unmounts the fs for secrets
  76. func (container *Container) UnmountSecrets() error {
  77. return os.RemoveAll(container.SecretMountPath())
  78. }
  79. // CreateConfigSymlinks creates symlinks to files in the config mount.
  80. func (container *Container) CreateConfigSymlinks() error {
  81. for _, configRef := range container.ConfigReferences {
  82. if configRef.File == nil {
  83. continue
  84. }
  85. resolvedPath, _, err := container.ResolvePath(configRef.File.Name)
  86. if err != nil {
  87. return err
  88. }
  89. if err := system.MkdirAll(filepath.Dir(resolvedPath), 0); err != nil {
  90. return err
  91. }
  92. if err := os.Symlink(filepath.Join(containerInternalConfigsDirPath, configRef.ConfigID), resolvedPath); err != nil {
  93. return err
  94. }
  95. }
  96. return nil
  97. }
  98. // ConfigMounts returns the mount for configs.
  99. // All configs are stored in a single mount on Windows. Target symlinks are
  100. // created for each config, pointing to the files in this mount.
  101. func (container *Container) ConfigMounts() []Mount {
  102. var mounts []Mount
  103. if len(container.ConfigReferences) > 0 {
  104. mounts = append(mounts, Mount{
  105. Source: container.ConfigsDirPath(),
  106. Destination: containerInternalConfigsDirPath,
  107. Writable: false,
  108. })
  109. }
  110. return mounts
  111. }
  112. // DetachAndUnmount unmounts all volumes.
  113. // On Windows it only delegates to `UnmountVolumes` since there is nothing to
  114. // force unmount.
  115. func (container *Container) DetachAndUnmount(volumeEventLog func(name, action string, attributes map[string]string)) error {
  116. return container.UnmountVolumes(volumeEventLog)
  117. }
  118. // TmpfsMounts returns the list of tmpfs mounts
  119. func (container *Container) TmpfsMounts() ([]Mount, error) {
  120. var mounts []Mount
  121. return mounts, nil
  122. }
  123. // UpdateContainer updates configuration of a container
  124. func (container *Container) UpdateContainer(hostConfig *containertypes.HostConfig) error {
  125. container.Lock()
  126. defer container.Unlock()
  127. resources := hostConfig.Resources
  128. if resources.CPUShares != 0 ||
  129. resources.Memory != 0 ||
  130. resources.NanoCPUs != 0 ||
  131. resources.CgroupParent != "" ||
  132. resources.BlkioWeight != 0 ||
  133. len(resources.BlkioWeightDevice) != 0 ||
  134. len(resources.BlkioDeviceReadBps) != 0 ||
  135. len(resources.BlkioDeviceWriteBps) != 0 ||
  136. len(resources.BlkioDeviceReadIOps) != 0 ||
  137. len(resources.BlkioDeviceWriteIOps) != 0 ||
  138. resources.CPUPeriod != 0 ||
  139. resources.CPUQuota != 0 ||
  140. resources.CPURealtimePeriod != 0 ||
  141. resources.CPURealtimeRuntime != 0 ||
  142. resources.CpusetCpus != "" ||
  143. resources.CpusetMems != "" ||
  144. len(resources.Devices) != 0 ||
  145. len(resources.DeviceCgroupRules) != 0 ||
  146. resources.DiskQuota != 0 ||
  147. resources.KernelMemory != 0 ||
  148. resources.MemoryReservation != 0 ||
  149. resources.MemorySwap != 0 ||
  150. resources.MemorySwappiness != nil ||
  151. resources.OomKillDisable != nil ||
  152. resources.PidsLimit != 0 ||
  153. len(resources.Ulimits) != 0 ||
  154. resources.CPUCount != 0 ||
  155. resources.CPUPercent != 0 ||
  156. resources.IOMaximumIOps != 0 ||
  157. resources.IOMaximumBandwidth != 0 {
  158. return fmt.Errorf("resource updating isn't supported on Windows")
  159. }
  160. // update HostConfig of container
  161. if hostConfig.RestartPolicy.Name != "" {
  162. if container.HostConfig.AutoRemove && !hostConfig.RestartPolicy.IsNone() {
  163. return fmt.Errorf("Restart policy cannot be updated because AutoRemove is enabled for the container")
  164. }
  165. container.HostConfig.RestartPolicy = hostConfig.RestartPolicy
  166. }
  167. return nil
  168. }
  169. // cleanResourcePath cleans a resource path by removing C:\ syntax, and prepares
  170. // to combine with a volume path
  171. func cleanResourcePath(path string) string {
  172. if len(path) >= 2 {
  173. c := path[0]
  174. if path[1] == ':' && ('a' <= c && c <= 'z' || 'A' <= c && c <= 'Z') {
  175. path = path[2:]
  176. }
  177. }
  178. return filepath.Join(string(os.PathSeparator), path)
  179. }
  180. // BuildHostnameFile writes the container's hostname file.
  181. func (container *Container) BuildHostnameFile() error {
  182. return nil
  183. }
  184. // EnableServiceDiscoveryOnDefaultNetwork Enable service discovery on default network
  185. func (container *Container) EnableServiceDiscoveryOnDefaultNetwork() bool {
  186. return true
  187. }