Containers in software terminology is a lightweight virtual
environment that groups and isolates a set of processes and resources such as
memory, CPU, disk etc. from the host and any other containers. They include the
application and all of its dependencies, but share the kernel with the other
containers. One huge benefit of containers are that they are not tied to any
specific infrastructure. The below diagram depicts docker containers on an
infrastructure.
Containers help
developers create and test applications in their local environment and later
containerize the application, which creates a docker image with the app and the
components required to run the app which is later used to create a container in
an environment which is needed to host the container.
Because the container has everything it needs to run your
application, they are very portable and can run on any machine that is running
Windows Server 2016. You can create and test containers locally, then deploy
that same container image to your company's private cloud, public cloud or
service provider. The natural agility of Containers supports modern app
development patterns in large scale, virtualized and cloud environments.
With containers, developers can build an app in any
language. These apps are completely portable and can run anywhere - laptop,
desktop, server, private cloud, public cloud or service provider - without any
code changes eventually helping developers build and ship higher-quality
applications, faster. For more details on Windows Server Containers you can
refer to this article
in MSDN.
In this series of posts we’ll see, how to create virtual
machines on Azure and later using these to host containers to deploy and test
applications.
To start with we’ll create a VM in a resource group and use
this to create and host our containers. To create and host containers in a VM,
you need a VM with Windows Server 2016 TP3 or later with the windows server
containers feature. I’ve created a PowerShell module to complete the process.
function New-AzureVMInRG
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $ResourceGroupName,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[ValidateScript({($_.Length -ge 3 -and $_.Length -lt 24) -and (-not($_ -cmatch '[A-Z]'))})]
[string] $StorageAccountName,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $VNetName,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $NICName,
[Parameter(Mandatory=$true)]
[ValidateNotNullOrEmpty()]
[string] $VMName,
[Parameter(Mandatory=$false)]
[string] $VMSize = 'Basic_A0',
[Parameter(Mandatory=$false)]
[string] $Location = 'West Europe',
[Parameter(Mandatory=$false)]
[string] $DNSDomainNameLabel,
[Parameter(Mandatory=$false)]
[string] $AvailabilitySetName
)
EnsureResourceGroup $ResourceGroupName $Location -Verbose
$storageAccount = EnsureStorageAccount $ResourceGroupName $StorageAccountName -Verbose
EnsureVirtualNetwork $VNetName $ResourceGroupName $Location -Verbose
if([string]::IsNullOrWhiteSpace($DNSDomainNameLabel))
{
$DNSDomainNameLabel = $ResourceGroupName.ToLower()
}
$publicIP = EnsurePublicIPAddress $NICName $DNSDomainNameLabel $ResourceGroupName $Location
$nic = EnsureAzureNetworkInterface $NICName $publicIP $VNetName $ResourceGroupName $Location
$availabilitySet = EnsureAvailabilitySet -$AvailabilitySetName $ResourceGroupName $Location
$vmConfig = New-AzureVMConfig -VMName $VMName -VMSize $VMSize -AvailabilitySetId $availabilitySet.Id
$vmConfig = New-AzureVMConfig -VMName $VMName -VMSize $VMSize
$credentials = Get-Credential -Message "Provide the name and
password for the local administrator on the virtual machine."
$vmConfig = Set-AzureVMOperatingSystem -VM $vmConfig -Windows -ComputerName $VMName -Credential $credentials -ProvisionVMAgent -EnableAutoUpdate
$vmConfig = Set-AzureVMSourceImage -VM $vmConfig -PublisherName "MicrosoftWindowsServer" -Offer "WindowsServer" -Skus "2016-Technical-Preview-3-with-Containers"
$vmConfig = Add-AzureVMNetworkInterface -VM $vmConfig -Id $nic.Id
$osDiskUri = $storageAccount.PrimaryEndpoints.Blob.ToString() + "vhds/" + $VMName + "OSDisk.vhd"
$vmConfig = Set-AzureVMOSDisk -VM $vmConfig -Name "OSDisk" -VhdUri $osDiskUri -CreateOption fromImage
New-AzureVM -ResourceGroupName $ResourceGroupName -Location $Location -VM $vmConfig
}
You can download the code from GitHub url : AzureResourceGroupExtensions.psm1
Using the module you can create a VM in an Azure resource
group as given below.
New-AzureVMInRG -ResourceGroupName "DockerDemo01" -StorageAccountName "dockerdemostrg01" -VNetName "DDVNet01" -NICName "DDNic01" -VMName "DDemoVM01" -DNSDomainNameLabel "ddemodomain01" -AvailabilitySetName "DDemoSet01"
Once the VM is created, we can login to the VM to create a
container and test the settings. To login, we need to first download the remote
desktop connection file. To download the .RDP file, I’ve created a module
member as given below.
function Get-VMRemoteDesktopFile
{
param
(
[Parameter(Mandatory=$true, Position = 0)]
[Parameter(ParameterSetName = "VMName")]
[string] $VMName,
[Parameter(Mandatory=$true, Position = 0, ValueFromPipeline = $true)]
[Parameter(ParameterSetName = "VM")]
[Microsoft.Azure.Commands.Compute.Models.PSVirtualMachine] $VM,
[Parameter(Mandatory=$true, Position = 1)]
[ValidateNotNullOrEmpty()]
[ValidateScript({(Split-Path $_ -leaf).EndsWith("rdp") })]
[string] $Path
)
$folder = Split-Path -Path $Path -Parent
if(-not (Test-Path $folder))
{
New-Item -Path $folder -ItemType Directory -Force | Out-Null
}
if($PSCmdlet.ParameterSetName -eq "VMName")
{
Get-AzureVM |? {$_.Name -eq $VMName} | Get-AzureRemoteDesktopFile -LocalPath $Path
}
else
{
$VM | Get-AzureRemoteDesktopFile -LocalPath $Path
}
}
Once you have the .rdp file download using the function
given above, you can login to the virtual machine and then create containers.
In the windows administration console, start a PowerShell
session by typing PowerShell. The command prompt will change to PS indicating a
valid PowerShell session
You can create a new container using the New-Container
cmdlet. The cmdlet needs a ContainerImage and a SwitchName as parameters.
Using these options, we can create a new container as given
below.
$containerImage = Get-ContainerImage
$vmSwitch = Get-VMSwitch | Select -ExpandProperty Name
$container = "DemoContainer01"
New-Container -Name $container -ContainerImage $containerImage -SwitchName $vmSwitch
Next we can use the Get-Container cmdlet to check the status
of the container.
Get-Container
As you can see, the status of the container is Off. You can
start the container using the Start-Container cmdlet:
Start-Container -Name $container
Once the container is started, you can interact with the
containers using PowerShell remoting commands such as Invoke-Command, or
Enter-PSSession. For e.g. you can use the Enter-PSSession cmdlet by providing
the container Id to create an interactive session as given below.
$demoContainer = Get-Container -Name $container
Enter-PSSession -ContainerId $demoContainer.Id -RunAsAdministrator
Later, you can exit the session and stop the container using
the Stop-Container cmdlet.
In the upcoming posts, we’ll see how to create an image of
the container, install web server and deploy a website application to the
container.