Docker Swarm on Windows Server. Before you get lost!
As a beginner I thought the concept behind docker is similar to the concept behind Java, where you build once and deploy anywhere. For Java this capability is achieved through JVM (Java Virtual Machine). We need to install the corresponding compatible JVM for our Operating System. This JVM provides the isolation layer for Java programs to run on any platform (i.e on any OS). However, docker does not provide such isolation for docker containers. Windows based containers should run on Windows hosts, Linux based containers should run on Linux hosts.
Windows have introduced Hyper-V isolation to run Linux containers on Windows. However, this is again similar to Windows running a Linux VM and on top of that run Linux docker containers. At the time of writing this is experimental and does not support on Windows Server because it is not recommended in production deployments.
The topic today is not docker, it is docker swarm (cluster of nodes on which a set of docker-services (docker-service => one or more containers from the same image) can be deployed). What I wanted to highlight in the above was;
- You need to have compatible docker images to your Windows OS version of your swarm nodes.
- Docker images compatible with Windows Server 2016 will not be compatible with Windows Server 2019 and vice-versa.
- If you need to deploy both Linux and Windows containers in the swarm then have both Linux and Windows nodes and utilize placement constraints to guide the deployment correctly.
Note: Windows Server 2016 is not that docker swarm friendly because it does not support many beneficial docker swarm features. Thus, I highly recommend going with Windows Server 2019 latest version.
Windows Server 2016
There are several things that you need to know if you want to have a docker swarm with Windows Server 2016 nodes. First you need to know what is not supported in Windows Server 2016 and what are the remedies to them.
Before moving on let’s see what are the Windows Server 2016 versions that are available;
- version 1607 (One and only version with GUI option)
- version 1709 (Server core mode only. No GUI option)
- version 1803 (Server core mode only. No GUI option)
1. For version 1607 the routing mesh is not supported
The approach that works on this version is to publish the ports in host mode. Each host publishes the port directly, and maps it to the container. If we use a defined port on the host, then we can only have one container per host.
Instead of defining the number of replicas we need to specify --mode global
, so that one container is created on each node. The command to create the service this way is:
docker service create --name web --mode global --publish mode=host,published=80,target=80 microsoft/iis
If we use a dynamic port on the host, then we can have more than one, but we have to discover the port to connect to. The command to create the service this way is:
docker service create --name web --replicas 2 --publish mode=host,target=80 microsoft/iis
2. For version 1709 and beyond routing mesh is supported
3. Docker network endpoint VIP is not supported in windows server 2016
Microsoft document https://docs.microsoft.com/en-us/virtualization/windowscontainers/manage-containers/swarm-mode helps to get a better understanding of this issue.
That is endpoint-mode ‘vip’ is not supported in Windows Server 2016. This is the default endpoint-mode. So we need to explicitly give the endpoint-mode as ‘dnsrr’. Then only we can refer to other service with their name.
# Deploy a service to the swarm
C:\> docker service create — name=<SERVICENAME> — endpoint-mode dnsrr — network=<NETWORKNAME> <CONTAINERIMAGE> [COMMAND] [ARGS…]
The second argument to this command, --endpoint-mode dnsrr, is required to specify to the Docker engine that the DNS Round Robin policy will be used to balance network traffic across service container endpoints.
Currently, DNS Round-Robin is the only load balancing strategy supported on Windows.
Users seeking an alternative load balancing strategy today can setup an external load balancer (e.g. NGINX) and use Swarm’s publish-port mode to expose container host ports over which to load balance.
The Following is a stack.yml consisting of several services that works on windows server 2016 version 1607. This is how above mentioned constraints (1 and 3) are tackled in a stack file.
version: '3.3'services:
<service_name1>:
image: <image_name>:<image_tag>
deploy:
mode: global
endpoint_mode: dnsrr
placement:
constraints: [node.labels.windows == true]
ports:
- target: 39830
published: 39830
mode: host<service_name2>:
image: <image_name>:<image_tag>
deploy:
mode: global
endpoint_mode: dnsrr
placement:
constraints: [node.labels.windows == true]
ports:
- target: 39832
published: 39832
mode: host
Windows Sever 2019
After Knowing the limitation of the Windows Server 2016 you’ll extremely be relieved to hear the Windows Server 2019 is more docker swarm friendly. A much better explanation is given in the article ‘6 Things You Can Do with Docker in Windows Server 2019 That You Couldn’t Do in Windows Server 2016’.
That’s all for now. If you have found some other things please comment them below and it will improve this blog post. Happy dockering on Windows!