This tutorial covers:

  1. Creating a container image for a cloned .Net Core demo application, building and running the container locally
  2. Deploying the Docker image to AWS ECR
  3. Writing a configuration file to automate building and deploying your container image using CircleCI

Containers are a useful tool for deploying applications because they allow for the packaging of an application’s code, libraries, and dependencies into a single, isolated unit. This makes it easy to deploy and run the application on any computer or server that has the necessary container software installed.

AWS Elastic Container Registry (ECR) is a managed container registry service used to store, manage, and deploy container images. It is fully integrated with other AWS services and provides a scalable and secure way to manage your container images. ECR allows you to store and retrieve images using the Docker CLI, and also integrates with other Docker tools like Docker Compose and Docker Swarm. With ECR, you can easily store and manage your Docker images in a central location and access them from anywhere in your AWS account.

In this tutorial, you will build an ASP.NET Core container with Docker and push the container image to Amazon Elastic Container Registry (Amazon ECR). When you complete the project, every new container image built as a result of changes made to your codebase will be pushed and stored on the AWS container registry.

Prerequisites

You will need the following for this tutorial:

Our tutorials are platform-agnostic, but use CircleCI as an example. If you don’t have a CircleCI account, sign up for a free one here.

Cloning the demo project

To begin, issue this command from the terminal to clone the demo project from GitHub using Git:

git clone https://github.com/CIRCLECI-GWP/docker-dotnet-api-ecr

This will clone the project into a docker-dotnet-api-ecr folder in your development folder (or whenever you ran the command from).

Building the Docker image locally

To build a custom Docker image for this project, you need to create a special type of file named Dockerfile.

Dockerfile is a text file that contains a set of instructions for building a Docker image. It is a simple, yet powerful tool that allows developers to define the environment and dependencies needed to run their applications in a consistent and reliable manner.

In this tutorial, you will use the Dockerfile included in the downloaded demo project to build the custom container image. The Dockerfile has the commands needed to install all the project’s dependencies, build the project, and run it.

Go to the root directory of the application, open the Dockerfile, and make sure it has this content:

# Build Stage
FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build
WORKDIR /app
COPY . ./
RUN dotnet restore
RUN dotnet publish -c Release -o output

# Serve Stage
FROM mcr.microsoft.com/dotnet/aspnet:6.0 AS runtime
WORKDIR /app
COPY --from=build /app/output .
ENTRYPOINT [ "dotnet", "docker-dotnet-api.dll" ]

There are two different stages specified in this file:

  • Build uses the .NET SDKto install any required dependencies before building the project and publishing it to a folder named out.
  • Serve uses the ASP.NET Core runtime image to run the application from the specified working directory, which is app in this case.

This is sometimes called a multi-stage Dockerfile. It combines development and production instructions into a single Dockerfile and reduces complexity in the process.

Next, issue this command to build the Docker image:

docker build -t dotnet-api:latest .

Based on the content of the application and the Dockerfile, this command will build the container image. You can confirm that the image was created using the command below to print out list of container images:

docker images

You will see a list of images, including dotnet-api.

REPOSITORY          TAG       IMAGE ID       CREATED          SIZE
dotnet-api          latest    b7b390e1661b   43 seconds ago   215MB

Running the Docker image locally

With the local version of the container image successfully built, run it with this command:

docker run -dit -p 5001:80 dotnet-api:latest

This command runs the container in the background, prints the container ID to the terminal, and runs the app on port 5001. Visit http://localhost:5001/api/weather to review it.

App running on Docker locally

Deploying the Docker image to Amazon ECR

In this section, you will create a user that will programmatically have access to push container images to the Amazon registry. To do that, navigate to AWS management console and select IAM. This service lets you manage access to AWS resources.

AWS console

Create a user with a unique name. I called mine dotnet-user. Make sure you tick option Access key - Programmatic access.

Add user

Next, set permissions for the user. Click Attach existing policies directly. Search for and choose these policies:

  • AmazonEC2ContainerRegistryFullAccess: This policy allows user to have full access to the container registry and its APIs.
  • AmazonEC2ContainerRegistryPowerUser: This grants user the administrative right to read and write to repositories.

Set permissions

From here, click Next twice, then click the Create User button in the Review Page.

You will be presented a success message along with your user credentials. This page is displayed only once, so make a note of the Access Key ID and the Secret access key. If you prefer, you can download a .csv file that contains the same credentials.

Credentials created

Automating container image deployment

Next, you will use CircleCI to automate the deployment of your Docker image to Amazon ECR. To easily do this, you will leverage the Circle Orb name circleci/aws-ecr specifically created with commands to automatically:

  1. Build a Docker image
  2. Login to Amazon container registry
  3. Create an Amazon ECR repo, if one doesn’t exist and
  4. Push the image to Amazon ECR

The downloaded project already contains a .circleci folder with a config.yml file in it. Open the config.yml file and make sure it has this content:

version: 2.1
orbs:
  aws-ecr: circleci/aws-ecr@8.1.3
workflows:
  build_and_push_image:
    jobs:
      - aws-ecr/build-and-push-image:
          context: dev
          create-repo: true
          dockerfile: Dockerfile
          path: .
          repo: dotnet-ecr
          tag: "$CIRCLE_SHA1"

This configuration file uses the Amazon Elastic Container Registry orb to build and deploy the Docker image. The dockerfile: command specifies the path to your Dockerfile.

The repo command specified the ECR repository as dotnet-ecr. This will be created if it doesn’t exist as stated by the create-repo flag. Also, to successfully deploy images to Amazon ECR, it is required that you supply your Amazon credentials. For that, you should use contexts in CircleCI.

Adding Context for Amazon ECR credentials

From your CircleCI dashboard, go to the Organization Settings page by clicking on the link in the sidebar.

Then, select Contexts, click the Create Context button, and add a unique name for your Context. The Context appears in a list with security set to All members. This means that anyone in your organization can access this Context at runtime. As specified in the .circleci/config.yml configuration for this tutorial, the Context name should be dev.

Create context

Next, select the dev context, click Add Environment Variable and enter these variables:

  • AWS_ACCESS_KEY_ID - The AWS access key id for the dotnet-user IAM role you had created earlier.
  • AWS_SECRET_ACCESS_KEY - AWS secret key for dotnet-user IAM role that you had created earlier.
  • AWS_ECR_REGISTRY_ID - The 12 digit AWS id associated with the ECR account. This is also known as account ID. You can find this from the AWS Support Page.
  • AWS_REGION - AWS region where your ECR resources will be located.

Connecting the application to CircleCI

Now you can change your remote repository URL if you cloned the repo for this tutorial and push your project to GitHub.

Log in to your CircleCI account. If you signed up with your GitHub account, all your repositories will be available on your project’s dashboard. Locate the dotnet-ecr project and click Set Up Project.

Select project

Enter the name of the branch where your code is housed on GitHub and click Set Up Project.

Set up project

Your first workflow will start running and complete successfully.

Pipeline build successful

To view the repository information, go to your AWS management Console.

View image url

Conclusion

With CircleCI deployment properly configured, you can easily make changes to your codebase, deploy to GitHub and be assured that your Docker image on Amazon container registry will always be updated with a new version without any manual effort from you.

I hope that you found this tutorial helpful. Happy coding!


Oluyemi is a tech enthusiast with a background in Telecommunication Engineering. With a keen interest in solving day-to-day problems encountered by users, he ventured into programming and has since directed his problem solving skills at building software for both web and mobile. A full stack software engineer with a passion for sharing knowledge, Oluyemi has published a good number of technical articles and blog posts on several blogs around the world. Being tech savvy, his hobbies include trying out new programming languages and frameworks.

Read more posts by Olususi Oluyemi