Creating an IIS Base Image for Containers

Now we have a base image from the last post, we can use it to create other images and containers. Enter a PowerShell command and call Get-ContainerImage, we should see our WindowsServerCore image.
For the sake of this demonstration we will let our containers get an IP address from DHCP in the network, other situations will lead to different DHCP configurations with the containers and their IP address as completely throw away.
So again in the host machine create a new VM switch, I have it mapped to my External switch which will handle the DHCP.

New-VMSwitch –Name DHCP –NetAdapterName Ethernet

Now we create a new container which will become our base IIS image, so call

New-Container –Name ServerCoreIIS –ContainerImageName WindowsServerCore –SwitchName “DHCP”

Then start it up with Start-Container –Name ServerCoreIIS
We will need to enable the IIS feature, so enter a PowerShell session.
Then invoke the command to install the Web Server feature.

Invoke-Command –ScriptBlock {Install-WindowsFeature Web-Server}

It will run through and should show an Exit Code of Success
Get the IP address.
We should see the typical IIS welcome page when we browse to it.
Now call Stop-Container ServerCoreIIS
We now need to create an image from that container, so call the Get-Container command and pipe it to the New-ContainerImage like this.

Get-Container –Name ServerCoreIIS | New-ContainerImage –Publisher YourCompany –Name ServerCoreIIS –Version 1.0

I have named both the container and image the same so I can easily determine the relationship.
When calling Get-ContainerImage we should see our 2 base images.
Now we can create any number of containers based off the ServerCoreIIS image like this.
Start one up, enter a PowerShell session using Enter-PSSession –ContainerName “IISWeb01” –RunAsAdministrator and get the IP address
We should then see the IIS welcome page again when we browse to that address.
So now we have a static website running from c:\inetpub\wwwroot on the container. In the next post I will configure the base IIS image to run an MVC website and create a container from that.

Happy coding.

Windows Server 2016 Containers

Containers, Docker and other similar technologies are such a trending topic these days I thought I would take the time to have a look at what all the fuss is about. Being a Windows developer and not completely happy with having to run VirtualBox just to get a Linux distro working so I can create a container, With Windows Server 2016 containers are built in so I wanted to explore them and see how it could change my development workflow. These posts are a journey of installing and configuring a set of containers to host an ASP.Net MVC website inside them. I initially tried running the PowerShell scripts linked by Microsoft on their ‘Windows Containers Quick Start’ pages, but I ended up getting so many errors with them (it is understandable as it is still in development) that I started from scratch and built the containers up myself.

Installing Windows Server Core and enabling the Container feature

Firstly get the Server 2016 ISO from Currently this is Technical Preview 4 and may change before the final release of Windows Server 2016.
I have renamed my ISO WindowsServerTP4 so I can find it on my machine much easier.
Create a VM and mount the ISO as the DVD drive.
Creating a Server 2016 Core Virtual Machine
Make sure the VM has access to an external switch.
I have called mine ContainerHost and will be a Server Core installation.
Start and connect to the Virtual Machine.
Follow the usual UELA and drive specifics.
Installing Server Core
Installing Server Core
Specify drive properties  
On first boot you need to change the password (use tab to move to the confirm password prompt).
Change password
Enter a PowerShell session.
Enter PowerShell session
Install the Container Windows feature by using the cmdlet
Install-WindowsFeature Containers.
Install Containers feature
Server will continue to install components during reboot.
Install and reboot
Login and renter back into PowerShell.
Now you can list all the command the Container feature exposes.
Run Get-Command –Module Containers
Container commands

Installing a Base OS Image

The main container features are now installed, however all containers must be based off an OS image and these come from OneGet. As Server Core Technical Preview 4 is version 10.0.10586.0, then the base OS image has to be the same. These images are WIM files and can be downloaded and saved to your local network from the Server Core Virtual Machine. First install the PackageProvider (OneGet).
Install-PackageProvider ContainerProvider –Force
Then you can use this to find container images from OneGet.
Find base OS images
Create a local share on your host machine and create a mapped drive in the Virtual Machine.
net use z: \\path-to-share\MyShare <account password> /user:"<username"
Save the WIM file to this share.
Save-ContainerImage -Name WindowsServerCore -Version 10.0.10586.0 -Destination "z:\WindowsServerCore.wim"
This will take a long time depending on your internet connection as it is Gigabytes in size.
Now the wim file is on your host network you can use the Install-ContainerOSImage to import it to your image collection. This way any time you want to create other Virtual Machines and run through this process again, you already have the WIM and don't need to download it again. However the WIM version will change if there is another Technical Preview or Release.
Install base OS image
Running the command Get-ContainerImage should list this as an OS image.
Display locally installed images
In the next post I will create an image that has IIS set up and then create containers based off this image.

Happy coding

In an older post on website performance using concatenating and minification I used the Ajax Minifier tool to do the work and used an MSBuild file to run that tool, now I use gulp which I find easier as it only needs a dependency on node and so can be separated out from the Visual Studio project itself and run outside the build cycle.


When run in a CI/CD environment, the gulp file is processed before an actual build takes place, this is so that the AssemblyInfo.cs file can be amended with the version information. The gulp file can be broken down into 3 main parts; the version, concatenation and minification and the assembly version writing.

The default task is run initially which will then run the version task. The version task reads any parameters passed into the gulp runner, in this case it is looking for buildVersion and uses the yargs library. If it is undefined, then it is being run outside the CI environment and can default to Then it performs the concatenation and minification of the styles using the gulp-concat and gulp-cssnano libraries. The resulting file is then written out to the public-assets/css directory which is where they are referenced from in the HTML view.The same process is taken for the JavaScript files except the gulp-uglify library is used to minify them.

Writing them to the public-assets/js and css directories allows the directories to be classed as static in IIS and so we can add addition headers such as expiry dates. Finally the same version number is passed to the assembly-info task which uses the gulp-dotnet-assembly-info library. This simply changes the AssemblyInfo.css file so when it is built, the assembly will have this version. Then when both JavaScript and css files are linked to in the HTML, the assembly version can be injected to the url.


TeamCity Integration

It is real easy to include a gulp task to TeamCity by creating a Build step to your pipeline and choosing the Command Line as the runner type.


Then specify ‘Custom script’ from the drop down and enter your normal gulp command in the Custom script text area.

With my gulp script I specify a build version parameter which gets its value from the environment variable BUILD_NUMBER. This is the counter that the gulp build step generates when it is running. I use this value, inject it into the gulp script using the version task which is then used to name the css and JavaScript files. It also changes the AssemblyInfo.cs file to create a unique assembly version.

Happy coding

There are some things you cannot do on a typical Windows 8.1 installation such as view a web site externally when running IIS Express. But also if you want to run full IIS on a Windows Pro 8.1 machine and have Visual Studio run your web application through it then you need to run Visual Studio with administrator privileges. In Windows 7 there is a compatibility tab in the program properties where you can specify this, but that is not available in Windows 8 or Windows 8.1 installations. So find the location of the devenv.exe application file. This is usually somewhere like C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE.  
  Right click it and instead of choosing properties, choose troubleshoot compatibility.  
Select Troubleshoot program for the options  
Then check the box for additional permissions (this usually means administrator privileges).  
Now test the program by running Visual Studio  
Once Visual Studio has opened, at the top it should specify that it is running as administrator  
Back to the wizard,  choose 'Yes, save these settings for this program'  
It will do its thing and look for any other issues.  
You should see the next image when it has finished off.  
Simply close it and you should be OK with running IIS Express as well as a local installation of IIS.  

Unless using third party tools, management of IIS Express is pretty limited. For example it is not possible to log to a SQL Server database for later analysis. You can however import the current log files into SQL Server and here I will show you how I go about it. Firstly you need to create the table in SQL Server, however I am going to initially use a temporary table:-These are all the fields that the current version of IIS Express 8.0 uses. However before you import, you need to strip out all comment fields such as those beginning with # symbols. To do this download the Microsoft PrepLog tool; it is an old tool, but still useful for this purpose.  Then run the tool on a log file using PrepTool on the command line:-Then finally, do a bulk insert to get it all into SQL ServerNow create a table to import the data to, the only difference here is the addition of an id column. I want an id column because I will be querying it from Entity Framework and for that you need a primary key.Then use a SELECT query to get the data into the final table:-Happy coding.