Deploying to Linux & Windows Docker Containers

Last week we shipped an update to the Docker Tools for Visual Studio adding support for Windows Containers.

While the tools support both Linux and Windows, and you can deploy the same project to Linux and Windows, we didn't necessarily optimize for this scenario because:

  • We wanted to stay true to the Docker standard, which uses a single Dockerfile
  • We didn't think developers would deploy to both, and it was only us "demo jockeys"  (PMs) that wanted to deploy to both

As it turns out, people kicking the tires like the idea of deploying to Linux and then deploying to Windows to see how it works. Or, your also riding the demo horse. 

The source of the problem - horse, not the cart, and not sure if it's the chicken or the egg - that's a much larger problem that only a special pig was able to solve:

Linux and Windows have different content to build the image:

In the Docs: https://azure.microsoft.com/en-us/documentation/articles/vs-azure-tools-docker-hosting-web-apps-in-docker/, we do call this out, but we know that if the tools do a great job, you shouldn't have to read docs... :)

Note that the Docker file is specific to the operating system. If you choose to republish to a different OS, you'll need to rename the Docker file so that Visual Studio can create a new default based on the target OS. For instance, if you first publish to a Linux container and later decide to publish to Windows, you should rename the Docker file to a unique name, such as DockerLinux. Then, when you republish to Windows, Visual studio will recreate the default Docker file for Windows. Later, when you republish either one, just select the appropriate Docker file for the OS.

What is a Dockerfile?

A Dockerfile is the definition for how to build the Container. Remember, in Docker, you're not just deploying an app to a target environment. You're building a component of the environment, which includes the app. The Dockerfile defines the baseline OS Image, where to get the app, and how to start the app. Among many other options. 

If you're building for Windows and/or Linux, by definition you're targeting different environments, or for Docker, your targeting different container types. Linux or Windows, and of course which version of Linux or WIndows.

Lets take a look at the content of the DockerFile

Linux Dockerfile

If you first published to Linux, your Dockerfile would contain the following:

FROM microsoft/aspnet:1.0.0-beta6
ADD . /app
WORKDIR /app
ENTRYPOINT ["./kestrel"]

Windows Dockerfile

Docker Doc References

If you first published to Windows, your Dockerfile would contain the following:

FROM windowsservercore
ADD . /app
WORKDIR /app
ENTRYPOINT ["cmd.exe", "/k", "web.cmd"]

Dockerfile format

The details of the Dockerfile are this:

FROM - what is the baseline OS image you want to use?

ADD - add the output of your compiled app

WORKDIR - set the working directory for the entry point

ENTRYPOINT - what should be started when the container spins up? Remember, this isn't just a normal Windows Server with IIS. It's a dedicated container for specific scenarios. 

How do I deploy to both Linux and Windows?

When you initially run the publishing experience in Visual Studio, the Docker File textbox is blank, with a watermark of (auto generate) as we're happy to create the default Docker File for you, based on the target OS:

 

Once you hit publish, the app and container are built and run. If you re-enter the publish dialog will now contain the default Docker file:

Renaming the Docker File

Once the publish is finished, and the default Docker file is created, simply rename the Docker file within solution explorer

Name it DockerWindows or DockerLinux, or whatever you'd like. Put it in a sub folder for Windows\Docker or Linux\Docker. The point is isolate the two docker files related to the target OS

Go back to the publish wizard. This time, use the [...] and select the renamed docker file.

Summary of Steps

  1. Provision a Linux Container Host
  2. Publish to the Linux Host
    Docker Tools for Visual Studio will create a default DockerFile for Linux
  3. Within Solution Explorer, rename the DockerFile to DockerFileLinux
  4. Publish again, this time selecting the renamed DockerFileLinux 
  5. Provision a Windows Container Host
  6. Publish to the Windows Host
    Docker Tools for Visual Studio will re-create the DockerFile as it doesn't see the previous file as it was renamed
  7. Within Solution Explorer, rename the DockerFile to DockerFileWindows
  8. Publish again, this time selecting the renamed DOckerFileWindow

Your project should now look something like this:

  1. Your Linux and Windows Dockerfiles
  2. Azure Resource Manager (ARM) Templates and parameter files for creating the Docker Container Hosts
  3. PowerShell scripts to run the ARM templates

 

I hope that helps explain our tooling options, and perhaps peeks into the details a docker a bit with the contents of the DockerFile

Thanks,

Steve