Deploying Existing .NET 5 Project with Docker to AWS Lambda.

Introduction.

In this article we will be demonstrating how to deploy an existing .Net 5 project to AWS Lambda as container image. With AWS Lambda, you upload your code and run it without thinking about servers. Many customers enjoy the way this works, but if you've invested in container tooling for your development workflows, it's not easy to use the same approach to build applications using Lambda. To help you with that, you can now package and deploy Lambda functions as container images of up to 10 GB in size. In this way, you can also easily build and deploy larger workloads that rely on sizable dependencies, such as machine learning or data intensive workloads.

Dependencies

Install Docker

Docker is an open platform for developing, shipping, and running applications. Docker enables you to separate your applications from your infrastructure so you can deliver software quickly. With Docker, you can manage your infrastructure in the same ways you manage your applications. By taking advantage of Docker's methodologies for shipping, testing, and deploying code quickly, you can significantly reduce the delay between writing code and running it in production.

Install AWS Visual Studio Plugin

The AWS Toolkit for Visual Studio is an extension for Microsoft Visual Studio running on Microsoft Windows that makes it easier for developers to develop, debug, and deploy applications using Amazon Web Services, allowing you to get started faster and be more productive.

Install Amazon.Lambda.Tools

To be able to deploy the project to AWS, we need to install Amazon.Lambda.Tools using the following command:

								
					dotnet tool install -g Amazon.Lambda.Tools
								  
							

If the tool is already installed, be sure to update to the latest version using the following command:

								
					dotnet tool update -g Amazon.Lambda.Tools
								  
							

Files to add

Add the following files to your project root folder.

Dockerfile

A template file for defining your Serverless functions and other AWS resources using AWS CloudFormation Serverless Application Model.


FROM public.ecr.aws/lambda/dotnet:5.0 AS base
WORKDIR /var/task

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

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

FROM base AS final
WORKDIR /var/task
COPY --from=publish /app/publish .
CMD [ "TimeProject::TimeProject.LambdaEntryPoint::FunctionHandlerAsync"]
  
							

 

serverless.template

A template file for defining your Serverless functions and other AWS resources using AWS CloudFormation Serverless Application Model.


	{
		"AWSTemplateFormatVersion": "2010-09-09",
		"Transform": "AWS::Serverless-2016-10-31",
		"Description": "An AWS Serverless Application that uses the ASP.NET Core framework running in Amazon Lambda.",
		"Parameters": {},
		"Conditions": {},
		"Resources": {
			"AspNetCoreFunction": {
			"Type": "AWS::Serverless::Function",
			"Properties": {
				"PackageType": "Image",
				"ImageConfig": {
				"EntryPoint": [
					"/lambda-entrypoint.sh"
				],
				"Command": [
					"TimeProject::TimeProject.LambdaEntryPoint::FunctionHandlerAsync"
				]
				},
				"ImageUri": "",
				"MemorySize": 256,
				"Timeout": 30,
				"Role": null,
				"Policies": [
				"AWSLambda_FullAccess"
				],
				"Events": {
				"ProxyResource": {
					"Type": "Api",
					"Properties": {
					"Path": "/{proxy+}",
					"Method": "ANY"
					}
				},
				"RootResource": {
					"Type": "Api",
					"Properties": {
					"Path": "/",
					"Method": "ANY"
					}
				}
				}
			},
			"Metadata": {
				"Dockerfile": "Dockerfile",
				"DockerContext": ".",
				"DockerTag": ""
			}
			}
		},
		"Outputs": {
			"ApiURL": {
			"Description": "API endpoint URL for Prod environment",
			"Value": {
				"Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
			}
			}
		}
		}
  
							

 

aws-lambda-tools-defaults.json

This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.


	{
		"Information": [
			"This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
			"To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
			"dotnet lambda help",
			"All the command line options for the Lambda command can be specified in this file."
		],
		"profile": "default",
		"region": "eu-central-1",
		"configuration": "Release",
		"s3-prefix": "TimeProject/",
		"template": "serverless.template",
		"template-parameters": "",
		"docker-host-build-output-dir": "./bin/Release/net5.0/linux-x64/publish",
		"image-command": "TimeProject::TimeProject.LambdaEntryPoint::FunctionHandlerAsync",
		"s3-bucket": "timeproject-api-deploy",
		"stack-name": "timeproject-api-deploy"
	}
  

 

LambdaEntryPoint.cs

Class that derives from Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction. The code in this file bootstraps the ASP.NET Core hosting framework.


namespace TimeProject
{
    /// 
    /// This class extends from APIGatewayProxyFunction which contains the method FunctionHandlerAsync which is the 
    /// actual Lambda function entry point. The Lambda handler field should be set to
    /// 
    /// TimeProject::TimeProject.LambdaEntryPoint::FunctionHandlerAsync
    /// 
    public class LambdaEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
    {
        /// 
        /// The builder has configuration, logging and Amazon API Gateway already configured. The startup class
        /// needs to be configured in this method using the UseStartup<>() method.
        /// 
        /// 
        protected override void Init(IWebHostBuilder builder)
        {
            builder
               .UseStartup();
        }

        protected override void Init(IHostBuilder builder)
        {

        }
    }
}

  

Before And After


 

Finally let's change the project type.

We can do so by simply adding the following line of code inside PropertyGroup tag in your .csproj project file.

	
	<AWSProjectType>Lambda</AWSProjectType>
	
	

Publish Project

To deploy, right click on the project and select Publish to AWS Lambda.


 

Fill in the bucket name and stack name if you have not done so already.


 

Once ready publish, you should see a screen.


 

Pushing to aws image container.


 

Publishing to Lambda.


 

Results.

Conclusion.

In this article, we have demonstrated how to deploy existing .Net 5 project to AWS Lambda. The following resources might helpful, If you want to learn more about AWS Lambda docker and understand more about the subject here

Happy Hacking! :)

Sources

https://github.com/aws/aws-lambda-dotnet https://aws.amazon.com/blogs/aws/new-for-aws-lambda-container-image-support/ https://aws.amazon.com/blogs/developer/net-5-aws-lambda-support-with-container-images/

Our greatest weakness lies in giving up. The most certain way to succeed is always to try just one more time.

Thomas A. Edison