Browse code

Windows: Default to Hyper-V Containers on client

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2016/04/15 09:12:02
Showing 8 changed files
... ...
@@ -470,6 +470,10 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
470 470
 // daemon to run in. This is only applicable on Windows
471 471
 func (daemon *Daemon) setDefaultIsolation() error {
472 472
 	daemon.defaultIsolation = containertypes.Isolation("process")
473
+	// On client SKUs, default to Hyper-V
474
+	if system.IsWindowsClient() {
475
+		daemon.defaultIsolation = containertypes.Isolation("hyperv")
476
+	}
473 477
 	for _, option := range daemon.configStore.ExecOptions {
474 478
 		key, val, err := parsers.ParseKeyValueOpt(option)
475 479
 		if err != nil {
... ...
@@ -485,6 +489,12 @@ func (daemon *Daemon) setDefaultIsolation() error {
485 485
 			if containertypes.Isolation(val).IsHyperV() {
486 486
 				daemon.defaultIsolation = containertypes.Isolation("hyperv")
487 487
 			}
488
+			if containertypes.Isolation(val).IsProcess() {
489
+				if system.IsWindowsClient() {
490
+					return fmt.Errorf("Windows client operating systems only support Hyper-V containers")
491
+				}
492
+				daemon.defaultIsolation = containertypes.Isolation("process")
493
+			}
488 494
 		default:
489 495
 			return fmt.Errorf("Unrecognised exec-opt '%s'\n", key)
490 496
 		}
... ...
@@ -164,7 +164,8 @@ Linux namespaces. On Microsoft Windows, you can specify these values:
164 164
 
165 165
 | Value     | Description                                                                                                                                                   |
166 166
 |-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
167
-| `default` | Use the value specified by the Docker daemon's `--exec-opt` . If the `daemon` does not specify an isolation technology, Microsoft Windows uses `process` as its default value.  |
167
+| `default` | Use the value specified by the Docker daemon's `--exec-opt` . If the `daemon` does not specify an isolation technology, Microsoft Windows uses `process` as its default value if the
168
+daemon is running on Windows server, or `hyperv` if running on Windows client.  |
168 169
 | `process` | Namespace isolation only.                                                                                                                                     |
169 170
 | `hyperv`   | Hyper-V hypervisor partition-based isolation.                                                                                                                  |
170 171
 
... ...
@@ -527,8 +527,9 @@ can specify default container isolation technology with this, for example:
527 527
 
528 528
     $ dockerd --exec-opt isolation=hyperv
529 529
 
530
-Will make `hyperv` the default isolation technology on Windows, without specifying
531
-isolation value on daemon start, Windows isolation technology will default to `process`.
530
+Will make `hyperv` the default isolation technology on Windows. If no isolation
531
+value is specified on daemon start, on Windows client, the default is
532
+`hyperv`, and on Windows server, the default is `process`. 
532 533
 
533 534
 ## Daemon DNS options
534 535
 
... ...
@@ -618,14 +618,16 @@ On Microsoft Windows, can take any of these values:
618 618
 | `process` | Namespace isolation only.                                                                                                                                     |
619 619
 | `hyperv`   | Hyper-V hypervisor partition-based isolation.                                                                                                                  |
620 620
 
621
-In practice, when running on Microsoft Windows without a `daemon` option set,  these two commands are equivalent:
622
-
621
+On Windows, the default isolation for client is `hyperv`, and for server is
622
+`process`. Therefore when running on Windows server without a `daemon` option 
623
+set, these two commands are equivalent:
623 624
 ```
624 625
 $ docker run -d --isolation default busybox top
625 626
 $ docker run -d --isolation process busybox top
626 627
 ```
627 628
 
628
-If you have set the `--exec-opt isolation=hyperv` option on the Docker `daemon`, any of these commands also result in `hyperv` isolation:
629
+If you have set the `--exec-opt isolation=hyperv` option on the Docker `daemon`, 
630
+if running on Windows server, any of these commands also result in `hyperv` isolation:
629 631
 
630 632
 ```
631 633
 $ docker run -d --isolation default busybox top
... ...
@@ -197,7 +197,9 @@ two memory nodes.
197 197
                                'host': use the host shared memory,semaphores and message queues inside the container.  Note: the host mode gives the container full access to local shared memory and is therefore considered insecure.
198 198
 
199 199
 **--isolation**="*default*"
200
-   Isolation specifies the type of isolation technology used by containers. 
200
+   Isolation specifies the type of isolation technology used by containers. Note
201
+that the default on Windows server is `process`, and the default on Windows client
202
+is `hyperv`. Linux only supports `default`.
201 203
 
202 204
 **--kernel-memory**=""
203 205
    Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)
... ...
@@ -297,7 +297,9 @@ redirection on the host system.
297 297
                                'host': use the host shared memory,semaphores and message queues inside the container.  Note: the host mode gives the container full access to local shared memory and is therefore considered insecure.
298 298
 
299 299
 **--isolation**="*default*"
300
-   Isolation specifies the type of isolation technology used by containers.
300
+   Isolation specifies the type of isolation technology used by containers. Note
301
+that the default on Windows server is `process`, and the default on Windows client
302
+is `hyperv`. Linux only supports `default`.
301 303
 
302 304
 **-l**, **--label**=[]
303 305
    Set metadata on the container (e.g., --label com.example.key=value)
... ...
@@ -39,6 +39,7 @@ dockerd - Enable daemon mode
39 39
 [**--ip-masq**[=*true*]]
40 40
 [**--iptables**[=*true*]]
41 41
 [**--ipv6**]
42
+[**--isolation**[=*default*]]
42 43
 [**-l**|**--log-level**[=*info*]]
43 44
 [**--label**[=*[]*]]
44 45
 [**--log-driver**[=*json-file*]]
... ...
@@ -183,6 +184,11 @@ unix://[/path/to/socket] to use.
183 183
 **--ipv6**=*true*|*false*
184 184
   Enable IPv6 support. Default is false. Docker will create an IPv6-enabled bridge with address fe80::1 which will allow you to create IPv6-enabled containers. Use together with `--fixed-cidr-v6` to provide globally routable IPv6 addresses. IPv6 forwarding will be enabled if not used with `--ip-forward=false`. This may collide with your host's current IPv6 settings. For more information please consult the documentation about "Advanced Networking - IPv6".
185 185
 
186
+**--isolation**="*default*"
187
+   Isolation specifies the type of isolation technology used by containers. Note
188
+that the default on Windows server is `process`, and the default on Windows client
189
+is `hyperv`. Linux only supports `default`.
190
+
186 191
 **-l**, **--log-level**="*debug*|*info*|*warn*|*error*|*fatal*"
187 192
   Set the logging level. Default is `info`.
188 193
 
... ...
@@ -3,10 +3,13 @@ package system
3 3
 import (
4 4
 	"syscall"
5 5
 	"unsafe"
6
+
7
+	"github.com/Sirupsen/logrus"
6 8
 )
7 9
 
8 10
 var (
9
-	ntuserApiset = syscall.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
11
+	ntuserApiset      = syscall.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
12
+	procGetVersionExW = modkernel32.NewProc("GetVersionExW")
10 13
 )
11 14
 
12 15
 // OSVersion is a wrapper for Windows version information
... ...
@@ -18,6 +21,21 @@ type OSVersion struct {
18 18
 	Build        uint16
19 19
 }
20 20
 
21
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
22
+type osVersionInfoEx struct {
23
+	OSVersionInfoSize uint32
24
+	MajorVersion      uint32
25
+	MinorVersion      uint32
26
+	BuildNumber       uint32
27
+	PlatformID        uint32
28
+	CSDVersion        [128]uint16
29
+	ServicePackMajor  uint16
30
+	ServicePackMinor  uint16
31
+	SuiteMask         uint16
32
+	ProductType       byte
33
+	Reserve           byte
34
+}
35
+
21 36
 // GetOSVersion gets the operating system version on Windows. Note that
22 37
 // docker.exe must be manifested to get the correct version information.
23 38
 func GetOSVersion() OSVersion {
... ...
@@ -34,6 +52,18 @@ func GetOSVersion() OSVersion {
34 34
 	return osv
35 35
 }
36 36
 
37
+// IsWindowsClient returns true if the SKU is client
38
+func IsWindowsClient() bool {
39
+	osviex := &osVersionInfoEx{OSVersionInfoSize: 284}
40
+	r1, _, err := procGetVersionExW.Call(uintptr(unsafe.Pointer(osviex)))
41
+	if r1 == 0 {
42
+		logrus.Warnf("GetVersionExW failed - assuming server SKU: %v", err)
43
+		return false
44
+	}
45
+	const verNTWorkstation = 0x00000001
46
+	return osviex.ProductType == verNTWorkstation
47
+}
48
+
37 49
 // Unmount is a platform-specific helper function to call
38 50
 // the unmount syscall. Not supported on Windows
39 51
 func Unmount(dest string) error {