Thursday, 01 March 2018

Running cross platform containers on Windows in Docker 18.03

With the recent release of Docker for Windows 18.03, I decided to finally start experimenting with it. One of the main features that this release brings is the ability to run both Windows and Linux images side by side, instead of having to switch Docker from Linux to Windows mode. The other benefit is that it runs all the images using the Windows Container infrastructure, instead of running the linux images in a Linux VM on your machine (which had to have some of your cpu and memory permanently allocated to it). This means that unless you're running a container, docker will hardly use any resource at all on your machine! All this combined makes docker for windows considerably more attractive!

There are some issues in this release (at this moment it's part of the edge channel, so it's to be expected), but it's a great step forward.

To start things off, at the moment Docker won't try to auto-detect what platform to use when running the image. Instead, it will always assume you want to run the image in the default system platform, unless specified otherwise. For example, on my Windows 10 machine the following command will pull a windows image:

docker pull hello-world

To get a linux image, you'd have to add the --platform=linux argument:

docker pull --platform=linux hello-world

Now this might not be what you want, and I was wondering if there's a way to change this. Unfortunately I haven't found it documented anywhere obvious, but I eventually stumbled on a GitHub discussion, which pointed me in the right direction. All you need is to set the DOCKER_DEFAULT_PLATFORM environment variable to linux or windows to change the default platform that your cli will use! In my case I switched the default to linux straight away.

Another thing you want to be aware of is once an image is pulled to your machine, you don't have to specify the platform. Again, the documentation doesn't do a great job of explaining it, and will certainly confuse newbie docker users (as it has certainly confused me!). They state:

Once the image has been pulled with the platform specified, the --platform flag is no longer required

While true, this is also masking the actual reason for why it's happening. The --platform argument is needed for the pull command, so that it can pull the correct image from the remote repository. If you're trying to run an image, and the image wasn't pulled previously, docker will try to download it (hence the need for the plarform argument the first time you run an image). Having read that message, I thought that if I wanted to run the image in a different platform, I'd have to remove the image first from the local machine, and pull it again with the other platform specified. In reality, docker keeps all the images by their image ID. The linux and windows variants will have different IDs, and when you pull the image, it will be tagged with whatever tag you requested. The key here is that the tag can be easily applied to a different image without having to remove and download images. Consider the following:


docker pull --platform=linux artiomchi/helloworld:latest
latest: Pulling from artiomchi/helloworld
Digest: sha256:37acc48652cc288f09f2f396569e642d73318886d1f922c553976ee3c2fc41b4
Status: Image is up to date for artiomchi/helloworld:latest
docker images
REPOSITORY                 TAG                           IMAGE ID            CREATED             SIZE
artiomchi/helloworld       latest                        9144aa0701ca        5 hours ago         111MB
artiomchi/helloworld       alpine                        9144aa0701ca        5 hours ago         111MB
artiomchi/helloworld       nanoserver-1709               71dfcd46ca97        6 hours ago         379MB
docker run --rm artiomchi/helloworld:latest
Hello World! This app is running on Linux 4.14.14-linuxkit #1 SMP Wed Jan 17 14:45:02 UTC 2018
docker pull --platform=windows artiomchi/helloworld:latest
latest: Pulling from artiomchi/helloworld
Digest: sha256:37acc48652cc288f09f2f396569e642d73318886d1f922c553976ee3c2fc41b4
Status: Downloaded newer image for artiomchi/helloworld:latest
docker images
REPOSITORY                 TAG                           IMAGE ID            CREATED             SIZE
artiomchi/helloworld       latest                        71dfcd46ca97        6 hours ago         379MB
artiomchi/helloworld       alpine                        9144aa0701ca        5 hours ago         111MB
artiomchi/helloworld       nanoserver-1709               71dfcd46ca97        6 hours ago         379MB
docker run --rm artiomchi/helloworld:latest
Hello World! This app is running on Microsoft Windows 10.0.16299

Note the Image ID and TAG columns in the output above - I already had both images downloaded in advance, so the pull command just set the tag to the image that had the correct platform (it's a bit more involved, but I'll mention it in a separate blog post). The second time, I requested a windows platform image, so the :latest tag was moved to the windows based image. In both cases the run command didn't need to have the platform specified, as it just picked up whatever image was tagged as :latest.

The great thing is that with this release you can now run any of these images side by side, by calling them either by the image ID or their alternative tags:


docker run --rm  9144aa0701ca
Hello World! This app is running on Linux 4.14.14-linuxkit #1 SMP Wed Jan 17 14:45:02 UTC 2018
docker run --rm 71dfcd46ca97
Hello World! This app is running on Microsoft Windows 10.0.16299
docker run --rm  artiomchi/helloworld:alpine
Hello World! This app is running on Linux 4.14.14-linuxkit #1 SMP Wed Jan 17 14:45:02 UTC 2018
docker run --rm artiomchi/helloworld:nanoserver-1709
Hello World! This app is running on Microsoft Windows 10.0.16299