<?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>Steve Lasker's Web Log - https://SteveLasker.blog</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/stevelasker/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/stevelasker/feed.xml</link>
    <description>Cheese has been moved to https://SteveLasker.blog</description>
    <lastBuildDate>Wed, 02 Jan 2019 21:01:45 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Moving the cheese - SteveLasker.blog</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/moving-the-cheese-stevenlasker-blog</link>
      <pubDate>Mon, 31 Dec 2018 01:30:25 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2665</guid>
      <description><![CDATA[Microsoft is retiring personal MSDN blogs. As a result, I've moved all my blog content...]]></description>
      <content:encoded><![CDATA[Microsoft is retiring personal MSDN blogs. As a result, I've moved all my blog content to:

<a href="https://SteveLasker.blog">https://SteveLasker.blog </a>

I hope you'll keep the great feedback coming there.

Steve

&nbsp;]]></content:encoded>
    </item>
    <item>
      <title>ACR Build (Preview) Now Supported In All Public Regions</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/acr-build-preview-now-supported-in-all-public-regions</link>
      <pubDate>Wed, 25 Jul 2018 22:15:23 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2595</guid>
      <description><![CDATA[ACR Build, a native container build capability of the Azure Container Registry is now available in...]]></description>
      <content:encoded><![CDATA[<a target="_blank" href="https://aka.ms/acr/build" rel="noopener">ACR Build</a>, a native container build capability of the <a target="_blank" href="https://aka.ms/acr" rel="noopener">Azure Container Registry</a> is now available <strong>in all regions ACR is available</strong>. That's <strong>23</strong> regions worldwide as of July 23rd 2018.

ACR Build enables network close builds, alongside your container registry. While docker has an efficient image layering scheme, image layers can grow in size. Reducing the network distance your image pull and push operations must travel is key to improving reliability, speed and reducing network egress costs.

Wherever you run your Azure Container Registry, you can now build Linux, Windows and ARM right alongside.
<h2>OS &amp; Framework Patching of Containers</h2>
<img src="https://msdnshared.blob.core.windows.net/media/2018/07/ACRBuildEverywhere-1024x612.png" alt="" width="700" class="aligncenter size-large wp-image-2625" />
ACR Build is primarily focused on the container lifecycle management challenge. ACR Build supports:
<ul>
 	<li>builds from your local directory <a target="_blank" href="https://docs.microsoft.com/en-us/cli/azure/acr?view=azure-cli-latest#az-acr-build" rel="noopener"><code>az acr build .</code></a></li>
 	<li>git commit based builds <a target="_blank" href="https://docs.microsoft.com/en-us/cli/azure/acr/build-task?view=azure-cli-latest#az-acr-build-task-create" rel="noopener"><code>az acr build-task create</code></a></li>
 	<li>base image updates, providing <a target="_blank" href="https://blogs.msdn.microsoft.com/stevelasker/2017/12/20/os-framework-patching-with-docker-containers-paradigm-shift/" rel="noopener">Container OS &amp; Framework patching</a></li>
</ul>
ACR Build is currently in preview, incorporating feedback. Based on feedback, we've recently enabled:
<ul>
 	<li>remote context, such as an existing git repository with nested folders
<code>az acr build \
-t hello-acr:{{.Build.ID}} \
https://github.com/Azure-Samples/acr-helloworld.git</code>
and nested folders
<code>az acr build \
-t hello-world-of-windows:{{.Build.ID}} \
https://github.com/AzureCR/acr-builder-os-tests.git#master:Windows/Servercore</code></li>
 	<li>multi-tagging support <code>-t image1:{{.Build.ID}} -t image1:latest</code></li>
 	<li>ARM support</li>
 	<li><a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows" rel="noopener">Windows support</a></li>
 	<li>{{.Build.Date}} is coming soon</li>
</ul>
Watch more on Azure Friday with Lara Rubbelke
<iframe width="960" height="540" src="https://channel9.msdn.com/shows/azure-friday/ACR-Build-Automate-Docker-builds-with-OS-and-framework-patching/player" allowfullscreen="allowfullscreen" frameborder="0"></iframe>

Give it a try. Tell us what you need.
<h3>For more information</h3>
<ul>
 	<li><a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows" rel="noopener"></a><a target="_blank" href="https://aka.ms/acr/build" rel="noopener">ACR Build Docs (https://aka.ms/acr/build)</a></li>
 	<li><a href="https://aka.ms/acr/uservoice">ACR Uservoice (https://aka.ms/acr/uservoice)</a></li>
 	<li><a target="_blank" href="https://aka.ms/acr/roadmap" rel="noopener">ACR Roadmap (https://aka.ms/acr/roadmap)</a></li>
 	<li><a target="_blank" href="https://aka.ms/acr/issues" rel="noopener">ACR Issues (https://aka.ms/acr/issues)</a></li>
 	<li><a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows" rel="noopener">ACR Build OS Tests (https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows)</a></li>
</ul>
Any other feedback, feel free to leave larger comments here, user voice, twitter (<a target="_blank" href="https://twitter.com/SteveLasker" rel="noopener">@SteveLasker</a>)

Thanks,
Steve and the great members of the ACR team]]></content:encoded>
    </item>
    <item>
      <title>Azure Container Registry Build Supports All Windows Versions (Preview of Preview)</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/acr-build-supports-windows-preview</link>
      <pubDate>Mon, 16 Jul 2018 23:00:50 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2565</guid>
      <description><![CDATA[ACR Build, a cloud-native container build capability of the Azure Container Registry now supports...]]></description>
      <content:encoded><![CDATA[<a target="_blank" href="https://aka.ms/acr/build" rel="noopener">ACR Build</a>, a cloud-native container build capability of the <a target="_blank" href="https://aka.ms/acr" rel="noopener">Azure Container Registry</a> now supports all supported versions of Windows Containers.

In May of 2018, Azure announced ACR Build (Preview), a component of Azure's <a target="_blank" href="https://azure.microsoft.com/en-us/blog/azure-container-registry-makes-geo-replication-generally-available-adding-lifecycle-management-capabilities/" rel="noopener">OS &amp; Framework Container Life-cycle Management</a> Today, we wanted to give customers early access to Windows Builds, in addition to the Linux and ARM builds customers could do since last May.
<h2>ACR Build Enables All Supported Versions of Windows Containers</h2>
The most significant element of Windows support is the support for all supported version of Windows, <a target="_blank" href="https://hub.docker.com/r/microsoft/windowsservercore/" rel="noopener">including ltsc2016, 1709 and 1803</a>. In addition to Windows Server Core, Nano Server is also supported by ACR Build.

A suite of tests for Windows containers are available here: <a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows" rel="noopener">https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows</a>
<h2>What is (Preview of Preview)</h2>
Updates to the <strong>az cli</strong> will not be publicly available until July 31. There are two ways to get ACR Build for Windows Container support today (July 16th, 2018)
<ol>
 	<li>Create a <a target="_blank" href="https://docs.microsoft.com/en-us/cli/azure/acr?view=azure-cli-latest#az-acr-build-task" rel="noopener">build task</a> with the public <strong>az cli</strong>
build-task already supports the <code>--os</code> parameter, so you're good to go if you just want build-tasks</li>
 	<li>To use <code>az acr build</code>; the equivalent of <code>docker build</code>, use a preview build of the <strong>az cli</strong>, which can be
<ol>
 	<li>installed directly: <a target="_blank" href="https://github.com/Azure/azure-cli#edge-builds" rel="noopener">https://github.com/Azure/azure-cli#edge-builds</a></li>
 	<li>or with a docker image: <a target="_blank" href="https://github.com/Azure/azure-cli#docker" rel="noopener">https://github.com/Azure/azure-cli#docker</a>
<code>docker run -v <span class="pl-smi">${HOME}</span>:/root -it azuresdk/azure-cli-python:dev</code></li>
</ol>
</li>
</ol>
<h2>A quick test</h2>
We'll use the most consistent way, a docker container of the dev builds of the <strong>az cli</strong>
<ul>
 	<li>On Windows, or Mac, instance a docker container, running the latest dev build, including updates to <code>az acr build </code>
<code>docker run -v ${HOME}:/root -it azuresdk/azure-cli-python:dev</code></li>
 	<li><strong>Note</strong>: ACR Build is currently supported:
<ul>
 	<li>East US</li>
 	<li>West Europe</li>
 	<li>Central US</li>
 	<li>South Central US
More regions are coming on weekly, with full global coverage coming "soon"</li>
</ul>
</li>
 	<li>Build a Windows Server Core image, with a .NET Framework app
<code>az acr build \
-t helloworld-windowsservercore:multi-arch-{{.Build.ID}} \
-f helloworld-windowsservercore/multi-arch.Dockerfile \
--os windows \
https://github.com/AzureCR/acr-builder-os-tests.git#master:Windows/Servercore</code></li>
</ul>
How this works:
<ul>
 	<li><code>az acr build</code> is the functional equivalent of <code>docker build</code>. Rather than having to install the docker client, <code>az acr build</code> sends the context to an ACR Build server in Azure</li>
 	<li><code>-t</code> uses the <a target="_blank" href="https://docs.docker.com/engine/reference/commandline/build/#tag-an-image--t" rel="noopener">standard docker tag</a>, with the added ability to get a unique build id.</li>
 	<li><code>-f</code> uses the <a target="_blank" href="https://docs.docker.com/engine/reference/commandline/build/#specify-a-dockerfile--f" rel="noopener">standard dockerfile syntax </a>to reference a Dockerfile that isn't in the root of the context</li>
 	<li><code>--os</code> tells ACR Build to use a Windows host. As many FX and platform tags are multi-arch, this parameter is required to specify which OS you require for <code>docker build</code></li>
 	<li><code>https://github...</code> is a remote context for the build. While <code>.</code> is supported for a local directory, acr build and build-task can also specify remote git repos, avoiding the necessity of first git clone</li>
</ul>
Since this references the <a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/blob/master/Windows/Servercore/helloworld-windowsservercore/multi-arch.Dockerfile" rel="noopener">multi-arch tag for Windows and the .NET Framework</a>, this will produce an 1803 version of Windows Server Core. To get a specific windows version, use the following:
<ul>
 	<li><em></em><strong>Windows Server</strong> 1709, using the <a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/blob/master/Windows/Servercore/helloworld-windowsservercore/1709.Dockerfile" rel="noopener">1709.Dockerfile</a>
<code>az acr build \
-t helloworld-windowsservercore:1709-{{.Build.ID}} \
-f helloworld-windowsservercore/1709.Dockerfile \
--os windows \
https://github.com/AzureCR/acr-builder-os-tests.git#master:Windows/Servercore</code></li>
 	<li>Windows <strong>Nano Server</strong> 1709, using the <a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/blob/master/Windows/Nanoserver/helloworld-nanoserver/1709.Dockerfile" rel="noopener">1709.Dockerfile </a>for Nano Server and .NET Core
<code>az acr build \
-t helloworld-nanoserver:1709-{{.Build.ID}} \
-f helloworld-nanoserver/1709.Dockerfile \
--os windows \
https://github.com/AzureCR/acr-builder-os-tests.git#master:Windows/Nanoserver</code></li>
</ul>
<h2>Automated Build Tasks, based on Git Commits, or Based Image Updates</h2>
The primary scenario for ACR Build revolves around Container OS &amp; Framework patching. Just as your builds kick off, based on git-commit changes, as base images are patched, your builds can also be triggered.

See <a target="_blank" href="https://aka.ms/acr/build" rel="noopener">Overview of ACR Build, targeting OS &amp; Framework Patching </a>for more details.
<h3>Creating automated builds</h3>
Note: this can be done directly with the publicly released <strong>az cli</strong>, however, we'll use the <strong>az cli docker image</strong> for consistency.
<ul>
 	<li>Fork the <a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests" rel="noopener">https://github.com/AzureCR/acr-builder-os-tests </a>repo</li>
 	<li>Create a <a target="_blank" href="https://github.com/settings/tokens" rel="noopener">Personal Access Token</a>.
For more info, see the <a target="_blank" href="https://docs.microsoft.com/en-us/azure/container-registry/container-registry-tutorial-build-task#create-a-build-task" rel="noopener">ACR Build Docs for creating a build task.</a></li>
 	<li>Set the PAT to an environment variable
<code>PAT=[pastePAT]</code></li>
 	<li>Create an acr build-task
<code>az acr build-task create \
-n HelloworldWinServercoreLtsc2016 \
-t helloworld-windowsservercore:ltsc2016-{{.Build.ID}} \
-f helloworld-windowsservercore/ltsc2016.Dockerfile \
-c https://github.com/AzureCR/acr-builder-os-tests.git#master:Windows/Servercore \
--os windows \
--git-access-token <span class="pl-smi">$PAT</span></code></li>
 	<li>Trigger a build manually
<code>az acr build-task run HelloworldWinServercoreLtsc2016</code></li>
</ul>
<h3>For more information</h3>
<ul>
 	<li><a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows" rel="noopener"></a><a target="_blank" href="https://aka.ms/acr/build" rel="noopener">ACR Build Docs (https://aka.ms/acr/build)</a></li>
 	<li><a href="https://aka.ms/acr/uservoice">ACR Uservoice (https://aka.ms/acr/uservoice)</a></li>
 	<li><a target="_blank" href="https://aka.ms/acr/roadmap" rel="noopener">ACR Roadmap (https://aka.ms/acr/roadmap)</a></li>
 	<li><a target="_blank" href="https://aka.ms/acr/issues" rel="noopener">ACR Issues (https://aka.ms/acr/issues)</a></li>
 	<li><a target="_blank" href="https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows" rel="noopener">ACR Build OS Tests (https://github.com/AzureCR/acr-builder-os-tests/tree/master/Windows)</a></li>
</ul>
Any other feedback, feel free to leave larger comments here, user voice, twitter (<a target="_blank" href="https://twitter.com/SteveLasker" rel="noopener">@SteveLasker</a>)

Thanks,
Steve and the great members of the ACR team]]></content:encoded>
    </item>
    <item>
      <title>Key Differences between VM and Container Vulnerability Scanning</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/key-differences-between-vm-and-container-vulnerability-scanning</link>
      <pubDate>Wed, 27 Jun 2018 20:22:10 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2535</guid>
      <description><![CDATA[As we explore the various options for integrating vulnerability scanning into containers running in...]]></description>
      <content:encoded><![CDATA[As we explore the various options for integrating vulnerability scanning into containers running in Azure, we encountered many different approaches and requests. I was initially writing a document for internal discussions, outlining some of our internal goals for how we want to think about container security, and why we might take one approach or another. While I'd suggest Azure has the best breadth and depth of containers in any of the major clouds, we are a large company, and not everyone is familiar with containers. In our busy lives, we only have a few seconds of mental processing, before we look to apply what we've just learned to the problems we have. Containers solve many problems, some more short term than others. However, until you've inverted your thought process, and think about a container-first mindset, you'll find yourself using a new tech as a better tool, but not nearly unlocking its potential.

As I wrote the document, there are lots of details and examples I wanted to outline to help people think about vulnerability from a container first mindset. Many of which represent opinions, or "best practices". As I wrote the <a target="_blank" href="https://blogs.msdn.microsoft.com/stevelasker/2018/03/01/docker-tagging-best-practices-for-tagging-and-versioning-docker-images/" rel="noopener">Docker tagging best practices for tagging and versioning docker-images</a> post, I thought about what makes a best practice for a new and rapidly evolving technology?

I don't consider myself a security expert, and I certainly don't play one on Twitter. I have worked in the industry for many years and have watched the balance of secure, usable and practical. We don't always get these right. And I don't believe the concept that something must be hard to be secure. I believe in good, obvious processes and realistic expectations for making something secure. After all, what's the first thing developers do when security gets in the way? ...we disable it. Not a very secure result, now is it?

To put some context to this paradigm shift, below are a number of concepts to consider when you think about adopting a container scanning solution. Just because something has been done a certain way for years, doesn't mean it's still relevant.
<h1>Virtual Machine and Container Differences</h1>
Below are several concepts we think about when running compute. I've provided a <strong>VM</strong> centric and <strong>Container</strong> centric view to each one.
<blockquote>Container Bigot Disclaimer: For those working with products like Vagrant, Terraform and other awesome products that automate VM creation; this isn't meant to suggest the challenges couldn't/aren't addressed with them. And while I'm far to say <a target="_blank" href="https://youtu.be/2fW5Z2z6pXM?t=76" rel="noopener">anything you can do in a VM, I can do better in a container</a>, I think we all recognize containers, and specifically Docker has brought about the next foundational shift in how we package and run software.</blockquote>
<h2>Where Is Fast a Priority</h2>
<strong>VM
</strong>VMs are typically measured in the length of up-time. How long was the VM running before it had to be rebooted or retired? While startup time is always important, VM startup time is typically measured in minutes. As long as they come up in single digits, they’re considered “the norm”.

<strong>Container
</strong>Containers are assumed to be relatively short-lived processes. They may be long running services, like websites or APIs, but the expectation is they get moved, updated, scaled with far more frequency.
Containers are measured in the number of seconds, or preferably milliseconds from the time of docker run to processing requests. Customers are also looking for docker pull to complete in seconds, reducing the amount of time to run a new image on a new node.
Considering containers are becoming the base of functions, where a workflow kicks off, and each step of the process may be its own container that’s pulled, instanced and tossed in the matter of seconds, anything that can slow down the instancing must be changed.
<h2>Configuring and Applying Changes</h2>
<strong>VM</strong>
While projects/products like Terraform, Spinnaker, Vagrant and others aim to automate the final configuration of VMs, they are most commonly configured post instancing. Teams routinely remote into the machine, applying software or patches. Even when it's not intended, many teams still do, and these long running nodes need to be protected.

<strong>Container</strong>

Containers are considered immutable. Meaning, once an image is instanced, it’s not changed. One would likely argue a running container shouldn’t be changed as it defeats the ability for a new instance to reflect the exact behavior.
Rather than update a running container, the image dockerfile is changed to implement the configuration change or software. The image is rebuilt, pushed to a registry, and awaits its time to be instanced.
<h2>Applying OS &amp; Framework Patching</h2>
<strong>VM
</strong>Like <strong>configuring and applying changes</strong>, teams work to update templates for deployments. However, most operations teams will monitor and update their running VMs. These are updated, without necessarily understanding what apps are running, as it's just too difficult for companies to track which VMs could be impacted.

<strong>Container</strong>
Also, like <strong>configuring and applying changes</strong>, a container isn’t patched while running. The image is rebuilt with the OS and framework patches. In this model, the image can be scanned and tested before its deployed.
<h2>Receiving Data</h2>
<strong>VM
</strong>As VMs are designed as long running instances, VMs are designed to host data. It may involve downloading EDI files to be processed, customer binaries to signed, pictures to be processed. In each case, the VM has the ability to download malicious content. If the VM is found to be vulnerable, the data on the VM must be scrubbed and typically recovered.

<strong>Container
</strong>Containers are considered immutable processes that may be run for seconds or hours. Any data that may be placed in a container would/should be considered disposable. The container must be assumed to fail at any point.
Containers store their data externally, using volume drivers or data services like DocDB, Relational or Blob storage.
An image that becomes suspect could/should be deleted without any worry for what temporary storage that may have been written.
<h2>Multiple Lines of Defense</h2>
<strong>VM
</strong>In the VM world, the VM itself has multiple lines of defense. It may be secured within a VNNet, locked down to where it may communicate through firewalls, which also run on the VM. Scanning is placed within each running VM.

<strong>Container
</strong>In the container world, securing the process within the container is the last line of defense.
Containers themselves do not actively run scanning. They are lightweight processes. The container host may likely run scanning for what images are being deployed. In the best world, the image being requested to run is verified against a list of pre-scanned images. If the image has been already, and recently scanned, it’s allowed to run.
The first line of defense for containers is the source where they are kept, before deployment. This is referred to as the container registry. Each company running containers will host their own private registry. The scanner keeps an inventory of all images in the company’s private registries. Scanning at the source allows offline scanning, before the image has been requested to be deployed. This makes instancing a container fast as it’s just verified to have been seen prior. The host monitoring will either block or scan images it hasn’t previously seen.
<h2>Vulnerability Detection and Impact</h2>
<strong>VM
</strong>In the VM world, for an enterprise solution, scan results are reported back to a central server. However, the report indicates what was found and the action. It doesn’t necessarily trigger a recursive action for other like VMs.

<strong>Container
</strong>In the container world, the registry is actively scanned. Each protected node may report back what images it’s running. As the scanner finds existing vulnerabilities in newly pushed images to the container registry, or it finds new vulnerabilities in existing images in the registry, the scanner determines the impact. It can use the data for what images are running (referenced by their image digest) to understand the impact of the vulnerability.
If the scanner happens to find a vulnerability that was in a single image that was never deployed, the risk is non-impactful. The action is as simple as either quarantining the image, or deleting it.
If the scanner finds a new, critical vulnerability in a base image that has 50 other derived images, which are deployed on 220 production nodes, the impact is far more severe.
The fundamental difference between containers and VMs is where the scanning occurs, with the analysis and action taken. In the container world, a single scan and detection can account for hundreds to thousands of nodes being remediated.
<h2>Remediating Vulnerabilities</h2>
<strong>VM
</strong>Remediating vulnerabilities in a VM typically involves applying a patch to a running VM. The intent involves the patch removing or replacing the initial offending binary or configuration.

<strong>Container</strong>
When vulnerabilities are found with containers, a new, remediated image is built, pushed and deployed. Some of the key differences being the original configuration and/or binary shouldn’t have any traits in the newly built image. When the vulnerability is found in a top-level image, meaning an image that copied the offending binary in its dockerfile, it’s built once and deployed to the intended nodes. To remediate a base image, all the subsequently derived images must be rebuilt. A shameless plug for <a target="_blank" href="https://aka.ms/acr/build" rel="noopener">ACR Build.</a> In the VM environment, without products like Terraform, each node must be individually updated.
<h1>The Scanning Paradigm Shift</h1>
With the above differences, we can see the approach for scanning containers would be very different from Virtual Machines. The basic approach of containers represents a paradigm shift from working with virtual machines. While Virtual Machines were a major change in 2001, improving many challenges of installations of the OS and software, installed on dedicated hardware, they are now nearly two decades old. We’ve learned a lot since. We’ve changed the workloads from machines under someone’s desk, in a closet with hopefully enough air conditioning, or a bigger closet in the basement of an enterprise. Expectations of 3 months to get infrastructure acquired and provisioned are long gone. Customers spin up instances in an instant, on-demand, with expectations of seconds in a cloud they have no care as to where it runs.

Containers aren’t just a better mousetrap, they account for many of the lessons the industry has learned and adjusted to as the workloads have grown and transitioned from assisting humans at work. Compute now accounts for most of the work, and the humans control and interact with the computers. As a result, it’s no longer just an annoyance when the excel spreadsheet is locked or not available. Having a system down, just for a few minutes, can kill the reliability of the business, cost them millions of dollars in fines or lost revenue, or cause complete failure of the business.

&nbsp;

As with any new tech, taking the time to digest its impact, understanding the opportunity for things it can resolve, and things it can't are just as important as understanding the calorie count of your favorite new dessert.]]></content:encoded>
    </item>
    <item>
      <title>ACR Build OS &amp; Framework Patching Now Supports Docker Hub</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/acr-build-supports-docker-hub</link>
      <pubDate>Mon, 11 Jun 2018 20:33:59 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2515</guid>
      <description><![CDATA[In May we announced the public preview of ACR Build, enabling OS &amp; Framework patching. When we...]]></description>
      <content:encoded><![CDATA[In May we <a href="https://azure.microsoft.com/en-in/blog/azure-container-registry-makes-geo-replication-generally-available-adding-lifecycle-management-capabilities/">announced the public preview of ACR Build</a>, enabling <a href="https://blogs.msdn.microsoft.com/stevelasker/2017/12/20/os-framework-patching-with-docker-containers-paradigm-shift/">OS &amp; Framework patching</a>. When we announced the preview, only Azure Container Registries were supported for base image update notifications.

With DockerCon starting this week, it's only appropriate we add support for base in Docker Hub.
<ul>
 	<li>Docker build a locally scoped directory in Azure, with a tag based on the build id:</li>
</ul>
<p style="padding-left: 30px"><code>git pull https://github.com/demo42/helloworld
az acr build -t helloworld:{{.Build.ID}} .</code>
<ul>
 	<li>Create a build-task that automatically builds, based on git commits, or base image updates</li>
</ul>
<p style="padding-left: 30px"><code>az acr build-task create \
-n helloworld \
-c https://github.com/demo42/helloworld \
-t helloworld:{{.Build.ID}} \
--git-access-token $PAT</code>

When <code>az acr build</code> completes, the base images dependencies are dynamically discovered. We believe dynamic discovery is key, so your build task and dependencies are kept in sync with your code:
<pre><code>ACR Builder discovered the following dependencies:
- image:
    registry: demo42.azurecr.io
    repository: helloworld
    tag: aanc
    digest: sha256:581a6215cae409690a4106fb06f8a1f7b9cd4790b956cb197b22eb4cae9b3977
  runtime-dependency:
    registry: registry.hub.docker.io
    repository: baseimages/node
    tag: 9-alpine
    digest: sha256:1c3d74a201d4169a2dff0d49e831510384063df7546ee89bb806febfe29eaadb
  git:
    git-head-revision: e578d0e125be1599fb125bdd07c05f16d45ff1c1</code></pre>
<h2>Build Latency</h2>
To meet the scale of builds that we expect over time, <strong>ACR build</strong> has a built in randomness to the delay by which a base image update will be notified. This is currently between 10 and 60 minutes.

Using <code>az acr build-task list-builds</code>, you can see the build change from a <strong>Git Commit</strong> to <strong>Image Update</strong>
<pre><code>BUILD ID   TASK               PLATFORM   STATUS    TRIGGER      STARTED              DURATION
---------- ------------------ ---------- --------- ------------ -------------------- ---------
aanc       helloworld         Linux      Succeeded Image Update 2018-06-11T18:34:55Z 00:00:45
aanb       helloworld         Linux      Succeeded Git Commit   2018-06-11T18:31:13Z 00:00:45</code></pre>
We believe automated OS &amp; Framework patching is a key element of container life cycle management. We also know that running ahead means we may not always have the the experience just right. We encourage your thoughts and feedback:
<ul>
 	<li><strong>Getting started with ACR Build</strong>: <a target="_blank" href="https://aka.ms/acr/build" rel="noopener">aka.ms/acr/build</a></li>
 	<li><strong>Issues with ACR Build</strong>: <a target="_blank" href="https://aka.ms/acr/issues" rel="noopener">aka.ms/acr/issues</a></li>
 	<li><strong>ACR Backlog</strong>: <a target="_blank" href="https://aka.ms/acr/backlog" rel="noopener">aka.ms/acr/backlog</a></li>
 	<li><strong>Feature suggestions for ACR</strong>: <a target="_blank" href="https://aka.ms/acr/uservoice" rel="noopener">aka.ms/acr/uservoice</a></li>
</ul>
You can always reach me directly at Steve.Lasker at microsoft dot com or twitter: @SteveLasker

Steve]]></content:encoded>
    </item>
    <item>
      <title>How ACR Build Id's are generated</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/how-acr-build-ids-are-generated</link>
      <pubDate>Fri, 18 May 2018 19:42:38 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2495</guid>
      <description><![CDATA[As you use ACR Build, for OS &amp; Framework patching, native container builds, or validating a...]]></description>
      <content:encoded><![CDATA[As you use <a target="_blank" href="https://aka.ms/acr/build" rel="noopener">ACR Build</a>, for <a target="_blank" href="https://blogs.msdn.microsoft.com/stevelasker/2017/12/20/os-framework-patching-with-docker-containers-paradigm-shift/" rel="noopener">OS &amp; Framework patching</a>, native container builds, or validating a docker build without having the docker client installed, you may be wondering, what is the format for those alpha-numeric Build id's. <code>aa12</code>

The short answer is it's based on the region the build was executed upon, and a base 32, alpha-numeric sequence to provide independent execution, with multi-region fault tolerance.

The format is: [2 digit, base 32 region code][base 32 sequence]

For some background why we chose this solution...
<h2><strong>Accepting failure as reality</strong></h2>
As we build ACR, and its associated services, we accept the premise that "failure is reality". One of the base foundations of container orchestrators is to accept failure as reality, at the infrastructure level. Its not that we don't strive to make ACR and all our container services reliable. But attempting to make a service n9's reliable is a costly investment. Rather than spend 90% of our effort, getting the last n% of reliability, we invest in recovering from and accepting failure, and providing more capabilities. The end result is you achieve n9's, but you do so by accepting any number of elements may individually fail, and we avoid single points of failure.
<h2>ACR Build, Independent Execution, Multi-Region Reliability</h2>
ACR supports <a target="_blank" href="https://aka.ms/acr/geo-replication" rel="noopener">geo-replicated registries</a>. Which means a single registry can span multiple regions. ACR supports multi-master changes, so any push, any delete, any meta-data update to any region is eventually consistent. Meaning, there's no guarantee for the ordering of each regions replicated arrival. However, all replicated regions will eventually have all the images and meta-data. There's no single master controller. This means any registry can go down, and the rest will continue to operate. As a practice, we have no single points of failure, other than the big rock we all reside. We have <a target="_blank" href="https://feedback.azure.com/forums/903958-azure-container-registry/suggestions/34290697-planetary-replication" rel="noopener">planetary replication</a>, to replicate to Mars and other destinations on our backlog, so the sky is not the limit.

Each replicated registry should be able to build, on its own, and become eventually consistent.
<h2>Balancing Needs for a Unique ID</h2>
With a little background, we can see why we didn't just use a Count Dracula approach of 1, 2, 3... We then had to decide; how can we generate a unique id?

We came up with a few guiding principles.
<ol>
 	<li>It must be unique, as we want to support <a target="_blank" href="https://blogs.msdn.microsoft.com/stevelasker/2018/03/01/docker-tagging-best-practices-for-tagging-and-versioning-docker-images/" rel="noopener">Best practices for tagging and versioning docker images</a></li>
 	<li>It must be short enough to be able remember as you tell someone across the room, or type into another device while looking at another screen</li>
 	<li>It must be easy for a human to read, and not get confused between 1 and l. 0 and o. 2 and z.</li>
 	<li>It would be nice if there was some sense of sequential ordering. Although it wasn't critical to use every digit.</li>
 	<li>It didn't have to be globally unique. It could be unique to a specific registry. Meaning myregistry.azurecr.io and yourregistry.azurecr.io could have the same build id. Making it globally unique would conflict with principals 2-4.</li>
 	<li>We could seed each region with it's own pre-qualifier, so each geo-replicated region of a registry could be sequential</li>
</ol>
We considered prefacing the region specific unique number with the region id. eastus-1234. Although the first private preview used this, it seemed long and could be confusing when you consider that ACR Build could load balance builds across geo-replicated regions. By using generic numbers, there's no guarantee the preface characters really meant a specific thing.
<h2>Where we landed:</h2>
<ul>
 	<li>To keep it short, human readable, we went with a base 32 alpha-numeric sequence. All digits will be lower case, <em>including the numbers. (what's the point of doing this if we can't laugh at the details) </em><code>0123456789abcdefghjkmnpqrstuvwxy</code></li>
 	<li>Each region will get a sequential two digit preface. Rather than do an elaborate <a target="_blank" href="https://en.wikipedia.org/wiki/ZIP_Code" rel="noopener">zip code model</a>, we'll take a simplistic agile approach. Every region we'll add, will simply get the next sequential two digit seed.
<em>An insider secret. You'll know the order we roll out build regions by its preface characters.</em></li>
</ul>
<table style="border: 1px solid black;margin-left: 30px">
<thead>
<tr style="border: 1px solid black;padding: 10px">
<th style="padding: 10px">Region</th>
<th style="padding: 10px">Seed</th>
</tr>
</thead>
<tbody>
<tr>
<td style="padding: 10px">East US</td>
<td style="padding: 10px">aa</td>
</tr>
<tr>
<td style="padding: 10px">West Europe</td>
<td style="padding: 10px">ab</td>
</tr>
<tr>
<td style="padding: 10px">The next region</td>
<td style="padding: 10px">ac</td>
</tr>
</tbody>
</table>
<ul>
 	<li>Each region will track its next id.</li>
 	<li>If a build fails, the build id is associated with the failed build, and the next sequential number is used for the next build.</li>
 	<li>Quick builds <code>az acr build -t .</code>, will also get sequential build ids.</li>
 	<li>Build Ids are assigned as the build is queued. If two builds are queued at the same time, that started at 1pm, that took 2 minutes will have a lower number than the build that started at 1:01 pm, and only took 30 seconds.</li>
 	<li>The preface characters are not tied to the closest registry from where the command is executed. As customers adopt base image updates, we expect huge bursts of automated builds as popular OS and run times update. As we scale ACR Build, we will stage the events, globally, just as Windows Update does today. If a region is at capacity, we may utilize any geo-replicated regions of a registry to load balance builds. If a registry is replicated between East US and West Europe, a build initiated on the east coast, may be bounced to West Europe based on capacity. ACR Geo-replication will kick in, and the Build ID will start with <code>ab</code>, the seed from West Europe.</li>
</ul>
We're excited to participate in building reliable systems, based on the reality that failure is a thing. We also strive on building systems that are easy to maintain as all too often, failures are triggered by complexity of simple things: <a target="_blank" href="https://mentalfloss.com/article/25845/quick-6-six-unit-conversion-disasters" rel="noopener">quick-6-six-unit-conversion-disasters</a>

Steve]]></content:encoded>
    </item>
    <item>
      <title>Docker Tagging: Best practices for tagging and versioning docker images</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/docker-tagging-best-practices-for-tagging-and-versioning-docker-images</link>
      <pubDate>Thu, 01 Mar 2018 03:54:34 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2145</guid>
      <description><![CDATA[In any new tech, there are lots of thoughts around “best practices”. When a tech is new, what makes...]]></description>
      <content:encoded><![CDATA[In any new tech, there are lots of thoughts around “best practices”. When a tech is new, what makes a best practice?
Working at Microsoft, running the Azure Container Registry (ACR), talking with lots of customers, some that use Azure and some that don’t, we’ve had a lot of exposure to what customers have encountered. We’ve been working on a number of scenarios, including container life cycle management and <a target="_blank" href="https://blogs.msdn.microsoft.com/stevelasker/2017/12/20/os-framework-patching-with-docker-containers-paradigm-shift/" rel="noopener">OS &amp; Framework patching with containers</a>. This has surfaced a number of interesting issues. Issues that suggest, “both sides” of the tagging argument  have value.
It’s easy to get caught up, arguing a particular best practice, …if you don’t first scope what you’re practicing. I'll start by outlining two basic versioning schemes we’ve found map to the most common scenarios. And, how they are used together to solve the container life cycle management problem.
<h1>Container Patterns Support a Self-Healing Model</h1>
Before I get into specific tagging schemes, it may help to identify a specific scenario impacted by your tagging scheme.

The most basic container scenario supports restart type policies. <code>docker run --restart always myunstableimage:v0</code> This helps when a container fails due to some internal reasoning. But, the host is still available. In this case, our code must be resilient. Or, to an old friends point (Pat Helland), "we must write our software with a <a target="_blank" href="https://blogs.msdn.microsoft.com/pathelland/2007/05/15/memories-guesses-and-apologies/" rel="noopener">apology based computing</a> approach." Apology based computing suggest our code must deal with "stuff" that happens. A set of code, or a container may fail and need to re-run that logic.

For the purposes of tagging, I'll stay focused on the other aspect; we must assume a container host may fail at any point. Orchestrators will re-provision the failed node, requiring a new docker pull. Which begs the question: when you have a collection of containers running the same workload, do you want them to all run the same workload, or some of them have the last version, while new nodes have a newer version?

<a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2018/03/OrchestratorDeployment.gif" rel="noopener"><img src="https://msdnshared.blob.core.windows.net/media/2018/03/OrchestratorDeployment.gif" alt="" width="1024" height="454" class="aligncenter wp-image-2225 size-large" /></a>

In the above diagram, we have:
<ol>
 	<li>a local build of 3 images: <code>web:1, api:1, cache:1</code>. Looking closely, we can see every tag has an ID, otherwise known as a <a target="_blank" href="https://docs.docker.com/engine/reference/commandline/images/#list-image-digests" rel="noopener">digest</a>.</li>
 	<li>When the images are pushed to a registry, they are stored as two parts. The image:tag, and the underlying digest. These are actually separate elements, with a pointer between them.</li>
 	<li>A deployment is made, using the tag. Not the digest. Although, that is an option. Digests aren't as clean as I show here. They actually look like this: <code>f3c98bff484e830941eed4792b27f446d8aabec8b8fb75b158a9b8324e2da252</code>. Not something I can easily fit in this diagram, and certainly not something you'd want to type, or even try and visually find when looking at the containers running in your environment.</li>
 	<li>When a deployment is made to a host, the orchestrator keeps track of what you asked it to deploy and keep deployed. This is the important part. ...wait for it...</li>
 	<li>With a deployment saved, the orchestrator starts its work. It evaluates what nodes it has to work with and distributes the request.</li>
</ol>
A few things here. While many would argue Kubernetes has become the defacto standard for container orchestrators, orchestration is a generalized concept. Over time, we expect orchestration to just become the underpinnings to higher level services. But, that's another post...

<a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2018/03/PushNewTags.gif" rel="noopener"><img src="https://msdnshared.blob.core.windows.net/media/2018/03/PushNewTags.gif" alt="" width="600" height="436" class="aligncenter wp-image-2235" /></a>
<ol start="6">
 	<li>As our development team moves along, a new version of the api and cache are built and pushed. Since this is just a minor fix to version 1, the team uses the same tag.</li>
 	<li>Our registry acknowledges the request, saving the new :1 version of the api and cache. Notice the original tags are now pointing to the new digests (3rp, 1n4)</li>
</ol>
At this point, you likely see where this is going.

<a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2018/03/DeployStableTags.gif" rel="noopener"><img src="https://msdnshared.blob.core.windows.net/media/2018/03/DeployStableTags.gif" alt="" width="800" height="550" class="aligncenter wp-image-2245" /></a>
<ol start="8">
 	<li>As Pat would say "Stuff Happens". <em>Actually, Pat would say something else</em>. Our Host-B node has failed.</li>
 	<li>No problem, our orchestrator's job is to maintain a requested deployment.
It sees the failure, evaluates the request made of it, and provisions the necessary resources to recover.
Our deployment chart clearly says, keep 3 copies of web:1, 3 copies of api:1 and 4 copies of cache:1. So, it does a docker run of each of those image:tag combinations. It's doing what it was told.
Our Host-C now has the replacement images running</li>
</ol>
<a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2018/02/StableTaggingCreatesInstability.png" rel="noopener"><img src="https://msdnshared.blob.core.windows.net/media/2018/02/StableTaggingCreatesInstability.png" alt="" width="800" height="534" class="aligncenter wp-image-2195" /></a>

Is this the desired state you want? The orchestrator did it's job. It was told to deploy and maintain a given set of images.

The problem was actually further upstream, when we re-used the same tag for our images.

Now, if you're like most people, you're likely thinking:
<ul>
 	<li>I can deploy with the digest - yup, and you can view lots of these: <code>f3c98bff484e830941eed4792b27f446d8aabec8b8fb75b158a9b8324e2da252</code></li>
 	<li>I can use semantic versioning, and always bump the number - yup, that sort of works, but read on</li>
 	<li>I can use my git commit id - that's pretty good as each commit is unique, and you can easily match a container image to its source. However, do you only rebuild your images when your source changes? ...read on</li>
</ul>
<h1>OS &amp; Framework Patching</h1>
While I believe in "never say never", using stable tags <em><strong>for deployments</strong> are </em>fraught with problems. However, Stable Tags do have their value.

Let's consider what happens when developers stop checking in code changes. In the VM world, Ops would continue to patch the running hosts for updates to the framework and patches to the host operating system. And, at some point, those patches may break the apps running on those nodes. One of the many benefits of containers are the ability to isolate the things our apps and services depend upon. Those dependencies are contained within our image, declared within our dockerfile.

<strong>A multi-stage dockerfile for an aspnetcore app, based linux</strong>

<code>FROM microsoft/aspnetcore:2.0 AS base
WORKDIR /app
EXPOSE 80</code>

<code>FROM microsoft/aspnetcore-build:2.0 AS build
WORKDIR /src
COPY HelloWorld.sln ./
COPY HelloWorld/HelloWorld.csproj HelloWorld/
RUN dotnet restore -nowarn:msb3202,nu1503
COPY . .
WORKDIR /src/HelloWorld
RUN dotnet build -c Release -o /app</code>

<code>FROM build AS publish
RUN dotnet publish -c Release -o /app</code>

<code>FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "HelloWorld.dll"]</code>

In the above example, we can see two images. The aspnetcore-build:2.0 image to compile our code, then we copy the output from our build image to an optimized asnetcore:2.0 image. See: <a href="https://blogs.msdn.microsoft.com/stevelasker/2017/09/11/net-and-multistage-dockerfiles/">.NET and MultiStage Dockerfiles </a>for more details

For the focus of tagging and OS &amp; Framework patching, notice our base image, used for the image we actually deploy.

<code>FROM microsoft/aspnetcore:2.0 AS base</code>

You can see we're using the stable tag, 2.0.  This is where semantic versioning does play a role. The ASP.NET Core team releases new capabilities, indicated by the major version. They shipped 1.0, 2.0 and you can imagine they'll continue to ship new capabilities. In the real world, new capabilities means things change, behaviors change, and thus, you want the development team to make a conscious choice which major version of aspnetcore they depend upon. This basic pattern is used across all major frameworks, java, go, node, etc.

While the team focuses on new capabilities, they must also service each version. The aspnetcore image contains aspnetcore, dotnet core, as well as linux or windows server nanao base layers, depending on which architecture you're running. How do you get OS &amp; Framework updates? Should you have to bump your FROM statement for every release? While the team will publish additional tags for minor, non-breaking changes, each team does update their stable major tags.

This does mean, depending on when you pull aspnetcore:2.0, you'll get different content. But, that's the intent. Whenever you pull the stable tag, <em>you should</em> get the latest OS &amp; Framework patched image. I say should as not all repo owners do proper maintenance on their images. Why, because it's actually pretty hard. <em>(insert smallest fiddle)</em> .

To stay focused on tagging schemes, I'll point you this post on <a href="https://blogs.msdn.microsoft.com/stevelasker/2017/12/20/os-framework-patching-with-docker-containers-paradigm-shift/">OS &amp; Framework Patching with Docker Containers – a paradigm shift</a>.

<a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2017/12/AzureContainerBuild.png" rel="noopener"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/AzureContainerBuild-1024x397.png" alt="" width="801" height="311" class="aligncenter wp-image-2067" /></a>
<h1>What Tagging Scheme Should I Use?</h1>
<h2>Stable Tags</h2>
Stable tags mean a developer, or a build system can continue to pull a specific tag, which continues to get updates. Stable doesn't mean the contents are frozen, rather stable implies the image should be stable, for the intent of that version. To keep it "stable", it's serviced to keep the evil people from corrupting our systems. (ok, evil can also be a simple mistake that has huge impacts)

An example:

A framework team ships 1.0. They know they'll ship updates, including minor updates. To support stable tags for a given major and minor version, they have two sets of stable tags.
<ul>
 	<li>:1 - a stable tag for the major version. 1 will represent the "newest" or "latest" 1.* version.</li>
 	<li>:1.0 a stable tag for version 1.0, allowing a developer to bind to updates of 1.0, and not be rolled forward to 1.1</li>
 	<li>:latest which will point to the latest stable tag, no matter what the current major version is.</li>
</ul>
<a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2018/03/StableTagging.gif" rel="noopener"><img src="https://msdnshared.blob.core.windows.net/media/2018/03/StableTagging.gif" alt="" width="1024" height="274" class="aligncenter wp-image-2265 size-large" /></a>

What's not quite captured above are servicing releases to any of the given tags. As base image updates are available, or any type of servicing release of the framework, the stable tags will be updated to the newest digest that represents the most current stable release of that version.

<a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2018/03/StableTaggingWithUpdates.gif" rel="noopener"><img src="https://msdnshared.blob.core.windows.net/media/2018/03/StableTaggingWithUpdates.gif" alt="" width="1024" height="243" class="aligncenter wp-image-2255 size-large" /></a>

In the above example, updates are provided for the specific versions. In this case, both the major and minor tags are continually being serviced. From a base image scenario, this allows the image owner to provide serviced images.

If you really wanted to bind to a specific image, that never changes, you'd set your FROM statement to the digest.
<pre class="highlight"><code>FROM favframework@sha256:45b23dee08asdfls3a7fea6c4cf9c25ccf269ee113ssc19722f87876677c5cb2</code></pre>
However, I'd highly suggest <em>"never"</em> doing binding to a digest. Yeah, I went there - <em>never.</em> If you bind to the digest, how would you get servicing of your base image?
<h1>Unique Tagging</h1>
Unique tagging simply means, every image pushed has a unique tag. Tags are <em>"never"</em> reused. We've had a number of customers request the ability to enforce this policy, which we'll be adding to ACR. Along with several other policies.

<a target="_blank" href="https://msdnshared.blob.core.windows.net/media/2018/03/UniqueTagging.gif" rel="noopener"><img src="https://msdnshared.blob.core.windows.net/media/2018/03/UniqueTagging.gif" alt="" width="1024" height="134" class="aligncenter wp-image-2275 size-large" /></a>
<h2>What value should use for your unique tags?</h2>
There are a number of options.
<ol>
 	<li><strong><del>git commit</del> </strong>- works until you start supporting base image updates, where your build system will kick off, with the same git commit as the previous built. However, the base image will have new content. Using a git commit winds up being a <strong><em>semi</em></strong>-stable tag.</li>
 	<li><strong>date-time-stamp</strong> - this is a fairly common approach as you can clearly tell when the image was built. But, how do correlate it back to your build system? Do you have to find the build that was completed at the same time? What time zone are you in? Are all your build systems calibrated to UTC?</li>
 	<li><strong>digest</strong> - it's unique, or should be. But, it's really not usable as it's just toooooo long. And, it doesn't really correlate with anything easily found.</li>
 	<li><strong>build id</strong> - this one is closest to the best as its likely incremental, gives you correlation back to the specific build to find all the artifacts and logs.</li>
 	<li><strong>&lt;build-system&gt;-&lt;build id&gt;</strong> - If your company has several build systems, prefixing the tag with the build system helps you differentiate the API team's Jenkins build system from the Web teams VSTS build system.</li>
</ol>
<h1>Wrapping up</h1>
Whew, that was a lot... As with many things, an answer, especially a best practice, depends on ___. Hopefully I've given some context for the various tagging schemes, and the reasoning behind them.

To summarize:
<ul>
 	<li><strong>Use stable tagging for base images</strong>
<em>"Never"</em> deploy with stable tags as deploying stable tags leads to instability</li>
 	<li><strong>Use unique tags for deployments</strong>
as you likely want deliberate deployments of a consistent version of components. Your hosts won't accidentally pull a newer version, inconsistent with the other nodes when "stuff" happens</li>
 	<li><strong>Use build id's</strong>
for your deployed images, so you can correlate it back to the rest of the information in your build system</li>
</ul>
You may have a good reason for deploying stable tags such as a test environment. But, just realize that images will be updated underneath, and you can very easily spend hours troubleshooting a node that pulled a slightly different version of that tag.

Some things to also consider:
<ul>
 	<li>Container best practices are evolving</li>
 	<li>The underlying technology is evolving</li>
 	<li>You're learning. I like to remind people, learning docker takes a day to realize it's cool, but 3 months to really "get it". Then, you're really just getting started</li>
 	<li>I'm just a person with an opinion, and I've very possibly missed something. Tell me what you think...</li>
</ul>
Steve

<em>When you stop learning, you start dying...</em>

<a target="_blank" href="https://github.com/SteveLasker/Presentations/blob/master/ACR/ImageTaggingBestPractices.pptx?raw=true" rel="noopener">PowerPoint deck with the animations used in the gifs</a>]]></content:encoded>
    </item>
    <item>
      <title>Relaxing ACR storage limits, with tools to self manage</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/relaxing-acr-storage-limits-with-tools-to-self-manage</link>
      <pubDate>Fri, 02 Feb 2018 20:47:39 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2105</guid>
      <description><![CDATA[When we created the tiered SKUs for ACR, we built the three tiers with the following scenarios in...]]></description>
      <content:encoded><![CDATA[When we created the tiered SKUs for ACR, we built the three tiers with the following scenarios in mind:
<ul>
 	<li><strong>Basic</strong> - the entry point to get started with ACR. Not intended for production, due to the size, limited webhooks and throughput SLA. Basic registries are encrypted at rest and geo-redundantly stored using Azure Blob Storage, as we believe these are standards that should never be skipped</li>
 	<li><strong>Standard</strong> - the most common registry, where most customers will be fine with the webhooks, storage amount and throughput.</li>
 	<li><strong>Premium</strong> - for the larger companies that have more concurrent throughput requirements, and global deployments.</li>
</ul>
The goal was never to force someone up a tier, beyond the basic tier. Or worse, cause a build failure if a registry filled up. Well, we all learn. :) It seems customers were quick to enable automation - awesome!. And are quickly filling up their registries.

There are two fundamental things we're doing:
<ol>
 	<li>ACR will relax the hard constraints on the size of storage. When you exceed the storage associated with your tier, we will charge an overage fee at $0.10/GiB. We did put some new safety limits in place. For instance Premium has a safety of 5tb. If you think you'll really need more, just let us know, and help us understand. We're trying to optimize the experiences, and there are differences we'd need to do for very large registries.</li>
 	<li>We have pulled up the Auto-Purge feature, allowing customers to manage their dead image pool. Using Auto-purge, customers will be able to declare a policy by which images can be automatically deleted after a certain time. You'll also be able to set the TTL on images. We've heard customers say they need to keep any deployed artifact for __ years. Wow, long time... Eventually, we'll be able to know when it's no longer deployed, and you'll be able to set the TTL for __ units, after the last use.</li>
</ol>
As customers hit the limits, we wanted to allow customers to store as much as they want, simply charging them for their usage. And enable them to manage their storage, with automated features.

<strong>When, when, will we get this?</strong>

The overage meters will start the end of February. Early next week, we'll start the design for the policies on auto-purge. As we know more, I'll post an update.

Thanks for the continued feedback,

Steve]]></content:encoded>
    </item>
    <item>
      <title>Working with ACR Geo-replication notifications</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/working-with-acr-geo-replication-notifications</link>
      <pubDate>Mon, 29 Jan 2018 22:09:17 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2085</guid>
      <description><![CDATA[Azure Container Registry geo-replication enables a single control plane across the global footprint...]]></description>
      <content:encoded><![CDATA[Azure Container Registry geo-replication enables a single control plane across the global footprint of Azure. You can opt into the regions you'd like your registry to have a network-close/local experience.

However, there are some important aspects to consider.

ACR Geo-replication is multi-master. You can push to any region, and ACR will replicate the manifests and layers to all other regions you've opted into. However, replication does take some time. Time, based on the size of the image layers. Without an understanding of the latency, it can be confusing and look like a failure has happened. We also recently realized the errors we're reporting can add to the confusion.

Lets assume you have a registry that replicates within:
<ul>
 	<li>West US</li>
 	<li>East US</li>
 	<li>Canada Central</li>
 	<li>West Europe</li>
</ul>
You have developers in both West US and West Europe, with production deployments in all regions. ACR uses Azure Traffic manager to find the closest registry to the location of the pull. The registry url remains the same. Which means its important to understand the semantics.
<h1>Image flow</h1>
From West US, I push a new tag: <code>stevelasdemos.azurecr.io/samples/helloworld:v1</code>. I can immediately pull that tag from West US, as that's the local registry I pushed to.

However, If I immediately attempt to pull the same tag from West Europe, the pull will fail as it doesn't yet exist. The pull will fail, even if I issue the docker pull from West US... Hmmm, why? Docker is a client/server model, and the pull is executed from the server.

I work in West US. I connected my docker client to the docker host running in West Europe. When I issue a docker pull, my client is just proxying the request to the host, which is running in West Europe. When the pull is executed, traffic manager routes to the closes registry, which is in West Europe.

If I remote/ssh into a box in West Europe, or execute a helm deploy from West US to West Europe, the same flow happens. The pull is initiated from West Europe. Which, is actually what we want as we want a local fast, reliable, cheap pull. But, how do I know when I can pull from West Europe?
<h1>Image Notifications</h1>
ACR supports web hook notifications that fire when images are pushed or deleted. Webhooks are regionalized, so you can create web hooks for each region.

In a production deployment, you'll likely want to listen to these web hooks and deploy as the images arrive.
<h1>Tag Updates</h1>
This is a more interesting conversation, and requires a new post on tagging schemes. Basically, base image owners should re-use tags as they service core versions. When a patch to 2.0 of an image is made available, the 2.0 tag should have the new version.

However, a production app should not use stable tags. Every new image to be deployed should use a unique tag. If you have 10 nodes deployed, and one of those nodes fails, the cluster or PaaS service will re-pull the tag it knows should be deployed. (how should you write PaaS service, it's a bit redundant...?)

If you re-use tags in production deployments, the new node will pull the most recent version of that tag, while the rest of the nodes are running an older version. If you always use unique tags for deployments, the new node will pull the same, consistent tag that's running on the other nodes.
<h1>Tag Replication</h1>
ACR geo-replication will replicate tag updates. But, if you're not aware of the flow, you can also get "magical" results.

Using the example above, <code>stevelasdemos.azurecr.io/samples/helloworld:v1</code> has been pushed and replicated to all regions, which are running in all regions.

If I push an update to :v1 from West US, and issue a docker run/helm deploy to all regions, my local West US deployment will get the new version of :v1. However, all the other regions will not get the new tag, as they already have that tag running.

If you deploy :v2 from West US, and attempt to deploy :v2 in the other regions, you'll get an unknown manifest error.

&nbsp;
<h1>Geo-replication and Webhook Notifications</h1>
When we initial designed the geo-replication feature, we realized this gap and added the regionalized webhooks. We do realize this could be slightly easier as we'd like a deployment to be queued, for when the replicas are deployed. We have some more work to do here, and would encourage feedback on what you'd like to see. What you're scenarios are.
<h1>Better Errors</h1>
A customer recently raised a ticket with us, as they were receiving a "<em>blob unknown</em>" errors. After digging into the issue, we realized we had an issue with how we cache manifest requests and the ordering of how we sync the blobs, manifests and cache them.

A while back, we added manifest caching. Customers were using OSS tools that continually polled the registry, asking for updates to a given tag. They were pinging the registry every second, from hundreds of machines. Each request went into the ACR storage infrastructure to recalculate the manifest. Only to return the same result. We added caching to cache manifest requests, which sped up the requests and improved overall ACR performance, across all customers. While we invalidate the 1hr cache TTL from a docker push, we realized a tag update, replicated across a registry wasn't invalidating the cache. We missed this as we consider it a best practice to never use the same tag, but we also know to never say never. So, we're fixing the cache invalidation when replicated.

We will also avoid "<em>blob unknown</em>" errors, when it's really a "<em>manifest unknown</em>" error". In the customer reported problem, we hadn't yet replicated all the content when they did a pull. Because the cache wasn't invalidated, we found the updated manifest, but the blobs hadn't yet replicated. We will make the replication more idem-potent, fix the cache TTL and will more accurately report "manifest unknown" as opposed to "blob unknown".
<h1>Preview --&gt; GA</h1>
These sort of quirks are why we have a preview phase of a service. We can't possibly foresee all the potential issues without taking really long private bake times, which can miss a market. For customers, they get early access to bits that hopefully help them understand what's coming, so they can focus elsewhere while we improve the service.

I just want to end with a thank you for those that help us improve our services, on your behalf. We value every bit of feedback.

Steve and the rest of the ACR team.]]></content:encoded>
    </item>
    <item>
      <title>OS &amp; Framework Patching with Docker Containers - a paradigm shift</title>
      <link>https://docs.microsoft.com/archive/blogs/stevelasker/os-framework-patching-with-docker-containers-paradigm-shift</link>
      <pubDate>Wed, 20 Dec 2017 19:29:21 GMT</pubDate>
      <dc:creator><![CDATA[Steve Lasker]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/stevelasker/?p=2035</guid>
      <description><![CDATA[Thinking of containers, we think of the easy packaging of our app, along with its dependencies. The...]]></description>
      <content:encoded><![CDATA[<a href="https://msdnshared.blob.core.windows.net/media/2017/12/AzureContainerBuild.png"></a>Thinking of containers, we think of the easy packaging of our app, along with its dependencies. The dockerfile FROM defines the base image used, with the contents copied or restored into the image.
We now have a generic package format that can be deployed onto multiple hosts. No longer must the host know about what version of the stack that's used, nor even the version of the operating system. And, we can deploy any configuration we need, unique to our container.
<h1>Patching workloads</h1>
In the VM world, we patch workloads by patching the host VM. The developer hands the app over to operations, who deploys it on a VM. Along with the list of dependencies that must be applied to the VM. Ops then takes ownership, hoping the patching of the OS &amp; Frameworks don't negatively impact the running workloads. How often do you think ops does a test run of a patch on a VM workload before deploying it? It's not an easy thing to do, or expectation in the VM world. We basically patch, and hope we don't get a call that something no longer works...

The workflow involves post deployment management. Projects like Spinnaker and Terraform are making great strides to automating the building process of VM, in an immutable infrastructure model. However, are VMs the equivalent to the transition from vhs to dvds?
<h1>Are containers simply a better mousetrap?</h1>
In our busy lives, we tend to look for quick fixes. We can allocate 30 seconds of dedicated and open ended thought before we latch onto an idea and want to run with it. We see a pattern, figure it's a better drop-in replacement and boom, we're off to applying this new technique.

When recordable dvd players became popular, they were mostly a drop in replacement for vhs tapes. They were a better format, better quality; <em>no need to rewind</em>, but the workflow was generally the same. Did dvds become a drop in replacement for the vhs workflow? Do you remember scheduling a dvd recording, which required setting the clock that was often blinking 12:00am from the last power outage, or was off by an hour as someone forgot how to set it after daylight savings time? At the same time the dvd format was becoming prominent, streaming media became a thing. Although dvds were a better medium to vhs tapes, you could only watch them if you had the physical media. DVRs and streaming media became the primary adopted solution. Not only were they a better quality format, but they solved the usability for integrating with the cable providers schedule. With OnDemand, NetFlix and other video streaming, the entire concept for watching videos changed. I could now watch from my set-top box, my laptop in the bedroom, the hotel, or my phone.

The switch to the dvd format is an example of a better mousetrap that didn't go far enough to solve the larger problem. There were better, broader options that solved a broader set of problems, but it was a paradigm shift.

&nbsp;
<h1>Base image updates</h1>
While you could apply a patch to a running container; this falls into the category of: "just because you can, doesn't mean you should". In the container world, we get OS &amp; Framework patches through base image updates. Our base images have stable tags that define a relatively stable version. For instance the <a href="https://hub.docker.com/r/microsoft/aspnetcore/">microsoft/aspnetcore</a> image has tags for :1.0, 1.1, 2.0. The difference between 1.0, 1.1, 2.0 represent functional and capability changes. Moving between these tags implies there may be a difference in functionality, as well as expanded capabilities. We wouldn't blindly change a tag between these versions and deploy the app into production without some level of validations. Looking at the <a href="https://hub.docker.com/r/microsoft/aspnetcore/tags/">tags</a> we see the image was last updated some hours or days ago. Even though the 2.0 version was initial shipped months prior.

To maintain a stable base image, owners of these base images maintain the latest OS &amp; Framework patches. They continually monitor and update their images for base image updates. The aspnetcore image updates based on the dotnet image. The dotnet image updates based on the Linux and Windows base images. The Windows and Linux base images update their base images, testing them for the dependencies they know of, before releasing.

Windows, Linux, Dotnet, Java, Node all provide patches for their published images. The paradigm shift here is providing updated base images with the patches already applied. How can we take advantage of this paradigm shift?
<h1>Patching containers in the build pipeline</h1>
In the container workflow we continually build and deploy containers. Once a container is deployed, the presumption is it's never touched. The deployment is immutable. To make a change, we rebuild the container. We can then test the container, before it's deployed. The container might be tested individually, or in concert with several other containers. Once there's a level of comfort, the container(s) are deployed. Or, scheduled for deployment using an orchestrator. Rebuilding each time, testing before deployment is a change. But, it's a change that enables new capabilities, such as pre-validating the change will function as expected.

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/TradContainerBuild.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/TradContainerBuild-1024x350.png" alt="Traditional Container Build" height="200" class="aligncenter wp-image-2046" /></a>
<h2><a href="https://msdnshared.blob.core.windows.net/media/2017/12/TradContainerBuild.png"></a>Container workflow primitives</h2>
To deliver a holistic solution to OS &amp; Framework patching, there are several primitives. One model would provide a closed-loop solution where every scenario is known. A more popular approach involves providing primitives that can be stitched together. If a component needs to be swapped out, for whatever reason, the user isn't blocked.

If we follow the SCC build workflow, we can see the SCC system notifies the build system. When the build system completes, it pushes to a private registry. When the registry receives updates, it can trigger a deployment, or a release management system can sit between, deciding when to release.

The primitives here are:
<ul>
 	<li>Source that provides notifications</li>
 	<li>Build system that builds an image</li>
 	<li>Registry that stores the results</li>
</ul>
The only thing missing is the source for base images that can provide notifications?
<h2>Azure Container Builder</h2>
Over the last year, we've been talking with customers, exploring the problem area for how to handle OS &amp; Framework patching. How can we enable a solution that fits within current workflows? Do we really want to enable patching running containers? Or, can we pickup the existing workflows, or the evolving workflows for containerized builds?

<a href="https://msdnshared.blob.core.windows.net/media/2017/12/AzureContainerBuild.png"><img src="https://msdnshared.blob.core.windows.net/media/2017/12/AzureContainerBuild-1024x397.png" alt="" width="1024" height="397" class="aligncenter wp-image-2067 size-large" /></a>

Just as SCC systems provide notifications, the Azure Container Builder will trigger a build based on a base image update? But, where will the notifications come from? We need a means to know when base images are updated. The missing piece here is the base image cache. Or, more specifically, an index to updated image tags. With a cache of public docker hub images, and any ACR based images your container builder has access to, we have the primitives to trigger an automated build. When code changes are committed, a container build will be triggered. When an update to the base image specified in the dockerfile is made, a container build will be triggered.

The additional primitive for base image update notifications is one of the key aspects of the Azure Container Builder. You may choose to use these notifications with your existing CI/CD system. Or, you may choose to use the new Azure Container Builder that can be associated with your Azure Container Registry. All notifications will be available through the Azure Event Grid, providing a common way to communicate asynchronous events across Azure.

<strong>Giving it a try...</strong>

We're still finalizing the initial public release of the Azure Container Builder. We were going to wait until when we had this working in public form. The more I read posts from our internal Microsoft teams, our field, Microsoft Regional Directors, and customers looking for a solution, the more I realized it's better to get something out for feedback. We've seen the great work the Google Container builder team has done, and the work AWS Code-build has started. Any cloud provider that offers containerized workflows will need private registries to keep their images network-close. We believe containerized builds should be treated the same way.
<ul>
 	<li>What do you think?</li>
 	<li>Will this fit your needs for OS &amp; Framework patching?</li>
 	<li>How will your ops teams feel about delegating the OS &amp; Framework patching to the development teams workflow?</li>
</ul>
Steve]]></content:encoded>
    </item>
  </channel>
</rss>