Learn About Amazon VGT2 Learning Manager Chanci Turner
In recent times, there has been a surge in interest among customers for hosting microservices-based applications using Amazon Elastic Container Service (ECS), primarily due to the advantages that AWS Fargate provides. AWS Fargate is a container compute engine that enables you to run containers without needing to provision, manage, or scale any Amazon EC2 instances. Fargate integrates seamlessly with Amazon ECS and supports microservices created in various programming languages and frameworks, including Java, .NET Core, Python, Node.js, Go, and Ruby on Rails. Nowadays, organizations building microservices with .NET are increasingly opting for .NET Core because of its cross-platform capabilities, allowing it to run on Linux.
This article will guide you on how to host a cross-platform ASP.NET Core application using AWS Fargate.
Reference Architecture
A solid reference architecture for deploying applications with AWS Fargate should encompass the VPC, Subnets, Load Balancer, Internet Gateway, Elastic Network Interface (ENI), AWS Fargate Task, Network ACLs, and Security Groups. The architectural decisions regarding VPC Networking, Load Balancing, and Container Networking carry significant weight.
There are two primary networking strategies for deploying containers in Amazon ECS:
- Deploy containers within a public VPC Subnet with direct Internet access.
- Deploy containers within a private VPC Subnet without direct Internet access.
Since the ASP.NET Core application will be handling traffic from the Internet, we will opt for deploying containers in the Public VPC Subnet with direct Internet access.
For routing traffic to containers via the Load Balancer, you have a couple of options:
- A public Load Balancer that accepts traffic from the Internet and routes it to the container through the AWS Fargate Task’s Elastic Network Interface (ENI).
- A private Internal Load Balancer that only accepts traffic from other containers within the cluster.
Given that the ASP.NET Core application container operates in the web tier, we will select a public Load Balancer. This Load Balancer will accept Internet traffic and direct it to the container via the AWS Fargate Task’s Elastic Network Interface (ENI).
Taking these factors into account, the reference architecture for deploying to AWS Fargate would resemble the following diagram:
[Diagram not included]
This solution positions containers within a public Subnet (inside a VPC). The AWS Fargate Task and the two containers have direct Internet access and are accessible to clients through the public Load Balancer.
Implementation Steps
To bring this architecture to life, we will perform the following actions:
- Containerize the ASP.NET Core application.
- Configure the reverse-proxy server.
- Containerize the NGINX reverse-proxy server.
- Create the Docker Compose file.
- Push container images to Amazon ECR.
- Establish the ECS cluster.
- Create an Application Load Balancer.
- Define an AWS Fargate Task.
- Set up the Amazon ECS service.
Code Examples
The code samples, Dockerfile definitions, Docker Compose files, and ECS task definitions for this solution can be found in the amazon-ecs-fargate-aspnetcore GitHub repository.
Prerequisites
Your development environment should meet the following prerequisites:
- Mac OS (latest version), Windows 10 (latest updates), or Ubuntu 16.04 or higher.
- .NET Core 2.0 or higher.
- Latest version of Docker.
- AWS CLI.
- AWS ECS CLI.
Containerizing the ASP.NET Core Application
The initial step is to containerize the ASP.NET Core application. If you’re utilizing Visual Studio 2017 or later with the latest updates on Windows, you can add container support to your solution. Simply right-click the existing project and select the option to add Docker support. For those developing on Linux or Mac OS, you will need to create a Dockerfile manually.
Your Dockerfile should resemble the following, regardless of the operating system:
FROM microsoft/aspnetcore:2.0
WORKDIR /mymvcweb
COPY bin/Release/netcoreapp2.0/publish .
ENV ASPNETCORE_URLS http://+:5000
EXPOSE 5000
ENTRYPOINT ["dotnet", "mymvcweb.dll"]
This Dockerfile generates an application container derived from the microsoft/aspnetcore:2.0 base image. It publishes the contents from the bin/Release folder to a designated work directory, initiates the default Kestrel web server, and listens on port 5000 to handle web traffic.
By default, ASP.NET Core utilizes Kestrel as its web server. Kestrel is lightweight and ideal for serving dynamic content from ASP.NET Core. However, for functionalities like serving static content, caching requests, compressing requests, and managing SSL terminations, employing a dedicated reverse-proxy server like NGINX is advisable.
Configuring the Reverse-Proxy Server
NGINX can serve as both the HTTP and reverse-proxy server. Its asynchronous, event-driven architecture is highly efficient, enabling it to manage thousands of concurrent requests while maintaining a small memory footprint.
In this setup, we will deploy an NGINX (reverse-proxy server) container in front of the ASP.NET Core application container, which is defined in the AWS Fargate Task. The reverse-proxy configuration file, nginx.conf, should be defined as follows:
worker_processes 4;
events { worker_connections 1024; }
http {
sendfile on;
upstream app_servers {
server 127.0.0.1:5000;
}
server {
listen 80;
location / {
proxy_pass http://app_servers;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $server_name;
}
}
}
The NGINX container is configured to listen on port 80 and forwards requests to the application container listening on port 5000. Notably, the upstream app_server in the nginx.conf file should be set to mymvcweb:5000 in the local development environment.
Containerizing the NGINX Reverse-Proxy Server
To containerize the NGINX reverse-proxy server, create a Dockerfile that looks like this:
FROM nginx
COPY nginx.conf /etc/nginx/nginx.conf
Creating the Docker Compose File
Next, use Docker Compose to define these two containers as microservices in your local development setup. Your Docker Compose file should appear as follows:
version: '2'
services:
mymvcweb:
build:
context: ./mymvcweb
dockerfile: Dockerfile
expose:
- "5000"
reverseproxy:
build:
context: ./reverseproxy
dockerfile: Dockerfile
ports:
- "80:80"
links:
- mymvcweb
You can build and test these two containers using the following Docker Compose commands:
docker-compose build
docker-compose up
After starting the containers, navigate to http://localhost:80 in your browser to see the default view of ‘index.cshtml’. To apply any changes made to the application code or container definitions, clear the Docker Compose cache by running the following commands:
For further insights into career development, consider exploring this blog post on mentorship. Also, if you’re looking for guidance on resume writing, SHRM is an authoritative source. Additionally, Amazon’s resource provides excellent insights into employee training practices.