Test your Chocolatey Packages in a Windows Container

Containers are a great place to test your Chocolatey packages or even packages from another source.  You don’t have to waste time creating and tearing down vms and perhaps most importantly you can avoid those “It worked on my machine” problems.  By spinning up a clean container every time you will know all your dependencies and can specify them.  There are many approaches and this is just one example.  This article assumes you have a place to run windows containers, docker, and a minimal amount of docker experience.  You can run this on a windows 10 machine, Server 2016 with Hyper-V, or Azure.

The complete code is posted below, but lets break it up a bit and walk through small pieces and point out some of the variations on the source of the package.

In this first version we’ll look at testing a package you’ve created and assume you have the .nupkg file locally.  First, its useful to define a few variable such as the path to the nupkg file.  The $waitTime variable gives chocolatey time to install before trying to fetch the logs.  All the real work is defined in the variable $ps.  $ps contains the code that downloads and installs the the latest chocolatey client.  Next it will use that client to install the chocolatey package you defined the path to in $chocoPack.  Finally it will download and run a script from Microsoft that keeps the container running after the install so you can examine it.  (The nature of a container is to stop running after its ran some piece of code.)  We’ll get to starting the container further down.

$chocoPack = ''
$waitTime=# [int] in seconds as estimate of how long package install takes
$waitUrl='https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/windows-server-container-tools/Wait-Service/Wait-Service.ps1'
$ps="iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'));choco install $chocoPack -y;Invoke-WebRequest -Uri '$waitUrl' -OutFile 'c:\Wait-Service.ps1';c:\Wait-Service.ps1 -ServiceName WinRm -AllowServiceRestart"

In this next section we’ll look at installing a package from the default public package repo.  The only difference here is that $chocoPack will just contain the name of the public package.  This example installs vscode because vscode is awesome.

$chocoPack = 'vscode'
$waitTime=# [int] in seconds as estimate of how long package install takes
$waitUrl='https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/windows-server-container-tools/Wait-Service/Wait-Service.ps1'
$ps="iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'));choco install $chocoPack -y;Invoke-WebRequest -Uri '$waitUrl' -OutFile 'c:\Wait-Service.ps1';c:\Wait-Service.ps1 -ServiceName WinRm -AllowServiceRestart"

And the last example is using your own private chocolatey server and specifies.   In teh choco install section I’ve added the $version variable and ‘-s $privateServerURL’.  -s specifies the ‘Source’, in this case the URL to your server.

$chocoPack = 'my-package'
$version='--version 1.0.0'
$privateServerURL = 'http:///choco/nuget/'
$waitTime=# [int] in seconds as estimate of how long package install takes
$waitUrl='https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/windows-server-container-tools/Wait-Service/Wait-Service.ps1'
$ps="iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'));choco install $chocoPack $version -s $privateServerURL -y;Invoke-WebRequest -Uri '$waitUrl' -OutFile 'c:\Wait-Service.ps1';c:\Wait-Service.ps1 -ServiceName WinRm -AllowServiceRestart"

Now lets look at actually spinning up the container.  The first line is the actual docker command to spin up the container based on windowsservercore image and tells powershell to run the code we defined above.  It also stores the container instance ID in $cid which you will need later.  The it waits to give the package time to install.  The Invoke-command will spit out the log files about the install.  Finally you can use powershell to “remote” into the container and manually look at logs or files, etc.

($cid = docker run -d $dockerArgs microsoft/windowsservercore powershell.exe -executionpolicy bypass $ps )
Start-Sleep -Seconds $waitTime
Invoke-Command -ContainerId $cid -RunAsAdministrator -ScriptBlock{
Get-Content C:\choco\logs\choco.summary.log
#Get-Content C:\choco\logs\chocolatey.log
choco list --local-only ## list install packages
}
Enter-PSSession -ContainerId $cid -RunAsAdministrator

And here it is altogether.

$chocoPack = ''
$waitTime=# [int] in seconds as estimate of how long package install takes
$waitUrl='https://raw.githubusercontent.com/Microsoft/Virtualization-Documentation/master/windows-server-container-tools/Wait-Service/Wait-Service.ps1'
$ps="iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'));choco install $chocoPack -y;Invoke-WebRequest -Uri '$waitUrl' -OutFile 'c:\Wait-Service.ps1';c:\Wait-Service.ps1 -ServiceName WinRm -AllowServiceRestart"
($cid = docker run -d $dockerArgs microsoft/windowsservercore powershell.exe -executionpolicy bypass $ps )
Start-Sleep -Seconds $waitTime
Invoke-Command -ContainerId $cid -RunAsAdministrator -ScriptBlock{
Get-Content C:\choco\logs\choco.summary.log
#Get-Content C:\choco\logs\chocolatey.log
choco list --local-only ## list install packages
}
Enter-PSSession -ContainerId $cid -RunAsAdministrator
Its also worth noting, in these examples I’m using the -d switch in ‘docker run -d’ which tells it to run detached or in the background.  You can use -it to just jump in and watch it as well.  When I first started working with docker there were issues doing this from powersehell.  The latest version of the tools fixed this problem 🙂
UPDATE:  You can not run a full GUI version of windows server in a container so if you are trying to install an application that has dependencies on .dll files not in Server Core this may not work.
Also, since chocolately is just Powershell files to install an application, this basic process can work to install any application that can be installed on Server Core from powershell/comdmandline.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.