When we introduced containers to Windows with the release of Windows Server 2016, our primary goal was to support traditional server-oriented applications and workloads. As time has progressed and the utility of containers as a technology is becoming fully realized, we’re now seeing containers playing an important role in enabling Internet of Things (IoT) workloads through Azure IoT Edge. We’ve seen new types of workloads getting containerized—workloads that rely on talking to peripheral devices and sensors (a problem for Windows containers). We’re introducing support for certain host device access from Windows Server containers, beginning in Insider Build 17735 to enable new Windows IoT use cases and transform capabilities for existing server workloads. We’re introducing support for select host device access from Windows Server containers (see table below).
We’ve contributed these changes back to the Open Containers Initiative (OCI) specification for Windows. We will be submitting changes to Docker to enable this functionality soon. Watch the video below for a simple example of this work in action (hint: maximize the video).
[video width="1748" height="746" mp4="https://msdnshared.blob.core.windows.net/media/2018/08/device-in-container.mp4"][/video]
To provide a simple demonstration of the workflow, we have a simple client application that listens on a COM port and reports incoming integer values (powershell console on the right). We did not have any devices on hand to speak over physical COM, so we ran the application inside of a VM and assigned the VM's virtual COM port to the container. To mimic a COM device, an application was created to generate random integer values and send it over a named pipe to the VM's virtual COM port (this is the powershell console on the left).
As we see in the video at the beginning, if we do not assign COM ports to our container, when the application runs in the container and tries to open a handle to the COM port, it fails with an IOException (because as far as the container knew, the COM port didn't exist!). On our second run of the container, we assign the COM port to the container and the application successfully gets and prints out the incoming random ints generated by our app running on the host.
How It Works
Let’s look at how it will work in Docker. From a shell, a user will type:
docker run --device="<IdType>/<Id>" <windows container image>
For example, if you wanted to pass a COM port to your container:
docker run --device="class/86E0D1E0-8089-11D0-9CE4-08003E301F73" mcr.microsoft.com/windowsservercore-insider:latest
The value we’re passing to the device argument is simple: it looks for an IdType and an Id. For this coming release of Windows , we only support an IdType of “class”. For Id, this is a device interface class GUID. The values are delimited by a slash, “/”. Whereas in Linux a user assigns individual devices by specifying a file path in the "/dev/" namespace, in Windows we’re adding support for a user to specify an interface class , and all devices which identify as implementing this class will be plumbed into the container.
If a user wants to specify multiple classes to assign to a container:
docker run --device="class/86E0D1E0-8089-11D0-9CE4-08003E301F73" --device="class/DCDE6AF9-6610-4285-828F-CAAF78C424CC" --device="…" mcr.microsoft.com/windowsservercore-insider:latest
What are the Limitations?
Process isolation only: We only support passing devices to containers running in process isolation ; Hyper-V isolation is not supported, nor do we support host device access for Linux Containers on Windows (LCOW).
We support a distinct list of devices: In this release, we targeted enabling a specific set of features and a specific set of host device classes. We're starting with simple buses. The complete list that we currently support is below.
Device Type | Interface Class GUID
GPIO | 916EF1CB-8426-468D-A6F7-9AE8076881B3
I2C Bus | A11EE3C6-8421-4202-A3E7-B91FF90188E4
COM Port | 86E0D1E0-8089-11D0-9CE4-08003E301F73
SPI Bus | DCDE6AF9-6610-4285-828F-CAAF78C424CC
Stay tuned for a Part 2 of this blog that explores the architectural decisions we chose to make in Windows to add this support.
These changes will enable direct access to a wide variety of sensors for Azure IoT Edge modules running on Windows IoT devices. Look for it with the next release of Windows. We’re eager to get your feedback. What specific devices are most interesting for you and what workload would you hope to accomplish with them? Are there other ways you’d like to be able to access devices in containers? Leave a comment below or feel free to tweet at me.
Craig Wilhite (@CraigWilhite)