.NET and Amazon Elastic Container Registry (ECR)
Tags: aws, dotnet, containers
Published: 2022-06-16 22:59:27

[Amazon Elastic Container Registry](https://aws.amazon.com/ecr) (ECR) is a system designed to support storing and managing Docker and Open Container Initiative (OCI) images and OCI-compatible artifacts. ECR can act as a private container image repository, where you can store your own images, a public container image repository for managing publicly accessible images, and to manage access to other public image repositories. ECR also provides lifecycle policies, that allow you to manage the lifecycles of images within your repository, image scanning, so that you can identify any potential software vulnerabilities, and cross-region and cross-account image replication so that your images can be available wherever you need them.

As with the rest of AWS services, ECR is built on top of other services. For example, Amazon ECR stores container images in Amazon S3 buckets so that server-side encryption is available by default. Or, if needed, you can use server-side encryption with KMS keys stored in [AWS Key Management Service](https://aws.amazon.com/kms) (AWS KMS), all of which you can configure as you create the registry. As you can likely guess, IAM manages access rights to the images, supporting everything from strict rules to anonymous access to support the concept of a public repository.

There are several different ways to create a repository. The first is through the ECR console by selecting the Create repository button. This will take you to the Create repository page as shown in Figure 1.
 
<img src="https://billthevestguy.com/wp-content/uploads/2021/10/figure05-ecr1.png" alt="AWS Console screen for creating an ECR repository" />_Figure 1. Creating an ECR repository in the AWS console_

Through this page you can set the _Visibility_ settings, _Image scan settings_, and _Encryption settings_. There are two visibility settings, _Private_ and _Public_. Private repositories are managed through permissions managed in IAM and are part of the AWS Free Tier, with 500 MB-month of storage for one year for your private repositories. Public repositories are openly visible and available for open pulls. Amazon ECR offers you 50 GB-month of always-free storage for your public repositories, and you can transfer 500 GB of data to the internet for free from a public repository each month anonymously (without using an AWS account.) If authenticating to a public repository on ECR, you can transfer 5 TB of data to the internet for free each month and you get unlimited bandwidth for free when transferring data from a public repository in ECR to any AWS compute resources in any region.

Enabling **Scan on push** on means that every image that is uploaded to the repository will be scanned. This scanning is designed to help identify any software vulnerabilities in the uploaded image, and will automatically run every 24 hours, but turning this on will ensure that the image is checked before it can ever be used. The scanning makes use of the Common Vulnerabilities and Exposures (CVEs) database from the Clair project, outputting a list of scan findings. 

_**Note**: Clair is an open-source project that was created for the static analysis of vulnerabilities in application containers (currently including OCI and Docker). The goal of the project is to enable a more transparent view of the security of container-based infrastructure - the project was named Clair after the French term which translates to clear, bright, or transparent._

The last section is _Encryption_ settings. When this is enabled, as shown in Figure 2, ECR will use AWS Key Management Service (KMS) to manage the encryption of the images stored in the repository, rather than the default encryption approach. 

<img src="https://billthevestguy.com/wp-content/uploads/2021/10/figure05-ecr2.png" alt="AWS Console screen for creating an ECR repository" />_Figure 2. Encryption settings_

You can use either the default settings, where ECR creates a default key (with an alias of aws/ecr) or you can _Customize encryption settings_ and either select a pre-existing key or create a new key that will be used for the encryption.

## Pull Through Cache Repositories

Everything we have gone through so far is to upload your own container image into the repository. However, as we will cover in depth a bit later in this post, at the heart of virtually all of your container images is a base container image, generally created by a vendor such as Microsoft or Docker. These base images are typically downloaded from a public repository. However, there may be instances where you prefer to source all images from Amazon Elastic Container Registry to take advantage of its high availability and security. If so, the pull-through cache repositories may be just what you are looking for as they will pull down referenced images from the source and cache them within ECR.

_**Note**: The pull-through cache repository feature was added for re:Invent 2021 so the available public repositories are gradually being added. It is possible that the repository that you may want to pass-through from is not yet available._

Creating a pull-through cache repository is a relatively simple process. First, begin by selecting **Private registry** from the left-menu, and then click the **Edit** button in the _Pull through cache_ panel to change settings. This will bring up the _Pull through cache_ configuration page, where you click the **Add rule** button. This will bring up the Create window as shown in Figure 3.

![Creating a pull-through cache](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/a46qp4jkt0w2jc15kiqa.png)_Figure 3 Creating a pull through cache_

The first drop-down, _Public registry_, contains all the pre-configured public registries available; as you can see we selected _ECR Public_. Clicking the **Save** button will bring you back to the list of pull-through cache rules.

Since this is a pass-through, you need to combine both the pass through url and the referenced source when using a pull URL using the format of _<accountId>.dkr.ecr.<region>.amazonaws.com/<namespace>/<sourcerepo> :<tag>_. If you look into a container image definition you may see the following lines:

```
# Build runtime image
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
```

Using the pull-through cache means that, if you were going to use the ASP.NET Core base image from Bitnami that is available from the ECR Public repository, you would change the FROM command to reference the pull through source, as shown below.

```
# Build runtime image
FROM xxxxxxxxx.dkr.ecr.use-east-2.amazonaws.com/ecr-public/bitnami/aspnet-core:latest
WORKDIR /app
```
Be aware that this is more than a simple pull-through, as the image that you reference will be cached in ECR so that additional calls to that same image will not have to go to the final source repository. This means that the storage used will be charged to your account.

##Other approaches for creating an ECR repo

Just as with all the other services that we have talked about so far, there is the UI-driven way to build an ECR like we just went through and then several other approaches to creating a repo.

### AWS CLI

You can create an ECR repository in the AWS CLI using the create-repository command as part of the ECR service.

```
C:\>aws ecr create-repository 
    --repository-name prodotnetonaws 
    --image-scanning-configuration scanOnPush=true 
    --region us-east-1
```
You can control all of the basic repository settings through the CLI just as you can when creating the repository through the ECR console, including assigning encryption keys and defining the repository URI.

### AWS Tools for PowerShell

And, as you probably aren’t too surprised to find out, you can also create an ECR repository using AWS Tools for PowerShell:

```
C:\> New-ECRRepository 
-RepositoryName prodotnetonaws
-ImageScanningConfiguration_ScanOnPush $true
```

Just as with the CLI, you have the ability to fully configure the repository as you create it.

### AWS Toolkit for Visual Studio

When using the AWS Toolkit for Visual Studio you must depend upon the extension’s built-in default values because the only thing that you can control through the AWS Explorer is the repository name as shown in Figure 4. As you may notice, the AWS Explorer does not have its own node for ECR and instead puts the Repositories sub-node under the Amazon Elastic Container Service (ECS) node. This is a legacy from the past, before ECR really became its own service, but it is still an effective way to access and work with repositories in Visual Studio.

![Creating a pull-through cache](https://billthevestguy.com/wp-content/uploads/2022/05/image-28.png)_Figure 4, Creating a repository in Visual Studio_

Once you create a repository in Visual Studio, going to the ECR console and reviewing the repository that was created will show you that it used the default settings, so it is a private repository with both “Scan on push” and “KMS encryption” disabled.
At this point, the easiest way to show how this will all work is to create an image and upload it into the repository. We will then be able to use this container image as we go through the various AWS container management services.

_**Note**: You will not be able to complete many of these exercises without Docker installed on your machine. You will find download and installation instructions for Docker Desktop at [https://www.docker.com/products/docker-desktop](https://www.docker.com/products/docker-desktop). Once you have Desktop installed you will be able to locally build and run container images._
 
We will start by creating a simple .NET ASP.NET Core sample web application in Visual Studio through _File -> New Project_ and selecting the _ASP.NET Core Web App (C#)_ project template. You then name your project and select where to save the source code. Once that is completed you will get a new screen that asks for additional information. The checkbox for **Enable Docker** defaults as unchecked, so make sure you check it and then select the Docker OS to use, which in this case is Linux. This will create a simple solution that includes a Dockerfile as shown in Figure 5.

![New .NET solution with Dockerfile](https://billthevestguy.com/wp-content/uploads/2021/10/figure05-ecr5.png)_Figure 5. New .NET solution with Dockerfile_
 
If you look at the contents of the generated Dockerfile you will see that it is very similar to the Dockerfile that we walked through earlier, containing the instructions to restore and build the application, publish the application, and then copy the published application bits to the final image, setting the ENTRYPOINT. 

```
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS base
WORKDIR /app
EXPOSE 80
EXPOSE 443

FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /src
COPY ["SampleContainer/SampleContainer.csproj", "SampleContainer/"]
RUN dotnet restore "SampleContainer/SampleContainer.csproj"
COPY . .
WORKDIR "/src/SampleContainer"
RUN dotnet build "SampleContainer.csproj" -c Release -o /app/build

FROM build AS publish
RUN dotnet publish "SampleContainer.csproj" -c Release -o /app/publish

FROM base AS final
WORKDIR /app
COPY --from=publish /app/publish .
ENTRYPOINT ["dotnet", "SampleContainer.dll"]
```

If you look at your build options in Visual Studio as shown in Figure 6 you will see additional ones available for containers. The Docker choice, for example, will work through the Dockerfile, start the final container image within Docker, and then connect the debugger to that container so that you can debug as usual.
 
![Build options in a containerized application](https://billthevestguy.com/wp-content/uploads/2021/10/figure05-ecr6.png)_Figure 6. Build options in a containerized application_

_**Note**: If you want to see what is going on within the container build process, go to the output window, change the Show output from drop-down to Container Tools and then debug the application in Docker. You will see Docker commands being processed._

The next step is to create the container image and persist it into the repository. To do so, right click the project name in the Visual Studio Solution Explorer and select _Publish Container to AWS_ to bring up the wizard as shown in Figure 7.

![Publish Container to AWS wizard](https://billthevestguy.com/wp-content/uploads/2021/10/figure05-ecr7.png)_Figure 7. Publish Container to AWS wizard_

Figure 7 shows that the repository that we just created is selected as the repository for saving, and the _Publish only the Docker image to Amazon Elastic Container Registry_ option in the **Deployment Target** was selected (these are not the default values for each of these options). Once you have this configured, click the **Publish** button. You’ll see the window in the wizard grind through a lot of processing, then a console window may pop up to show you the actual upload of the image, and then the wizard will automatically close if successful.

You can see the new repository in Visual Studio as well as by logging into Amazon ECR and going into the _prodotnetonaws_ repository (the one we uploaded the image into), as shown in Figure 8, will show that there is now an image available within the repository with a _latest_ tag, just as configured in the wizard. You can click the icon with the Copy URI text to get the URL that you will use when working with this image. We recommend that you go ahead and do this at this point and paste it somewhere easy to find as that is the value you will use to access the image.

![Container image stored in Amazon ECR](https://billthevestguy.com/wp-content/uploads/2021/10/figure05-ecr8.png)_Figure 8. Container image stored in Amazon ECR_

Now that you have a container image stored in the repository, in the next post, we will look at how you could use it!