Configuring Docker with PowerShell DSC

The post today comes from Andrew Weiss, a very talented consultant with Microsoft Consulting Services.  Andrew has been working on a great project that provides the ability to manage Docker containers using PowerShell DSC.  Thank you Andrew for contributing your article on Building Clouds!


With the release of the first preview build of Windows PowerShell Desired State Configuration for Linux (https://github.com/MSFTOSSMgmt/WPSDSCLinux) comes a plethora of configuration management possibilities that extend across multiple platforms.

This article provides guidance for combining PowerShell DSC with the lightweight, container-based platform known as Docker to quickly create reusable dev/test environments in Microsoft Azure. More specifically, you'll be "Dockerizing" a boilerplate web application that uses PlatypusTS, a web and mobile framework built on TypeScript.

"Infrastructure-as-Code"

When building applications in the cloud, it is important to provide both developers and system administrators with a common set of tools and frameworks. DevOps introduces a concept known as "infrastructure-as-code" where IT pros can manage infrastructure using the same techniques and languages that developers use.

What is Docker?

Docker is an open source platform built-on top of LXC, or LinuX Containers, that can be used for developing and deploying applications. Using what are known as images and containers, developers and IT pros can easily distribute standardized development environments both on-premises and in Azure. What differentiates Docker from traditional virtual machines is that Docker containers are encompassed by a significantly reduced footprint that don't rely on the bloat of a guest operating system.

If you're interested in learning more, the team behind Docker provides a great interactive walkthrough: https://www.docker.com/tryit/.

Getting Started with DSC for Linux

The instructions for installing and configuring your Linux hosts for DSC can be found in an earlier article published by Kristopher Bash back in May when PowerShell DSC for Linux was first announced and released.

Using the step-by-step guidance provided by that article, ensure that your Linux host has been configured for DSC prior to following the rest of the instructions included in this guide. I'll be using an Ubuntu 14.04 LTS virtual machine that I have deployed on Microsoft Azure for the purposes of this walkthrough.

Prerequisites

  • Linux host connectivity via SSH and TCP ports 80, 5985, and 5986
  • Windows host running PowerShell v4.0 or newer
  • Git (https://git-scm.com/)
  • SSH client (PuTTy)

Configuring your Management Workstation

To begin, using a Windows PowerShell console, I'll navigate to an appropriate directory on my workstation and clone the Docker DSC configuration files I need. Executing the command below creates a new directory called DockerClientDSC with my configuration source code:

 git clone https://github.com/anweiss/DockerClientDSC

Within the DockerClientDSC directory is the DockerClient.ps1 script which contains a DSC configuration called DockerClient. I'll use this to ensure that my target VM on Azure is configured as a Docker host and contains the Docker images I want to use for dev/test. I'll also set my working directory to the DockerClientDSC folder before proceeding:

Installing Docker with DSC

Before using the DockerClient configuration, I want to create a variable to hold the hostname of my Linux VM:

 $hostname = "platypus-dev01.contoso.com"

Then I load the configuration into my current session by dot sourcing the script:

 . .\DockerClient.ps1

I can now execute the DockerClient configuration with the Hostname parameter to create a new DockerClient subdirectory that contains the required .mof file for the target node:

 DockerClient -Hostname $hostname

To apply the generated configuration, I need to get a credential for my target host (note that at the time of this writing, the DSC for Linux providers only support connecting via the "root" user):

 $cred = Get-Credential -UserName "root"

I'm also going to configure a set of options that will allow me to successfully establish a PowerShell remoting session to the target:

 $options = New-CimSession -UseSsl -SkipCACheck -SkipCNCheck -SkipRevocationCheck

I can use these options to initiate a CIM session to my Linux VM:

 $session = New-CimSession -Credential $cred -ComputerName $hostname -Port 5986 -Authentication basic -SessionOption $options -OperationTimeoutSec 600

Finally, I can apply my configuration:

 Start-DscConfiguration -CimSession $session -Path .\DockerClient -Verbose -Wait -Force

After the command completes without errors, I now have Docker installed and configured on my Linux VM. Now let's use the DockerClient configuration script to download some Docker Images.

Pulling Docker Images with DSC

Let's go ahead and update our configuration to assert that our Docker host contains a couple of Docker Images. We're going to download a MongoDB image long with an image containing a pre-packaged boilerplate web application based on the PlatypusTS framework. We can do so using the Image parameter as follows:

 DockerClient -Hostname $hostname -Image @("mongo:latest", "anweiss/docker-platynem:latest")

With our CIM session already established, we can simply re-run the Start-DscConfiguration cmdlet.

 Start-DscConfiguration -CimSession $session -Path .\DockerClient -Verbose -Wait -Force

I now have the latest MongoDB images downloaded and installed on my host.

Running Linked Containers with DSC

We can also use the DockerClient DSC configuration to create new linked containers with an instance of MongoDB and our boilerplate web application. Since our web application relies on a running instance of MongoDB, I'm going to first create a MongoDB container. To do so I'll create a hashtable to hold the parameters used for the container.

 $dbContainer = @{Name="db"; Image="mongo:latest"}

Then I'll use the hashtable to create a new configuration.

 DockerClient -Hostname $hostname -Container $dbContainer

As we did before, let's re-run the Start-DscConfiguration cmdlet:

 Start-DscConfiguration -CimSession $session -Path .\DockerClient -Verbose -Wait -Force

Awesome! Now we should have an instance of MongoDB in a running container. Let's SSH in to our VM using PuTTy and get the container's IP address. To do so, we'll execute the following Docker command in our SSH session:

 sudo docker inspect --format="{{ .NetworkSettings.IPAddress }}" db 

I'm going to copy the IP address that's displayed (your's will probably be different).

Now back in our PowerShell console, we'll create a variable to hold the MongoDB container's IP address as well as a variable for our web container's environment variables. We'll also create another hashtable that will hold the settings for our web container.

 $mongoIP = "172.17.0.28"
$envVars = @("MONGOHQ_URL=mongodb://$mongoIP/platynem-dev","PORT=80")

$webContainer = @{Name="web";Image="anweiss/docker-platynem:latest";Port="80:80";Env=$envVars;Link="db"}

Once again, we'll use the hashtable to create a new configuration.

 DockerClient -Hostname $hostname -Container $webContainer

Let's push the configuration again.

 Start-DscConfiguration -CimSession $session -Path .\DockerClient -Verbose -Wait -Force

Our web application should now be running via port 80. When I launch my browser, and direct it to the URL of my VM I should now see a boilerplate web application running in the web container and linked to the container running MongoDB...all configured using PowerShell DSC.


Note – This same technique can be applied to instances of Docker on premises as well, without changing the steps.

Thank you so much for the great post, Andrew.  Stay tuned to Building Clouds!