<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>Working with Containers</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/containerstuff/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/containerstuff/feed.xml</link>
    <description>Patterns and Notes on how to get your Apps Working on Containers</description>
    <lastBuildDate>Tue, 10 Oct 2017 20:07:24 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Integrating Azure Container Registry for Container Image management</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/integrating-azure-container-registry-for-container-image-management</link>
      <pubDate>Tue, 10 Oct 2017 12:07:24 GMT</pubDate>
      <dc:creator><![CDATA[Rohit Tatachar]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=646</guid>
      <description><![CDATA[As part of our Enterprise readiness for the Container based program, one key component is to...]]></description>
      <content:encoded><![CDATA[As part of our Enterprise readiness for the Container based program, one key component is to integrate with a Container Registry (in our case the Azure Container Registry) which is a private repository of you Docker based Container Images. Integrating ACR into your CI/CD process further helps creating a secure End-End dev-ops model for Enterprise readiness.

<strong>What is a Container Registry?</strong>

Azure Container Registry is a managed Docker registry service based on the open-source Docker Registry 2.0. Create and maintain Azure container registries to store and manage your private Docker container images. Use container registries in Azure with your existing container development and deployment pipelines, and draw on the body of Docker community expertise. Some of the Advantages to ACR over other registries are below, for more details visit <a href="https://azure.microsoft.com/en-us/services/container-registry/">https://azure.microsoft.com/en-us/services/container-registry/</a>:
<ul>
 	<li>Manage different types of Containers</li>
 	<li>Provides a private Repo accessible only to your Org</li>
 	<li>Repo instance available in same region/Datacenter as your data hence reducing latency</li>
</ul>
<strong>Key Concepts</strong>
<ul>
 	<li>Registry - Create one or more container registries in your Azure subscription. Each registry is backed by a standard Azure storage account in the same location. A fully qualified registry name has the form myregistry.azurecr.io.</li>
 	<li>Managed Registry - A tier that offers additional capabilities for registries in three SKUs - Basic, Standard, and Premium. The images in these SKUs are stored in Storage Accounts managed by the Azure Container Registries service, which improves reliability and enables new features.</li>
 	<li>Repository - A registry contains one or more repositories, which are groups of container images. Azure Container Registry supports multilevel repository namespaces. This feature enables you to group collections of images related to a specific app, or a collection of apps to specific development or operational teams. For example:
rtrappscontainerregistry.azurecr.io/[Offerin]/[ServiceLine]/[Service]/[App Name]:[Build ID]</li>
 	<li>Image - Stored in a repository, each image is a read-only snapshot of a Docker container. Azure container registries can include both Windows and Linux images. You control image names for all your container deployments. Use standard Docker commands to push images into a repository, or pull an image from a repository.</li>
</ul>
<strong>Steps to Create ACR</strong>

1) Login to Azure Portal https://portal.azure.com/
2) Click on “+”
3) Select ‘Azure container registry’ then Select it

4) In the ‘Azure Container Registry’ blade, enter the following information. Then click on ‘Create’
a) Registry name: A globally unique top-level domain name for your specific registry. In this example, the registry name is ‘myazurecontainerregistry1’, but substitute a unique name of your own. The name can contain only letters and numbers.
b) Resource group: Select an existing resource group or type the name for a new one.
c) Location: Select an Azure datacenter location where the service is available, such as South Central US.
d) Admin user: If you want, enable an admin user to access the registry. You can change this setting after creating the registry.

Steps to pull and push an image in Azure Container Registry
1) Open PowerShell shell as Administrator
2) Run below command to login to Azure Container Registry

docker login myazurecontainerregistry1.azurecr.io -u demouser -p myPassword

3) Create a tag of the image to be pushed into Azure Container Registry

The following command creates an alias of the image, with a fully qualified path to your registry.

docker tag myApp myazurecontainerregistry1.azurecr.io/samples/myApp
4) Push the image to your Azure Container Registry

docker push myazurecontainerregistry1.azurecr.io/samples/myApp

5) Pull the image from Azure Container Registry

docker pull myazurecontainerregistry1.azurecr.io/samples/myApp]]></content:encoded>
    </item>
    <item>
      <title>Optimizing legacy workloads using Containers</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/optimizing-legacy-workloads-using-containers</link>
      <pubDate>Tue, 03 Oct 2017 11:38:04 GMT</pubDate>
      <dc:creator><![CDATA[Rohit Tatachar]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=627</guid>
      <description><![CDATA[This blog links to another article that covers some of the optimization and related benefits that...]]></description>
      <content:encoded><![CDATA[This blog links to another article that covers some of the optimization and related benefits that can be accrued by moving your legacy and older work load to Containers along with the direct benefits of modernization and agility.

https://www.microsoft.com/itshowcase/blog/optimizing-microsoft-legacy-apps-containers/]]></content:encoded>
    </item>
    <item>
      <title>Pre-Req Considerations and Quick Start guide to Containerizing legacy apps</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/pre-req-considerations-and-quick-start-guide-to-containerizing-legacy-apps</link>
      <pubDate>Tue, 03 Oct 2017 11:17:28 GMT</pubDate>
      <dc:creator><![CDATA[Rohit Tatachar]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=616</guid>
      <description><![CDATA[Considerations: Some of the things to consider when looking at candidate legacy applications for...]]></description>
      <content:encoded><![CDATA[<strong>Considerations: Some of the things to consider when looking at candidate legacy applications for Containerization</strong>
<table width="642">
<tbody>
<tr>
<td width="43">1</td>
<td width="68">High</td>
<td width="531">What are pre-requisites required to setup app into new box?</td>
</tr>
<tr>
<td width="43">2</td>
<td width="68">Medium</td>
<td width="531">Which - .NET Frameworks Version required for app?</td>
</tr>
<tr>
<td width="43">3</td>
<td width="68">Medium</td>
<td width="531">Does app use Authentication/Authorization? [Ad, AAD, custom...]</td>
</tr>
<tr>
<td width="43">4</td>
<td width="68">Medium</td>
<td width="531">Does app use Session State / Data Persistence?</td>
</tr>
<tr>
<td width="43">5</td>
<td width="68">High</td>
<td width="531">Does app do any kind of logging - Centralized/File system, Windows event log?</td>
</tr>
<tr>
<td width="43">6</td>
<td width="68">High</td>
<td width="531">Does app use  certificates?</td>
</tr>
<tr>
<td width="43">7</td>
<td width="68">High</td>
<td width="531">Does app uses - Commercial/Professional Software (e.g. SharePoint, SQL Server, SAP, Oracle, Site core)?</td>
</tr>
<tr>
<td width="43">8</td>
<td width="68">Low</td>
<td width="531">Does app has - Strict security / compliance requirements? (Need clarification on this questions)</td>
</tr>
<tr>
<td width="43">9</td>
<td width="68">Medium</td>
<td width="531">Does app use Multiple disks?</td>
</tr>
<tr>
<td width="43">10</td>
<td width="68">Medium</td>
<td width="531">Does app use Multiple web apps or virtual directory?</td>
</tr>
<tr>
<td width="43">11</td>
<td width="68">Medium</td>
<td width="531">Does app require specific Registry Settings?</td>
</tr>
<tr>
<td width="43">12</td>
<td width="68">Medium</td>
<td width="531">Does app utilize File Shares?</td>
</tr>
<tr>
<td width="43">13</td>
<td width="68">Medium</td>
<td width="531">Does app require specific NTFS file/folder permissions?</td>
</tr>
<tr>
<td width="43">14</td>
<td width="68">Medium</td>
<td width="531">Does app require Registering GAC / ActiveX components?</td>
</tr>
<tr>
<td width="43">15</td>
<td width="68">Medium</td>
<td width="531">Does app require any 3rd party component like SMTP etc.?</td>
</tr>
<tr>
<td width="43">16</td>
<td width="68">Medium</td>
<td width="531">Does app need DNS/IP mapping?</td>
</tr>
<tr>
<td width="43">17</td>
<td width="68">Medium</td>
<td width="531">Does app require Multiple domain support?</td>
</tr>
<tr>
<td width="43">19</td>
<td width="68">Medium</td>
<td width="531">Does app require Scheduled Task Support?</td>
</tr>
<tr>
<td width="43">20</td>
<td width="68">High</td>
<td width="531">Does app have dependency? what are upstream/downstream apps?</td>
</tr>
</tbody>
</table>
<h1><a></a>Steps to Containerize an application</h1>
<ol>
 	<li>Copy the working bits to the folder.</li>
 	<li>Create a file and save it as “dockerfile”. * Without any extension.</li>
 	<li>Take the image you want to built for the docker file. “FROM microsoft/aspnet”</li>
 	<li>Copy the compiled files to the image “ADD ./&lt;WebApp&gt;/ "c:/inetpub/wwwroot/&lt;WebApp&gt;"”</li>
 	<li>Set the powershell as default shell for running the subsequent commands.</li>
 	<li>Install the IIS feature if required.</li>
 	<li>If required to enable or disable any property use the powershell commands.RUN Set-WebConfigurationProperty -filter /system.webServer/security/authentication/windowsAuthentication -name enabled -value true -PSPath IIS:\ ;</li>
 	<li>RUN Set-WebConfigurationProperty -filter /system.WebServer/security/authentication/AnonymousAuthentication -name enabled -value false -PSPath IIS:\ ;</li>
 	<li>If you want to add any user as the administrator you can use the command</li>
 	<li>If need to edit any registry use the commands like</li>
 	<li>RUN New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\lsa -Name DisableLoopbackCheck -Value 1 -PropertyType DWORD -Force | Out-Null</li>
 	<li>Start the web service in the application..</li>
 	<li>RUN New-Website -Name 'Webapp' -Port 8086 \</li>
 	<li>   -PhysicalPath 'c:\inetpub\wwwroot\WebApp' -ApplicationPool '.NET v4.5'</li>
 	<li>To expose the port from the container you can use EXPOSE 8086</li>
 	<li>If you want to execute some common script you want to start every time a container start</li>
 	<li>ENTRYPOINT ["Powershell", "C:/entrypoint.ps1"]</li>
 	<li>Where entrypoint.ps1 can be a file consisting of all the powershell commands required to run in the container for server setup</li>
 	<li>All this command can be composed into a single docker file and store it with the compiled code.\</li>
 	<li>After creation of the docker file create the image</li>
</ol>]]></content:encoded>
    </item>
    <item>
      <title>Using the Windows EventViewer GUI to view Eventlogs in Containers</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/using-the-windows-eventviewer-gui-to-view-eventlogs-in-containers</link>
      <pubDate>Fri, 18 Aug 2017 16:45:00 GMT</pubDate>
      <dc:creator><![CDATA[MarkBrianWest]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=585</guid>
      <description><![CDATA[If you work with legacy apps (or maybe some not so legacy apps) in containers then you know about...]]></description>
      <content:encoded><![CDATA[If you work with legacy apps (or maybe some not so legacy apps) in containers then you know about what a pain it is to read the all important event log. In this post I'll present a passable pattern that is good enough for occasional use, like when initially deploying or diagnosing an in-production failure. 

Right up front: This is not ideal but it's not bad and it works. It's WAY better than viewing events in the Container CLI like I presented in <a href="https://blogs.msdn.microsoft.com/containerstuff/2017/02/14/access-a-database-with-active-directory-from-a-windows-service-in-a-container/" target="_blank">here</a>. If anybody knows how to remote the EventLog viewer right into the container please let me know and I'll update with credits.

The sequence is:
<ul>
	<li>We create a container with a shared volume and access the CLI on the container. </li>

	<li>On the container CLI we do whatever stuff we need to do, for instance maybe install and start up a Windows Service.</li>

	<li>Using the <a href="https://technet.microsoft.com/en-us/library/cc732848(v=ws.11).aspx" target="_blank">wevtutil</a> utility, we snap a copy of the event log in which we are interested to a file on the shared volume.</li>

	<li>We return to the container host to access the event log file and view in the EventViewer GUI</li>

	<li>Repeat snap-read as necessary as you would do in the regular course of diagnostics</li>

</ul>



[on container host]

Open a Powershell sesion

Create a share directory
<code>mkdir c:\shared</code>

Create container with shared volume pointing to the c:\shared directory
<code>docker run -it --name winservcoret2 -v c:\shared:c:\shared microsoft/windowsservercore</code>

Since the container was started with the -it configuration, the PowerShell session will switch to the Container console

[on container]

Do things that create some events, then snap a copy of the event log to a file in the shared volume. In this case we snap the <strong>application</strong> log but you can snap any log present on the container.
<code>wevtutil epl Application C:\shared\AppLogBackup.evtx</code>

[on container host]

Open c:\shared\AppLogBackup.evtx directly or open it from an existing EventViewer 

<img src="https://msdnshared.blob.core.windows.net/media/2017/08/FileSystem-300x154.png" alt="" width="300" height="154" class="alignnone size-medium wp-image-605" />

The Eventlog Viewer will open with the snapped event log

<img src="https://msdnshared.blob.core.windows.net/media/2017/08/EventViewer-300x224.png" alt="" width="300" height="224" class="alignnone size-medium wp-image-595" />

We have a number of options for filtering the events that get written to the .evtx file, for example this script which boxes on start and end dates:

<code>$start = '1/1/2016'
$end = '1/2/2017'
function GetMilliseconds ($date) {
     $ts = New-TimeSpan -Start $date -End (Get-Date)
     [math]::Round($ts.TotalMilliseconds)
     } # end function
$startDate = GetMilliseconds(Get-Date $start)
 $endDate = GetMilliseconds(Get-Date $end)
 wevtutil epl Application test.evtx /q:"*[System[TimeCreated[timediff(@SystemTime) &gt;= $endDate] and TimeCreated[timediff(@SystemTime) &lt;= $startDate]]]&quot;</code>

]]></content:encoded>
    </item>
    <item>
      <title>Getting IIS Win Auth to Work in a Container</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/getting-iis-win-auth-to-work-in-a-container</link>
      <pubDate>Mon, 31 Jul 2017 19:45:33 GMT</pubDate>
      <dc:creator><![CDATA[MarkBrianWest]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=575</guid>
      <description><![CDATA[As you have no doubt figured out by now, containerization of IIS apps that use Windows...]]></description>
      <content:encoded><![CDATA[As you have no doubt figured out by now, containerization of IIS apps that use <a href="https://technet.microsoft.com/en-us/library/cc754628(v=ws.10).aspx" target="_blank">Windows Authentication </a>to authenticate users is not as simple as referring to the <a href="https://technet.microsoft.com/en-us/library/hh831782(v=ws.11).aspx" target="_blank">gMSA</a> of the app in the <a href="https://blogs.msdn.microsoft.com/containerstuff/2017/01/30/create-a-container-with-active-directory-support/" target="_blank">credentialspec</a> of the Docker Run command. Two new things are needed: 1) association of the <a href="https://msdn.microsoft.com/en-us/library/ms677949(v=vs.85).aspx" target="_blank">Service Principal Name </a>with the gMSA and, 2) setting the hostname of the container to the name of the gMSA.

<strong>tldr version:</strong>

Assuming you have a gMSA named <em>redmond\adonconnt1</em> and a container host named <em>markw2016cont5.redmond.corp.microsoft.com</em>

1) Use <a href="https://setspn -c -s HTTP/adoncontt1 redmond\adoncontt1" target="_blank">Setspn</a> like this : 

<code>setspn -c -s HTTP/markw2016cont5 redmond\adoncontt1
setspn -c -s HTTP/markw2016cont5.redmond.corp.microsoft.com redmond\adoncontt1</code>

2) Add the -h param to the docker run command like this:

<code>docker run -it --name winautht1 -h adoncontt1 -p 81:80 -v c:\shared:c:\shared --security-opt "credentialspec=file://adoncontt1.json" microsoft/windowsservercore:latest</code>

* It is mandatory that the argument for the -h parameter in the docker run command (in this example 'adoncontt1') be exactly the name of the gMSA (in this example 'adoncontt1').

<strong>Full version:</strong>

I'll get to this in a day or two :-)
]]></content:encoded>
    </item>
    <item>
      <title>CI/CD of Containers from Visual Studio to Service Fabric</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/cicd-of-containers-from-visual-studio-to-service-fabric</link>
      <pubDate>Thu, 08 Jun 2017 10:12:33 GMT</pubDate>
      <dc:creator><![CDATA[MarkBrianWest]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=296</guid>
      <description><![CDATA[CI/CD is all the rage for software deployment for good reason. Docker Containers are all the rage...]]></description>
      <content:encoded><![CDATA[CI/CD is all the rage for software deployment for good reason. Docker Containers are all the rage for software packaging and distribution for good reason. When the two are combined you get much more than the sum of the parts, they come together in a very natural way that suggests that they were created to act as one. We are not going to get into the details of all that here, there is plenty of coverage of that elsewhere.

In this post we will be presenting the complete sequence of steps you can take to implement full CI/CD of containers from new or legacy source in Visual Studio to production in Azure Service Fabric.

We will present a step by step sequence starting from scratch, and due to certain features being available only in pre production at this time (May 23 2017) you may be better off starting from scratch yourself even if you already have a running service fabric.
<p style="margin: 0in;font-family: Calibri;font-size: 11.0pt"> Prereqs</p>

<ul>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Windows 10</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Azure Subscription </span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Visual Studio (Preview)</span></li>
</ul>
<p style="margin: 0in;font-family: Calibri;font-size: 11.0pt">Steps</p>

<ul>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Obtain a Visual Studio Online account</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Install Docker for Windows</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Select an Azure Subscription</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Create Azure Container Repository </span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Log in to Azure from Powershell</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Create Key Vault</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Create Certificate and Key</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Import Certificate to local cert store</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Create a Service Fabric Cluster</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Edit load balancer</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Create/open app</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Add Docker support</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Edit ports</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Add solution to source control</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Add CI/CD</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Verify site access</span></li>
 	<li><span style="font-family: Calibri;font-size: 11.0pt">Check In</span></li>
</ul>
&nbsp;
<h2>Obtain a Visual Studio Online account</h2>
<p style="margin: 0in;font-family: Calibri;font-size: 11.0pt">A <span style="text-decoration: underline">Visual Studio Team Services</span> account will be needed to facilitate the CI/CD automation</p>
<p style="margin: 0in;font-family: Calibri;font-size: 11.0pt">You may skip this step if you already have a Visual Studio Team Services account</p>

1) Contact support at your workplace for details on using an in house instance of Visual Studio Team Services or Create an individual Visual Studio Team Services account at <a href="https://www.visualstudio.com/team-services/"><span style="font-family: Calibri;font-size: 11.0pt">https://www.visualstudio.com/team-services/</span></a>

&nbsp;
<h2>Install Docker for Windows</h2>

1) Obtain Docker for Windows here <a href="https://www.docker.com/docker-windows"><span style="font-family: Calibri;font-size: 11.0pt">https://www.docker.com/docker-windows</span></a>, It is recommended that you install the stable version 
2) Configure to run Windows Containers

<img width="300" height="186" class="alignnone size-medium wp-image-365" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/DockerRunWindowsContainers-300x186.png" />

&nbsp;
<h2><b>Select an Azure Subscription</b></h2>
You will create all of your assets there: Container repository, Key Value, Service Fabric. Certain steps in this process will fail if you try to cross Subscriptions. Select one and stick with it throughout the entire process.

&nbsp;
<h2><b>Create an Azure Container Registry</b></h2>
This is where the CI/CD workflow will store your containers for Service Fabric to reference.

1) Open <a href="https://portal.azure.com">https://portal.azure.com</a></li>
2) Browse to New Service and select 'Azure Container Service'</li>
3) Select the Azure Subscription chosen to contain all assets</li>

<img width="182" height="300" class="alignnone size-medium wp-image-316" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CreateContainerRegistry-182x300.png" />

4) Select 'Create' and wait for completion. For more information: <a href="https://docs.microsoft.com/en-us/azure/container-registry/">https://docs.microsoft.com/en-us/azure/container-registry/</a>

&nbsp;
<h2><b>Log in to Azure from Powershell</b></h2>
Open an Administrator Powershell session. You will refer to this frequently so leave it open throughout the entire process.

1) Log in to Azure

<code>PS Login-AzureRmAccount</code>

2) List your subscriptions

<code>Get-AzureRmSubscription</code>

3) Change context to the subscription selected to contain all assets

<code>Set-AzureRmContext -SubscriptionId &lt;guid&gt;</code>

&nbsp;
<h2><b>Create a Key Vault</b></h2>
This is where the CI/CD workflow will store your key (from your certificate) for Service Fabric to reference. If you already have a key vault in the selected subscription then feel free to skip over this step.

1) Create resource group for key vault (provide your own values here)

<code>PS C:\WINDOWS\system32&gt; New-AzureRmResourceGroup -Name mwkeyvaultrg -Location 'West US'</code>

<code>ResourceGroupName : mwkeyvaultrg
Location  : westus
ProvisioningState : Succeeded
Tags :
ResourceId  : /subscriptions/00f885db-ef1d-4545-ad2d-64c0caf93356/resourceGroups/mwkeyvaultrg</code>

2) Create key vault (provide your own values here)

<code>PS C:\WINDOWS\system32&gt; New-AzureRmKeyVault -VaultName 'mwkeyvault' -ResourceGroupName 'mwkeyvaultrg' -Location 'West US' -EnabledForDeployment</code>

<code>Vault   : mwkeyvault
Resource Group   : mwkeyvaultrg
Location : West US
Resource   : /subscriptions/00f885db-ef1d-4545-ad2d-64c0caf93356/resourceGroups/mwkeyvaultrg/providers/Microsoft.KeyVault/vaults/mwkeyvault
Vault  : <a href="https://mwkeyvault.vault.azure.net">https://mwkeyvault.vault.azure.net</a>
Tenant ID  : 72f988bf-86f1-41af-91ab-2d7cd011db33
SKU  : Standard
Enabled For Deployment?  : True
Enabled For Template Deployment? : False
Enabled For Disk Encryption?  : False
Access Policies  :
Tenant ID  : 72f988bf-86f1-41af-91ab-2d7cd011db33
Object ID  : 41df24f8-cbe5-4635-bde3-e15c54291f99
Application ID  :
Display Name  : Mark West (markwes@microsoft.com)
Permissions to Keys  : get, create, delete, list, update, import, backup,
restore, recover
Permissions to Secrets  : get, list, set, delete, backup, restore, recover
Permissions to Certificates : get, delete, list, create, import, update,
deleteissuers, getissuers, listissuers, managecontacts, manageissuers, setissuers</code>

&nbsp;
<h2><b>Create a Certificate and Key</b></h2>
You need to create a certificate and key in order to all the CI/CD workflow to interact with Service Fabric. In this step we will create a self-signed certificate and place copies in the local file system and the key store created above.

Fetch ServiceFabricRPHelpers.psm1 from here: <a href="https://github.com/ChackDan/Service-Fabric/tree/master/Scripts/ServiceFabricRPHelpers">https://github.com/ChackDan/Service-Fabric/tree/master/Scripts/ServiceFabricRPHelpers</a>. Place in a directory.  in the example we will use C:\temp\ServiceFabricRPHelpers.

1) Select a directory in which to store certificates, in the example we will use C:\Data\Keys.
2) Return to the Administrator Powershell session opened above
3) Create variable for the following values (provide your own values here)

<code>PS C:\WINDOWS\system32&gt; $ResouceGroup = "mwkeyvaultrg"
PS C:\WINDOWS\system32&gt; $VName = "mwkeyvault"
PS C:\WINDOWS\system32&gt; $SubID = "00f885db-ef1d-4545-ad2d-64c0caf93377"
PS C:\WINDOWS\system32&gt; $locationRegion = "westus"
PS C:\WINDOWS\system32&gt; $newCertName = "cloudmsserfabt1cert1"
PS C:\WINDOWS\system32&gt; $dnsName = "cloudmsserfabt1.westus.cloudapp.azure.com"
PS C:\WINDOWS\system32&gt; $localCertPath = "C:\Data\Keys"</code>

Navigate to parent folder of ServiceFabricRPHelpers.psm1, import, and run Invoke-AddCertToKeyVault

<code>PS cd C:\temp\ServiceFabricRPHelpers
PS C:\temp\ServiceFabricRPHelpers&gt; Import-Module ".\ServiceFabricRPHelpers.psm1"
PS C:\temp\ServiceFabricRPHelpers&gt; Invoke-AddCertToKeyVault -SubscriptionId $SubID -ResourceGroupName $ResouceGroup -Location $locationRegion -VaultName $VName -CertificateName $newCertName -CreateSelfSignedCertificate -DnsName $dnsName -OutputPath $localCertPath</code>

<code>cmdlet Invoke-AddCertToKeyVault at command pipeline position 1
Supply values for the following parameters:
Password: ***
Switching context to SubscriptionId 00f885db-ef1d-4545-ad2d-64c0caf93332
Ensuring ResourceGroup mwkeyvaultrg in westus
Using existing valut mwkeyvault in West US
Creating new self signed certificate at C:\Data\Keys\cloudmsserfabt1cert1.pfx
Reading pfx file from C:\Data\Keys\cloudmsserfabt1cert1.pfx
Writing secret to cloudmsserfabt1cert1 in vault mwkeyvault</code>

<code>Name  : CertificateThumbprint
Value : 25AF2CDFE070D84D7548DFC5382EC73DB007F947</code>

<code>Name  : SourceVault
Value : /subscriptions/00f885db-ef1d-4545-ad2d-64c0caf93321/resourceGroups/mwkeyvaultrg/providers/Microsoft.KeyVault/vaults/mwkeyvault</code>

<code>Name  : CertificateURL
Value : <a href="https://mwkeyvault.vault.azure.net:443/secrets/cloudmsserfabt1cert1/ac8bf2e94fca4d0a88cc9e76d38f3a34">https://mwkeyvault.vault.azure.net:443/secrets/cloudmsserfabt1cert1/ac8bf2e94fca4d0a88cc9e76d38f3a92</a></code>

*** you will be prompted for the certificate password. Supply one and DO NOT FORGET IT. It is up to you to securely store the password by whatever mechanism you choose.

Copy the values for CertificateThumbprint, SourceVault, and CertificateURL. You WILL NEED THESE later.

More information: <a href="https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-cluster-creation-via-arm#create-key-vault">https://docs.microsoft.com/en-us/azure/service-fabric/service-fabric-cluster-creation-via-arm#create-key-vault</a>

&nbsp;
<h2><b>Import Certificate to local cert store</b></h2>
In this step we import the certificate and key into local certificate stores. You will need to import to both the Current User Store and The Local Machine Store. In the example we will demonstrate importing to The Current User Store and leave it up to you to repeat for The Local Machine Store.

1) Navigate to the directory used to store certificates. In our case we are using C:\Data\Keys.
2) Open the certificate file, in our case we are using C:\Data\Keys\cloudmsserfabt1cert1.pfx.

<img width="300" height="296" class="alignnone size-medium wp-image-415" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/OpenCertFile-300x296.png" />

A certificate import wizard will open.

<img width="300" height="294" class="alignnone size-medium wp-image-505" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CertWizard1-300x294.png" />

3) Click Next, leave as is

<img width="300" height="294" class="alignnone size-medium wp-image-506" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CertWizard2-300x294.png" />

4) Click Next, supply password specified in the <b>Create a Certificate and Key</b> step above, check 'Mark this key as exportable' checkbox

<img width="300" height="295" class="alignnone size-medium wp-image-516" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CertWizard3-300x295.png" />

5) Click Next, leave as is

<img width="300" height="293" class="alignnone size-medium wp-image-525" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CertWizard4-300x293.png" />

6) Click Next, then click Finish

<img width="241" height="161" class="alignnone size-full wp-image-535" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CertWizard5.png" />

If all goes well you will see a success message. If not, see <a href="https://msdn.microsoft.com/en-us/library/bb950259(v=bts.10).aspx">https://msdn.microsoft.com/en-us/library/bb950259(v=bts.10).aspx</a> for more information.

&nbsp;
<h2><b>Create a Service Fabric Cluster</b></h2>
Here we create a Service Fabric Cluster to house our containerized apps. As of this date (20170606) it is mandatory to choose a prerelease version of Service Fabric in order to support the CDT (CD/CD Tooling) extension in Visual Studio and that is what we will demonstrate. When the required features go GA, you will not be required to use a pre-release version.

1) Select WindowsServer 2016-Datacenter-with-Containers in the Operating system dropdown
2) Select the Select the Azure Subscription chosen to contain all assets in the Subscription dropdown
3) Select OK

<img width="290" height="300" class="alignnone size-medium wp-image-325" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CreateSerFab1-290x300.png" />

4) Optional + Recommended : Supply an Application Insights key (ref)
5) Select Manual Fabric upgrade mode
6) Select latest preview, in our case 255.255.5718.255 (preview)
7) Select OK

<img width="236" height="300" class="alignnone size-medium wp-image-335" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CreateSerFab2-236x300.png" />

8) Provide the exact values of CertificateThumbprint, SourceVault, and CertificateURL that you obtained in the <b>Create a Certificate and Key</b> step above.
9) Select OK

<img width="300" height="164" class="alignnone size-medium wp-image-345" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CreateSerFab3-300x164.png" />

10) Select Create, wait for completion

<img width="300" height="174" class="alignnone size-medium wp-image-355" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/CreateSerFab4-300x174.png" />

&nbsp;
<h2><b>Edit load balancer</b></h2>
We must configure the Azure Load Balancer of the Service Fabric in order to expose the application endpoint.

1) Open the Resource Group of the Service Fabric

<img width="300" height="165" class="alignnone size-medium wp-image-375" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/EditLoadBalancer1-300x165.png" />

2) Open the Load Balancer

<img width="300" height="251" class="alignnone size-medium wp-image-385" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/EditLoadBalancer2-300x251.png" />

3) Add a Health Probe (note port 80 to match the port of the containerized application)

<img width="300" height="211" class="alignnone size-medium wp-image-395" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/EditLoadBalancer3-300x211.png" />

4) Add a load balancing rule  (note port 80 in and out to match the port of the containerized application). Alternate out ports may be specified to suit your desired configuration.

<img width="269" height="300" class="alignnone size-medium wp-image-405" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/EditLoadBalancer4-269x300.png" />

Note the front end address of <strong>13.64.109.163</strong>

&nbsp;
<h2><b>Create/open app</b></h2>
1) With Visual Studio, open an existing app or create a new one. In our case we will create a new one based on classic ASP.NET Web Forms to fit the pattern of many legacy apps

<img width="300" height="164" class="alignnone size-medium wp-image-435" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/VStudioCreateApp1-300x164.png" />

2) Build and run the app to make sure it is working

<img width="300" height="205" class="alignnone size-medium wp-image-175" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/02/ConnectionDone-300x205.png" />

&nbsp;
<h2><b>Add Docker support</b></h2>
1) Right click on the project to bring up the context menu
2) Select Add -&gt; Docker Support

<img width="300" height="186" class="alignnone size-medium wp-image-445" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/VStudioCreateApp3-300x186.png" />

This will add a file called Dockerfile to the project and a project called docker-compose to the solution

<img width="178" height="300" class="alignnone size-medium wp-image-455" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/VStudioCreateApp4-178x300.png" />

The Dockerfile is like a make file for containers

<code>FROM microsoft/aspnet:4.6.2
ARG source
WORKDIR /inetpub/wwwroot
COPY ${source:-obj/Docker/publish} .</code>

The docker-compose file contains a docker-compose.yml file which describes how containers work together in an application

<code>version: '3'
services:
aspcontserfabcicdt5:
image: aspcontserfabcicdt5
build:
context: .\aspcontserfabcicdt5
dockerfile: Dockerfile</code>

&nbsp;
<h2><b>Edit ports</b></h2>
We need to edit both the Dockerfile  and the docker-compose.yml files in order to expose the application port to the outside network. Without this step the application endpoints will not be reachable from a client outside of the Service Fabric.

1)Edit the Dockerfile to Expose port 80

<code>FROM microsoft/aspnet:4.6.2
ARG source
WORKDIR /inetpub/wwwroot
COPY ${source:-obj/Docker/publish} .
<strong>EXPOSE 80</strong></code>

2) Edit the docker-compose.yml to map internal port 80 to external port 80

<code>version: '3'
services:   aspcontserfabcicdt5:
image: aspcontserfabcicdt5
build:
context: .\aspcontserfabcicdt5
dockerfile: Dockerfile
<strong>ports:</strong>
<strong> - '80:80'</strong></code>

3) Build the solution.

*** If you get this error 'Volume sharing is not enabled. Enable volume sharing in the Docker CE for Windows Settings' then you need to switch Docker to run Windows Containers. See step

&nbsp;
<h2><b>Add solution to source control</b></h2>
1) Hover over the server stack with red X icon at the bottom Visual Studio status bar, this is the CI/CD button.
If your solution is not checked into source control then a tooltip will appear as shown here

<img width="300" height="147" class="alignnone size-medium wp-image-476" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/AddToSourceControl-300x147.png" />

2) Add your solution to your chosen Team Services repo

<img width="300" height="247" class="alignnone size-medium wp-image-485" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/AddToSourceControl2-300x247.png" />

&nbsp;
<h2><b>Add CI/CD</b></h2>
1) Click on the CI/CD Button -&gt; Configure Continuous Delivery

<img width="300" height="153" class="alignnone size-medium wp-image-465" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/AddCiCd1-300x153.png" />

Provide the values in the dialog.

2) First select the subscription chosen in the <b>Select an Azure Subscription</b> step above. All other drop downs will populate allowing you to choose the Target Host and Container registry that you created earlier.
3) The Cluster Certificate Password is the Certificate password that you provided in the <b>Create a Certificate and Key</b> Step above.

<img width="300" height="182" class="alignnone size-medium wp-image-475" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/AddCiCd2-300x182.png" />

4) Select OK. Visual Studio will now create a CI/CD pipeline for you in Team Services
5) Carefully watch the Output Panel for progress and error messages. The example below shows a successful pipeline creation along with information about the definitions which were created. You should record this information.

<code>Setting up CI/CD for project aspcontserfabcicdt5 to Service Fabric Cluster cloudmsprerelt3.....................................done
The continuous build delivery setup for Team Project aspcontserfabcicdt5 completed successfully. Builds are now automatically generated and deployed to Service Fabric Cluster cloudmsprerelt3 upon code updates.
Details:
Service Fabric Cluster: cloudmsprerelt3 fabric:/aspcontserfabcicdt5
VSTS Team Project Name: aspcontserfabcicdt5
VSTS Team Project: <a href="https://markwest.visualstudio.com/aspcontserfabcicdt5">https://markwest.visualstudio.com/aspcontserfabcicdt5</a>
Build Definition: <a href="https://tfs.app.visualstudio.com/A8ecae3e6-5faf-4e4b-93b9-904d82a94a65/_permalink/_build/index?collectionId=8ecae3e6-5faf-4e4b-93b9-904d82a94a80&amp;projectId=6a758b68-dcef-427f-ad15-92d80759a447&amp;definitionId=10">https://tfs.app.visualstudio.com/A8ecae3e6-5faf-4e4b-93b9-904d82a94a113/_permalink/_build/index?collectionId=8ecae3e6-5faf-4e4b-93b9-904d82a94a80&amp;projectId=6a758b34-dcef-427f-ad15-92d80759a447&amp;definitionId=10</a>
Release Definition: <a href="https://markwest.visualstudio.com/6a758b68-dcef-427f-ad15-92d80759a418/_release?definitionId=1">https://markwest.visualstudio.com/6a758b68-dcef-427f-ad15-92d80759a455/_release?definitionId=1</a></code>

6) Team Services will attempt to build and deploy immediately. Check the status of the workflows at the URL of the VSTS Team Project indicated above. In our case this is <a href="https://markwest.visualstudio.com/aspcontserfabcicdt5">https://markwest.visualstudio.com/aspcontserfabcicdt5</a>

<img width="300" height="92" class="alignnone size-medium wp-image-425" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/TeamServicesBuildStatus-300x92.png" />

Here we see the release was successful, which implies that the build was also successful.

&nbsp;
<h2><b>Verify site access</b></h2>
<ul>
 	<li>It may take Azure an hour or more to deploy load balancer changes, so the changes made in the <b>Edit Load Balancer</b> step above may not yet be complete. The site URL will be inaccessible until after the load balancer changes have been fully deployed (i.e. you'll just have to wait).</li>
</ul>
1) Browse to the URL of the load balancer front end address, in this case <a href="https://13.64.109.163">https://13.64.109.163</a>

<img width="300" height="245" class="alignnone size-medium wp-image-495" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/BrowseApp-300x245.png" />

&nbsp;
<h2><b>Check In</b></h2>
The set-up and validation phase is now complete. From now on, whenever you push to the repo, the Build and Release will execute automatically.

To trigger a new build and release changes, just commit + sync + push.

<img width="186" height="300" class="alignnone size-medium wp-image-545" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/Checkin1-186x300.png" />

<img width="185" height="300" class="alignnone size-medium wp-image-555" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/Checkin2-185x300.png" />

<img width="188" height="300" class="alignnone size-medium wp-image-565" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/Checkin3-188x300.png" />

<img width="187" height="300" class="alignnone size-medium wp-image-305" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/Checkin4-187x300.png" />

<img width="189" height="300" class="alignnone size-medium wp-image-315" alt="" src="https://msdnshared.blob.core.windows.net/media/2017/06/Checkin5-189x300.png" />

At this point the code changes are checked in and the build and release processes are underway.

A really great video which covers much of the Visual Studio portion of this process can be found at <a href="https://channel9.msdn.com/Events/Build/2017/P4107" target="_blank">Get my ASP.NET 4 app running in containers in Azure</a>]]></content:encoded>
    </item>
    <item>
      <title>Five tips for moving virtual machine-based apps to Windows Server Containers</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/five-tips-for-moving-virtual-machine-based-apps-to-windows-server-containers</link>
      <pubDate>Wed, 22 Mar 2017 19:30:04 GMT</pubDate>
      <dc:creator><![CDATA[MarkBrianWest]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=265</guid>
      <description><![CDATA[Something with which I've been involved lately showed up on IT Showcase :-)
Five tips for moving...]]></description>
      <content:encoded><![CDATA[Something with which I've been involved lately showed up on IT Showcase :-)
<a href="https://www.microsoft.com/itshowcase/blog/five-tips-for-moving-virtual-machine-based-apps-to-windows-server-containers/">Five tips for moving virtual machine-based apps to Windows Server Containers</a>]]></content:encoded>
    </item>
    <item>
      <title>Visual Studio 2017 : client version 1.22 is too old</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/visual-studio-2017-client-version-1-22-is-too-old</link>
      <pubDate>Mon, 13 Mar 2017 16:35:13 GMT</pubDate>
      <dc:creator><![CDATA[MarkBrianWest]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=245</guid>
      <description><![CDATA[This might come in handy when building with Containers in Visual Studio 2017

I created a...]]></description>
      <content:encoded><![CDATA[This might come in handy when building with Containers in <strong>Visual Studio 2017</strong>

I created a containerized asp.net core app and I got this exception: "<code>Microsoft.DotNet.Docker.CommandLineClientException: client version 1.22 is too old. Minimum supported API version is 1.24, please upgrade your client to a newer version</code>." on the first build right out of the gate using just what the IDE gave me from the output of the app template.

This is on a <strong>Windows 10</strong> platform with <strong>Docker For Windows</strong>:
<code>Microsoft Windows [Version 10.0.14393]
(c) 2016 Microsoft Corporation. All rights reserved.
C:\Windows\system32&gt;docker-compose version
docker-compose version 1.11.2, build f963d76f
docker-py version: 2.1.0
CPython version: 2.7.13
OpenSSL version: OpenSSL 1.0.2j  26 Sep 2016</code>
<div>You can get the details of your environment by typing <code>docker-compose version</code> at the command line.</div>
I'll spare you the details of how and why, I fixed it by changing
<code>version:'2'</code> to <code>version:'2.1'</code> in the two <b>docker-compose</b> project files that Visual Studio adds to your solution when you enable container support:

<b>docker-compose.ci.build.yml</b>
<b>docker-compose.yml</b>

Your mileage may vary.]]></content:encoded>
    </item>
    <item>
      <title>Remediate Multi-tenancy Port Collision -or- How I put Multiple Container Websites is a single VM / Scaleset</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/remediate-multi-tenancy-port-collision</link>
      <pubDate>Tue, 14 Feb 2017 13:38:37 GMT</pubDate>
      <dc:creator><![CDATA[MarkBrianWest]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=195</guid>
      <description><![CDATA[Many apps (legacy and modern) provide service interfaces on TCP ports. Many of these service...]]></description>
      <content:encoded><![CDATA[Many apps (legacy and modern) provide service interfaces on TCP ports. Many of these service interfaces expect to reside on a well-known port, for example HTTP (80) and HTTPS(443). The current implementation of Windows Containers employs a port mapping mechanism to expose ports running on the container to access from outside the container, and any other access from the  network to the container is blocked. All access to the services on the container must be made via a mapped port on the container host. Obviously port numbers cannot be shared by multiple services, so each service must map to a unique port number. This is usually a blocker, especially with HTTP clients which usually expect to operate on the well-known ports. We will demonstrate how to use the <a target="_blank" href="https://azure.microsoft.com/en-us/services/load-balancer/"><span style="color: #337ab7">Azure Load Balancer </span></a>to resolve this issue.

<h2>Step by Step</h2>
In this step-by-step we will:
<ol>
 	<li>create two containers running IIS on a container host in Azure</li>
 	<li>configure an Azure Load Balancer to reference the web sites on the containers</li>
</ol>
<strong>Create two containers running on a single Host.</strong>

- start a Powershell admin session on the container host

- Create two containers

<code>docker run -it --name Site1 -p 81:80 -v c:\shared:c:\shared  microsoft/dotnet-framework:4.6.2</code>

<code>docker run -it --name site2 -p 82:80 -v c:\shared:c:\shared  microsoft/dotnet-framework:4.6.2</code>

<strong>In this example we will assume the following IP Addresses</strong>

Container Host IP: 10.138.137.183

Internal IP: Site1 : 172.28.103.94

Internal IP: Site2 : 172.28.104.223

&nbsp;

&nbsp;
<h2>Load Balancer Configuration (Option 1: Azure Portal)</h2>
<strong>Front End IP Pool</strong>

Each Tenant should have a Virtual IP created, and DNS configured to resolve to that Front IP. In the example below we have site1 and site2 setup with their individual Public IP's assigned from the Virtual network to which the Load balancer is connected.

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/FrontEndIpPool.png" />

<strong>Backend Pools</strong>

In the below example we have a single VM in the backend pool. To achieve HA and Load balancing, we would create multiple VMs in the same Availability set. The backend pool would be set to this Availability set. If the same container is placed on the hosts in the Availability set. Requests will be loaded balanced across those machines.

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/BackendPools.png" />

<strong>Health Probes</strong>

Each site on the container host has a container listening on the hosts port. We need to setup a probe for those ports. In the example below, we have a container running on Container IP: port 80, mapped to the Host IP: Ports 81 &amp; 82, and the host has a site on port 80. The health probes will mark those Hosts as "up" if they are responding on these ports.

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/HealthProbes.png" />

<strong>Load balancing Rules</strong>

Each Site will need a Load balancing rule to map the Virtual IP:port tuple to the HostIP: Port. Inside the container host the Host IP: port is mapped to the Container IP: port.

In the example below we also route the Virtual IP:80 to the Host:80. We then route site 1 virtual IP and port 80 to the host: port 81, and site 2 virtual IP and port 80 to the host: port 82.
<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/LoadBalancingRules.png" />
<h2></h2>
<h2></h2>
<h2>Load Balancer Configuration (Option 2: Azure Powershell)</h2>
Script:

<a href="https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-get-started-ilb-arm-ps">https://docs.microsoft.com/en-us/azure/load-balancer/load-balancer-get-started-ilb-arm-ps</a>

---Create Script starts---

<b>Connect to Subscription: </b>

<code>Login-AzureRmAccount
Select-AzureRmSubscription -Subscriptionid "GUID of subscription"
New-AzureRmResourceGroup -Name NRP-RG -location "West US" </code>

<b>Create Virtual IP and Backend Pool: </b>

<code>$frontendIP1 = New-AzureRmLoadBalancerFrontendIpConfig -Name LB-Frontend -PrivateIpAddress 10.0.2.5 -SubnetId $vnet.subnets[0].Id
$frontendIP2 = New-AzureRmLoadBalancerFrontendIpConfig -Name LB-Frontend -PrivateIpAddress 10.0.2.5 -SubnetId $vnet.subnets[0].Id </code>

<code>$beaddresspool= New-AzureRmLoadBalancerBackendAddressPoolConfig -Name "BackendPool" </code>

<b>For RDP access to hosts: </b>

<code>$inboundNATRule1= New-AzureRmLoadBalancerInboundNatRuleConfig -Name "RDP1" -FrontendIpConfiguration $frontendIP -Protocol TCP -FrontendPort 3441 -BackendPort 3389
$inboundNATRule2= New-AzureRmLoadBalancerInboundNatRuleConfig -Name "RDP2" -FrontendIpConfiguration $frontendIP -Protocol TCP -FrontendPort 3442 -BackendPort 3389 </code>

<b>Create Health Probes and IB rules: </b>

<code>$healthProbe0 = New-AzureRmLoadBalancerProbeConfig -Name "Port80"  -Protocol tcp -Port 80 -IntervalInSeconds 15 -ProbeCount 2
$healthProbe1 = New-AzureRmLoadBalancerProbeConfig -Name "Port81"  -Protocol tcp -Port 81 -IntervalInSeconds 15 -ProbeCount 2
$healthProbe2 = New-AzureRmLoadBalancerProbeConfig -Name "Port82"  -Protocol tcp -Port 82 -IntervalInSeconds 15 -ProbeCount 2 </code>

<code>$lbrule = New-AzureRmLoadBalancerRuleConfig -Name "Host" -FrontendIpConfiguration $frontendIP1 -BackendAddressPool $beAddressPool -Probe
$healthProbe1 -Protocol Tcp -FrontendPort 8080 -BackendPort 80 </code>

<code>$lbrule = New-AzureRmLoadBalancerRuleConfig -Name "Site1" -FrontendIpConfiguration $frontendIP1 -BackendAddressPool $beAddressPool -Probe
$healthProbe1 -Protocol Tcp -FrontendPort 80 -BackendPort 81 </code>

<code>$lbrule = New-AzureRmLoadBalancerRuleConfig -Name "Site2" -FrontendIpConfiguration $frontendIP2 -BackendAddressPool $beAddressPool -Probe
$healthProbe1 -Protocol Tcp -FrontendPort 80 -BackendPort 82 </code>

---Create Script ends---

---Add Script starts---

<b>Connect to Subscription: </b>

<code>Login-AzureRmAccount
Select-AzureRmSubscription -Subscriptionid "GUID of subscription" </code>

<b>Create Virtual IP and Health Probe: </b>

<code>$Subnet = Get-AzureRmVirtualNetwork -Name [vnet name]  -ResourceGroupName ERNetwork | Get-AzureRmVirtualNetworkSubnetConfig –Name "subnet-1" </code>

<code>Get-AzureRmLoadBalancer -Name [ilbname]  -ResourceGroupName [resource group name] | Add-AzureRmLoadBalancerFrontendIpConfig -Name "Site3" -Subnet $Subnet | Set-AzureRmLoadBalancer </code>

<code>$ilb = Get-AzureRmLoadBalancer -Name [ilb name]  -ResourceGroupName [resource group name] </code>

<code>$beaddresspool= get-AzureRmLoadBalancerBackendAddressPoolConfig -Name "BackendPool" -LoadBalancer $ilb </code>

<code>add-AzureRmLoadBalancerProbeConfig -Name "Port83"  -Protocol tcp -Port 83 -IntervalInSeconds 15 -ProbeCount 2 -LoadBalancer $ilb  </code>

<code>$ilb | Set-AzureRmLoadBalancer </code>

<b>Create the LB rule: </b>

<code>$healthProbe3 = Get-AzureRmLoadBalancerProbeConfig -Name "Port83" -LoadBalancer $ilb </code>

<code>$frontIP3 = Get-AzureRmLoadBalancerFrontendIpConfig -Name site3 -LoadBalancer $ilb  </code>

<code>$ilb | add-AzureRmLoadBalancerRuleConfig -Name "site3" -FrontendIPConfiguration $frontIP3 -Protocol "Tcp" -FrontendPort 80 -BackendPort 83 -BackendAddressPool $beaddresspool -Probe $healthProbe3 </code>

<code>$ilb | Set-AzureRmLoadBalancer </code>

---Add Script ends---

&nbsp;

&nbsp;
<h2>Test Site Access</h2>
All three sites should be available from the network on port 80

<strong>Host Site:</strong> https://10.138.137.183:80

<strong>Container Site1:</strong>  https://10.138.137.166:80

<strong>Container Site2:</strong>  https://10.138.137.170:80]]></content:encoded>
    </item>
    <item>
      <title>Manage IIS on a Container with the IIS Admin Console</title>
      <link>https://docs.microsoft.com/archive/blogs/containerstuff/manage-iis-on-a-container-with-the-iis-admin-console</link>
      <pubDate>Tue, 14 Feb 2017 12:36:21 GMT</pubDate>
      <dc:creator><![CDATA[MarkBrianWest]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/containerstuff/?p=75</guid>
      <description><![CDATA[Many legacy apps are based on IIS and ship with documentation which describes deployment and...]]></description>
      <content:encoded><![CDATA[Many legacy apps are based on IIS and ship with documentation which describes deployment and management operations primarily via the <a target="_blank" href="https://msdn.microsoft.com/en-us/library/bb756935.aspx"><span style="color: #337ab7">IIS Manager</span></a>. This console is a GUI. Windows Containers do not support any form of GUI, so all ‘local’ operations must be performed via a command line interface. We will demonstrate how to prepare containers for IIS administration via a remote instance of the IIS Manager.

<h2>Step by Step</h2>
In this step-by-step we will:
<ol>
 	<li>create a container based on an image with IIS already installed</li>
 	<li>add remote IIS admin support to the container</li>
 	<li>connect to the IIS admin console on the container host to the IIS Admin Service service the container</li>
</ol>
<u>On the container host:</u>

- Open a PowerShell admin session

- Start interactive container

- With .net 3.5 -

<code>docker run -it --name frame35 cd\-v c:\shared:c:\shared microsoft/dotnet-framework:3.5</code>

- with .net 4.6.2 -

<code>docker run -it --name frame46 -v c:\shared:c:\shared microsoft/dotnet-framework:4.6.2</code>

- or start detached and then attach to container -

<code>docker run --name &lt;name&gt; -d=true -v c:\shared:c:\shared microsoft/windowsservercore:latest</code>

<code>docker attach &lt;name&gt;</code>

Note: To add Active Directory support to any container, add <code>--security-opt "credentialspec=file://&lt;CredentialSpecName&gt;.json"</code> to the docker run command line. See &lt;ref&gt; for more details.

i.e. <code>docker run -it --name frame46 -v c:\shared:c:\shared --security-opt "credentialspec=file://adoncontt1.json" microsoft/dotnet-framework:4.6.2</code>

This will switch the console from container host to container. This is now the 'container console'.

<u>From container console:</u>

Start Admin PowerShell

<code>Powershell</code>

- Install IIS + IIS Management

<code>Install-WindowsFeature -name Web-Server -IncludeManagementTools</code>

- Install IIS Management Service

<code>Dism /online /enable-feature /featurename:IIS-ManagementService /all</code>

- Enable remote access

<code>New-ItemProperty -Path HKLM:\software\microsoft\WebManagement\Server -Name EnableRemoteManagement -Value 1 -Force</code>

--- optional - add any or all of these features ----------------------------

<code>Import-Module Dism</code>

<code>Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebServerRole
Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebServer
Enable-WindowsOptionalFeature -Online -FeatureName IIS-CommonHttpFeatures
Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpErrors
Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpRedirect
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ApplicationDevelopment
Enable-WindowsOptionalFeature -Online -FeatureName IIS-NetFxExtensibility
Enable-WindowsOptionalFeature -Online -FeatureName IIS-NetFxExtensibility45
Enable-WindowsOptionalFeature -Online -FeatureName IIS-HealthAndDiagnostics
Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpLogging
Enable-WindowsOptionalFeature -Online -FeatureName IIS-LoggingLibraries
Enable-WindowsOptionalFeature -Online -FeatureName IIS-RequestMonitor
Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpTracing
Enable-WindowsOptionalFeature -Online -FeatureName IIS-Security
Enable-WindowsOptionalFeature -Online -FeatureName IIS-URLAuthorization
Enable-WindowsOptionalFeature -Online -FeatureName IIS-RequestFiltering
Enable-WindowsOptionalFeature -Online -FeatureName IIS-IPSecurity
Enable-WindowsOptionalFeature -Online -FeatureName IIS-Performance
Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpCompressionDynamic
Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebServerManagementTools
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ManagementScriptingTools
Enable-WindowsOptionalFeature -Online -FeatureName IIS-IIS6ManagementCompatibility
Enable-WindowsOptionalFeature -Online -FeatureName IIS-Metabase
Enable-WindowsOptionalFeature -Online -FeatureName IIS-HostableWebCore
Enable-WindowsOptionalFeature -Online -FeatureName IIS-CertProvider
Enable-WindowsOptionalFeature -Online -FeatureName IIS-WindowsAuthentication
Enable-WindowsOptionalFeature -Online -FeatureName IIS-DigestAuthentication
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ClientCertificateMappingAuthentication
Enable-WindowsOptionalFeature -Online -FeatureName IIS-IISCertificateMappingAuthentication
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ODBCLogging
Enable-WindowsOptionalFeature -Online -FeatureName IIS-StaticContent
Enable-WindowsOptionalFeature -Online -FeatureName IIS-DefaultDocument
Enable-WindowsOptionalFeature -Online -FeatureName IIS-DirectoryBrowsing
Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebDAV
Enable-WindowsOptionalFeature -Online -FeatureName IIS-WebSockets
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ApplicationInit
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ASPNET
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ASPNET45
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ASP
Enable-WindowsOptionalFeature -Online -FeatureName IIS-CGI
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ISAPIExtensions
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ISAPIFilter
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ServerSideIncludes
Enable-WindowsOptionalFeature -Online -FeatureName IIS-CustomLogging
Enable-WindowsOptionalFeature -Online -FeatureName IIS-BasicAuthentication
Enable-WindowsOptionalFeature -Online -FeatureName IIS-HttpCompressionStatic
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ManagementConsole
Enable-WindowsOptionalFeature -Online -FeatureName IIS-ManagementService
Enable-WindowsOptionalFeature -Online -FeatureName IIS-WMICompatibility
Enable-WindowsOptionalFeature -Online -FeatureName IIS-LegacyScripts
Enable-WindowsOptionalFeature -Online -FeatureName IIS-LegacySnapIn
Enable-WindowsOptionalFeature -Online -FeatureName IIS-FTPServer
Enable-WindowsOptionalFeature -Online -FeatureName IIS-FTPSvc
Enable-WindowsOptionalFeature -Online -FeatureName IIS-FTPExtensibility</code>

---------------------------------

- Stop Services

<code>net stop Iisadmin
net stop W3svc
net stop wmsvc</code>

- Start Services

<code>net start Iisadmin
net start W3svc
net start wmsvc</code>

- add admin user

<code>net user &lt;username&gt; &lt;password&gt; /ADD
net localgroup administrators &lt;username&gt; /add</code>

Open another PS admin session on the container host, this will be the new 'container <b>host</b> console'

<u>From container<b> host</b> console:</u>

- List containers

<code>Docker ps</code>

- Note containerID

&nbsp;

- Find container IP address

<code>docker inspect -f "{{ .NetworkSettings.Networks.nat.IPAddress }}" &lt;container id&gt;</code>

This will display the container IP address, copy it.

<u>From container host desktop:</u>

- Start IIS manager console

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/StartIisConsole.png" />

- Select 'Connect to a Server', Connect to container IP address

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/SpecifyAddress.png" />

&nbsp;

- Provide the &lt;name&gt; and &lt;password&gt; provided above in [net user &lt;username&gt; &lt;password&gt; /ADD]

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/SpecifyCredentials.png" />

&nbsp;

- Click on Next. You will get a certificate error dialog

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/CertError.png" />

&nbsp;

- Click 'View Certificate'. You will get a 'Certificate' Dialog

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/CertDetails.png" />

&nbsp;

- Click 'Install Certificate'. You will get a certificate import wizard

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/CertExport.png" />

&nbsp;

- Select 'Local Machine', click 'Next'

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/CertImport2.png" />

&nbsp;

- Select 'Place all certificates in the following store', click 'Browse', select 'Trusted Root Certification Authorities', click 'OK', nick 'Next'

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/CertImport3.png" />

&nbsp;

Click 'Finish'

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/CertImport4.png" />

&nbsp;

- Click 'Cancel'

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/SpecifyCredentials.png" />

&nbsp;

- Click 'Next'. The screen below indicates success. Others screens may indicate error.

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/ConnectionName.png" />

&nbsp;

- You may now administer the IIS service running on the container from the IIS admin console running on the container host.

<img alt="Start IIS Console" src="https://msdnshared.blob.core.windows.net/media/2017/02/ConnectionDone.png" />

&nbsp;]]></content:encoded>
    </item>
  </channel>
</rss>