Browse Source

Windows: Default to Hyper-V Containers on client

Signed-off-by: John Howard <jhoward@microsoft.com>
John Howard 9 years ago
parent
commit
ef2db56bcf

+ 10 - 0
daemon/daemon_windows.go

@@ -470,6 +470,10 @@ func (daemon *Daemon) stats(c *container.Container) (*types.StatsJSON, error) {
 // daemon to run in. This is only applicable on Windows
 func (daemon *Daemon) setDefaultIsolation() error {
 	daemon.defaultIsolation = containertypes.Isolation("process")
+	// On client SKUs, default to Hyper-V
+	if system.IsWindowsClient() {
+		daemon.defaultIsolation = containertypes.Isolation("hyperv")
+	}
 	for _, option := range daemon.configStore.ExecOptions {
 		key, val, err := parsers.ParseKeyValueOpt(option)
 		if err != nil {
@@ -485,6 +489,12 @@ func (daemon *Daemon) setDefaultIsolation() error {
 			if containertypes.Isolation(val).IsHyperV() {
 				daemon.defaultIsolation = containertypes.Isolation("hyperv")
 			}
+			if containertypes.Isolation(val).IsProcess() {
+				if system.IsWindowsClient() {
+					return fmt.Errorf("Windows client operating systems only support Hyper-V containers")
+				}
+				daemon.defaultIsolation = containertypes.Isolation("process")
+			}
 		default:
 			return fmt.Errorf("Unrecognised exec-opt '%s'\n", key)
 		}

+ 2 - 1
docs/reference/commandline/create.md

@@ -164,7 +164,8 @@ Linux namespaces. On Microsoft Windows, you can specify these values:
 
 | Value     | Description                                                                                                                                                   |
 |-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `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.  |
+| `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
+daemon is running on Windows server, or `hyperv` if running on Windows client.  |
 | `process` | Namespace isolation only.                                                                                                                                     |
 | `hyperv`   | Hyper-V hypervisor partition-based isolation.                                                                                                                  |
 

+ 3 - 2
docs/reference/commandline/dockerd.md

@@ -527,8 +527,9 @@ can specify default container isolation technology with this, for example:
 
     $ dockerd --exec-opt isolation=hyperv
 
-Will make `hyperv` the default isolation technology on Windows, without specifying
-isolation value on daemon start, Windows isolation technology will default to `process`.
+Will make `hyperv` the default isolation technology on Windows. If no isolation
+value is specified on daemon start, on Windows client, the default is
+`hyperv`, and on Windows server, the default is `process`. 
 
 ## Daemon DNS options
 

+ 5 - 3
docs/reference/commandline/run.md

@@ -618,14 +618,16 @@ On Microsoft Windows, can take any of these values:
 | `process` | Namespace isolation only.                                                                                                                                     |
 | `hyperv`   | Hyper-V hypervisor partition-based isolation.                                                                                                                  |
 
-In practice, when running on Microsoft Windows without a `daemon` option set,  these two commands are equivalent:
-
+On Windows, the default isolation for client is `hyperv`, and for server is
+`process`. Therefore when running on Windows server without a `daemon` option 
+set, these two commands are equivalent:
 ```
 $ docker run -d --isolation default busybox top
 $ docker run -d --isolation process busybox top
 ```
 
-If you have set the `--exec-opt isolation=hyperv` option on the Docker `daemon`, any of these commands also result in `hyperv` isolation:
+If you have set the `--exec-opt isolation=hyperv` option on the Docker `daemon`, 
+if running on Windows server, any of these commands also result in `hyperv` isolation:
 
 ```
 $ docker run -d --isolation default busybox top

+ 3 - 1
man/docker-create.1.md

@@ -197,7 +197,9 @@ two memory nodes.
                                '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.
 
 **--isolation**="*default*"
-   Isolation specifies the type of isolation technology used by containers. 
+   Isolation specifies the type of isolation technology used by containers. Note
+that the default on Windows server is `process`, and the default on Windows client
+is `hyperv`. Linux only supports `default`.
 
 **--kernel-memory**=""
    Kernel memory limit (format: `<number>[<unit>]`, where unit = b, k, m or g)

+ 3 - 1
man/docker-run.1.md

@@ -297,7 +297,9 @@ redirection on the host system.
                                '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.
 
 **--isolation**="*default*"
-   Isolation specifies the type of isolation technology used by containers.
+   Isolation specifies the type of isolation technology used by containers. Note
+that the default on Windows server is `process`, and the default on Windows client
+is `hyperv`. Linux only supports `default`.
 
 **-l**, **--label**=[]
    Set metadata on the container (e.g., --label com.example.key=value)

+ 6 - 0
man/dockerd.8.md

@@ -39,6 +39,7 @@ dockerd - Enable daemon mode
 [**--ip-masq**[=*true*]]
 [**--iptables**[=*true*]]
 [**--ipv6**]
+[**--isolation**[=*default*]]
 [**-l**|**--log-level**[=*info*]]
 [**--label**[=*[]*]]
 [**--log-driver**[=*json-file*]]
@@ -183,6 +184,11 @@ unix://[/path/to/socket] to use.
 **--ipv6**=*true*|*false*
   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".
 
+**--isolation**="*default*"
+   Isolation specifies the type of isolation technology used by containers. Note
+that the default on Windows server is `process`, and the default on Windows client
+is `hyperv`. Linux only supports `default`.
+
 **-l**, **--log-level**="*debug*|*info*|*warn*|*error*|*fatal*"
   Set the logging level. Default is `info`.
 

+ 31 - 1
pkg/system/syscall_windows.go

@@ -3,10 +3,13 @@ package system
 import (
 	"syscall"
 	"unsafe"
+
+	"github.com/Sirupsen/logrus"
 )
 
 var (
-	ntuserApiset = syscall.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
+	ntuserApiset      = syscall.NewLazyDLL("ext-ms-win-ntuser-window-l1-1-0")
+	procGetVersionExW = modkernel32.NewProc("GetVersionExW")
 )
 
 // OSVersion is a wrapper for Windows version information
@@ -18,6 +21,21 @@ type OSVersion struct {
 	Build        uint16
 }
 
+// https://msdn.microsoft.com/en-us/library/windows/desktop/ms724833(v=vs.85).aspx
+type osVersionInfoEx struct {
+	OSVersionInfoSize uint32
+	MajorVersion      uint32
+	MinorVersion      uint32
+	BuildNumber       uint32
+	PlatformID        uint32
+	CSDVersion        [128]uint16
+	ServicePackMajor  uint16
+	ServicePackMinor  uint16
+	SuiteMask         uint16
+	ProductType       byte
+	Reserve           byte
+}
+
 // GetOSVersion gets the operating system version on Windows. Note that
 // docker.exe must be manifested to get the correct version information.
 func GetOSVersion() OSVersion {
@@ -34,6 +52,18 @@ func GetOSVersion() OSVersion {
 	return osv
 }
 
+// IsWindowsClient returns true if the SKU is client
+func IsWindowsClient() bool {
+	osviex := &osVersionInfoEx{OSVersionInfoSize: 284}
+	r1, _, err := procGetVersionExW.Call(uintptr(unsafe.Pointer(osviex)))
+	if r1 == 0 {
+		logrus.Warnf("GetVersionExW failed - assuming server SKU: %v", err)
+		return false
+	}
+	const verNTWorkstation = 0x00000001
+	return osviex.ProductType == verNTWorkstation
+}
+
 // Unmount is a platform-specific helper function to call
 // the unmount syscall. Not supported on Windows
 func Unmount(dest string) error {