Sets the Windows-specific fields of the OCI spec
(c *container.Container, s *specs.Spec, isHyperV bool)
| 224 | |
| 225 | // Sets the Windows-specific fields of the OCI spec |
| 226 | func (daemon *Daemon) createSpecWindowsFields(c *container.Container, s *specs.Spec, isHyperV bool) error { |
| 227 | s.Hostname = c.FullHostname() |
| 228 | |
| 229 | if len(s.Process.Cwd) == 0 { |
| 230 | // We default to C:\ to workaround the oddity of the case that the |
| 231 | // default directory for cmd running as LocalSystem (or |
| 232 | // ContainerAdministrator) is c:\windows\system32. Hence docker run |
| 233 | // <image> cmd will by default end in c:\windows\system32, rather |
| 234 | // than 'root' (/) on Linux. The oddity is that if you have a dockerfile |
| 235 | // which has no WORKDIR and has a COPY file ., . will be interpreted |
| 236 | // as c:\. Hence, setting it to default of c:\ makes for consistency. |
| 237 | s.Process.Cwd = `C:\` |
| 238 | } |
| 239 | |
| 240 | if c.Config.ArgsEscaped { |
| 241 | s.Process.CommandLine = c.Path |
| 242 | if len(c.Args) > 0 { |
| 243 | s.Process.CommandLine += " " + escapeArgs(c.Args) |
| 244 | } |
| 245 | } else { |
| 246 | s.Process.Args = append([]string{c.Path}, c.Args...) |
| 247 | } |
| 248 | s.Root.Readonly = false // Windows does not support a read-only root filesystem |
| 249 | if !isHyperV { |
| 250 | if c.BaseFS == "" { |
| 251 | return errors.New("createSpecWindowsFields: BaseFS of container " + c.ID + " is unexpectedly empty") |
| 252 | } |
| 253 | |
| 254 | if daemon.UsesSnapshotter() { |
| 255 | // daemon.Mount() for the snapshotters actually mounts the filesystem to the host |
| 256 | // using containerd/mount.All and BaseFS is the directory where this is mounted. |
| 257 | // This is consistent with Linux-based graphdriver implementations. |
| 258 | // For the windowsfilter graphdriver, the underlying Get() call does not actually mount |
| 259 | // the filesystem to a path, and BaseFS is the Volume GUID of the prepared/activated |
| 260 | // filesystem. |
| 261 | |
| 262 | // The spec for Root.Path for Windows specifies that for Process-isolated containers, |
| 263 | // it must be in the Volume GUID (\\?\\Volume{GUID} style), not a host-mounted directory. |
| 264 | backingDevicePath, err := getBackingDeviceForContainerdMount(c.BaseFS) |
| 265 | if err != nil { |
| 266 | return errors.Wrapf(err, "createSpecWindowsFields: Failed to get backing device of BaseFS of container %s", c.ID) |
| 267 | } |
| 268 | s.Root.Path = backingDevicePath |
| 269 | } else { |
| 270 | s.Root.Path = c.BaseFS // This is not set for Hyper-V containers |
| 271 | } |
| 272 | if !strings.HasSuffix(s.Root.Path, `\`) { |
| 273 | s.Root.Path = s.Root.Path + `\` // Ensure a correctly formatted volume GUID path \\?\Volume{GUID}\ |
| 274 | } |
| 275 | } |
| 276 | |
| 277 | // First boot optimization |
| 278 | s.Windows.IgnoreFlushesDuringBoot = !c.HasBeenStartedBefore |
| 279 | |
| 280 | setResourcesInSpec(c, s, isHyperV) |
| 281 | |
| 282 | // Read and add credentials from the security options if a credential spec has been provided. |
| 283 | if err := daemon.setWindowsCredentialSpec(c, s); err != nil { |
no test coverage detected