DEV Community

Cover image for How to Deploy Dart Functions to AWS Lambda
Shinya Kato
Shinya Kato

Posted on

How to Deploy Dart Functions to AWS Lambda

Introduction

While AWS Lambda, a highly popular serverless computing service, does not officially provide a Dart runtime, you can deploy functions created in Dart to AWS Lambda using the custom runtime mechanism.

Deploying Dart functions to AWS Lambda enables you to utilize them not only within AWS Lambda but also integrate them with services like Amazon API Gateway, allowing you to leverage them in Flutter applications as well. This unified codebase in Dart offers great convenience.

In this article, we will briefly introduce how to deploy Dart functions to AWS Lambda.

Preparation

In this article, we will use Serverless Framework and Docker Desktop to deploy Dart functions to AWS Lambda. If you haven't installed them yet, please complete the installation using the following commands or links.

Additionally, you'll need an AWS account and access tokens for AWS services.

AWS Account

https://aws.amazon.com

AWS Authentication Token

Once you have generated the authentication token, set it in the environment variables as follows:

export AWS_ACCESS_KEY_ID=xxxxxxxxxx
export AWS_SECRET_ACCESS_KEY=xxxxxxxxxx
Enter fullscreen mode Exit fullscreen mode

Serverless Framework

brew install serverless
Enter fullscreen mode Exit fullscreen mode

https://www.serverless.com/

Docker Desktop

https://www.docker.com/products/docker-desktop/

Implementation and Registration of Functions

Now let's implement the Dart function to deploy it to AWS Lambda.

Project Structure

We'll proceed with the following structure. Details about Dockerfile and serverless.yml will be explained later.

.
├── Dockerfile
├── LICENSE
├── analysis_options.yaml
├── lib
│   ├── functions.dart
│   └── main.dart
├── pubspec.lock
├── pubspec.yaml
└── serverless.yml
Enter fullscreen mode Exit fullscreen mode

Installing Packages

When deploying to AWS Lambda, you'll need to use the Dart custom runtime aws_lambda_dart_runtime_ns. Please add it to your dependencies in pubspec.yaml using the following command or manually:

https://pub.dev/packages/aws_lambda_dart_runtime_ns

dart pub add aws_lambda_dart_runtime_ns
Enter fullscreen mode Exit fullscreen mode
dart pub get
Enter fullscreen mode Exit fullscreen mode
name: sample

environment:
  sdk: ^3.3.4

dependencies:
  aws_lambda_dart_runtime_ns: ^0.0.13

dev_dependencies:
  lints: ^3.0.0
  test: ^1.24.0
Enter fullscreen mode Exit fullscreen mode

Creating a Function to Deploy to AWS Lambda

Let's create a simple function to deploy to AWS Lambda.
For now, let's make the function simply return the string Hello, World! when called.

import 'package:aws_lambda_dart_runtime_ns/aws_lambda_dart_runtime_ns.dart';

FunctionHandler get sayHelloWorld {
  return FunctionHandler(
    name: 'hello-world',
    action: (context, event) {
      // Perform various operations here such as 
      // file IO, database operations, etc.

      return InvocationResult(
        requestId: context.requestId,
        body: {
          'message': 'Hello, World!',
        },
      );
    },
  );
}
Enter fullscreen mode Exit fullscreen mode

To briefly explain, the FunctionHandler object represents the function executed on AWS Lambda.

The name of FunctionHandler is the required name when the function (or command) is invoked.
Additionally, this name must be associated with the command definition in serverless.yml, which will be introduced later.

The action of FunctionHandler defines the actual behavior of the function (or command). In this example, it simply returns the message 'Hello, World!', but you can perform various operations such as file operations or DB operations within action.

The InvocationResult needed to be returned in action represents the result of the processing. You can set any JSON data in the body of InvocationResult.

Registering the Created Function to the Custom Runtime

Let's register the sayHelloWorld function we created earlier to the custom runtime. It's very simple.

import 'package:aws_lambda_dart_runtime_ns/aws_lambda_dart_runtime_ns.dart';
import 'package:sample/functions.dart' as fn;

Future<void> main(List<String> args) async {
  await invokeAwsLambdaRuntime([
    fn.sayHelloWorld, // This is what you need to do
  ]);
}
Enter fullscreen mode Exit fullscreen mode

When registering the created function to the custom runtime, all you need to do is call the invokeAwsLambdaRuntime function and pass the functions you want to register as arguments.

With this, the process of creating the function you want to register with AWS Lambda and registering it with the custom runtime is complete.

Deploying to AWS Lambda

Once you've reached this point, all that's left is to deploy the program you've created to AWS Lambda.
We'll define the Dockerfile and serverless.yml as follows:

I'm not very knowledgeable about hardware, but it seems that using ARM-based AWS Graviton makes you happy, so we'll proceed with an architecture based on arm64.

Dockerfile

FROM arm64v8/dart:latest as build-image

WORKDIR /work
COPY ./ ./

RUN dart pub get
RUN dart compile exe ./lib/main.dart -o ./bootstrap
RUN chmod +x bootstrap

FROM --platform=linux/arm64 public.ecr.aws/lambda/provided:latest

COPY --from=build-image /work/bootstrap /var/runtime/

CMD ["dummyHandler"]
Enter fullscreen mode Exit fullscreen mode

If the folder structure where the Dart program is located is different, please modify the ./lib/main.dart part accordingly.

serverless.yml

service: sample-app

provider:
  name: aws
  runtime: provided
  timeout: 30
  region: ap-northeast-1
  architecture: arm64
  ecr:
    images:
      appImage:
        path: ./
        platform: linux/arm64

functions:
  hello-world:
    image:
      name: appImage
      command:
        - hello-world
Enter fullscreen mode Exit fullscreen mode

Since there is no specific preference for the region, let's use ap-northeast-1 (Tokyo) for now.

When defining functions, please pay attention to ensuring that the name of the command matches the name defined earlier for FunctionHandler.

Deployment

Once you have configured everything, you can deploy the function you created to AWS Lambda using the following Serverless Framework command:

Please make sure Docker Desktop is running before executing the command.

sls deploy
Enter fullscreen mode Exit fullscreen mode
sls deploy
Running "serverless" from node_modules
(node:6460) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)

Deploying sample-app to stage dev (ap-northeast-1)

✔ Service deployed to stack sample-app-dev (32s)

functions:
  hello-world: sample-app-dev-hello-world
Enter fullscreen mode Exit fullscreen mode

References

The project created in this article is publicly available in the following repository. If you'd like to quickly try it out, feel free to clone or fork it and deploy it to AWS Lambda to play around with.

https://github.com/myConsciousness/sample-aws-lambda-with-dart-runtime

Top comments (0)