Deploy transpiled TypeScript code in Lambda with container images - Amazon Lambda
Services or capabilities described in Amazon Web Services documentation might vary by Region. To see the differences applicable to the China Regions, see Getting Started with Amazon Web Services in China (PDF).

Deploy transpiled TypeScript code in Lambda with container images

You can deploy your TypeScript code to an Amazon Lambda function as a Node.js container image. Amazon provides base images for Node.js to help you build the container image. These base images are preloaded with a language runtime and other components that are required to run the image on Lambda. Amazon provides a Dockerfile for each of the base images to help with building your container image.

If you use a community or private enterprise base image, you must add the Node.js runtime interface client (RIC) to the base image to make it compatible with Lambda.

Lambda provides a runtime interface emulator for local testing. The Amazon base images for Node.js include the runtime interface emulator. If you use an alternative base image, such as an Alpine Linux or Debian image, you can build the emulator into your image or install it on your local machine.

Using a Node.js base image to build and package TypeScript function code

To complete the steps in this section, you must have the following:

To create an image from an Amazon base image for Lambda
  1. On your local machine, create a project directory for your new function.

  2. Create a new Node.js project with npm or a package manager of your choice.

    npm init
  3. Add the @types/aws-lambda and esbuild packages as development dependencies. The @types/aws-lambda package contains the type definitions for Lambda.

    npm install -D @types/aws-lambda esbuild
  4. Add a build script to the package.json file.

    "scripts": { "build": "esbuild index.ts --bundle --minify --sourcemap --platform=node --target=es2020 --outfile=dist/index.js" }
  5. Create a new file called index.ts. Add the following sample code to the new file. This is the code for the Lambda function. The function returns a hello world message.


    The import statement imports the type definitions from @types/aws-lambda. It does not import the aws-lambda NPM package, which is an unrelated third-party tool. For more information, see aws-lambda in the DefinitelyTyped GitHub repository.

    import { Context, APIGatewayProxyResult, APIGatewayEvent } from 'aws-lambda'; export const handler = async (event: APIGatewayEvent, context: Context): Promise<APIGatewayProxyResult> => { console.log(`Event: ${JSON.stringify(event, null, 2)}`); console.log(`Context: ${JSON.stringify(context, null, 2)}`); return { statusCode: 200, body: JSON.stringify({ message: 'hello world', }), }; };
  6. Create a new Dockerfile with the following configuration:

    • Set the FROM property to the URI of the base image.

    • Set the CMD argument to specify the Lambda function handler.

    Example Dockerfile

    The following Dockerfile uses a multi-stage build. The first step transpiles the TypeScript code into JavaScript. The second step produces a container image that contains only JavaScript files and production dependencies.

    FROM as builder WORKDIR /usr/app COPY package.json index.ts ./ RUN npm install RUN npm run build FROM WORKDIR ${LAMBDA_TASK_ROOT} COPY --from=builder /usr/app/dist/* ./ CMD ["index.handler"]
  7. Build the Docker image with the docker build command. The following example names the image docker-image and gives it the test tag.

    docker build --platform linux/amd64 -t docker-image:test .

    The command specifies the --platform linux/amd64 option to ensure that your container is compatible with the Lambda execution environment regardless of the architecture of your build machine. If you intend to create a Lambda function using the ARM64 instruction set architecture, be sure to change the command to use the --platform linux/arm64 option instead.

  1. Start the Docker image with the docker run command. In this example, docker-image is the image name and test is the tag.

    docker run -p 9000:8080 docker-image:test

    This command runs the image as a container and creates a local endpoint at localhost:9000/2015-03-31/functions/function/invocations.

  2. From a new terminal window, post an event to the following endpoint using a curl command:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}'

    This command invokes the function with an empty event and returns a response. If you're using your own function code rather than the sample function code, you might want to invoke the function with a JSON payload. Example:

    curl "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{"payload":"hello world!"}'
  3. Get the container ID.

    docker ps
  4. Use the docker kill command to stop the container. In this command, replace 3766c4ab331c with the container ID from the previous step.

    docker kill 3766c4ab331c
To upload the image to Amazon ECR and create the Lambda function
  1. Run the get-login-password command to authenticate the Docker CLI to your Amazon ECR registry.

    • Set the --region value to the Amazon Web Services Region where you want to create the Amazon ECR repository.

    • Replace 111122223333 with your Amazon Web Services account ID.

    aws ecr get-login-password --region cn-north-1 | docker login --username AWS --password-stdin
  2. Create a repository in Amazon ECR using the create-repository command.

    aws ecr create-repository --repository-name hello-world --image-scanning-configuration scanOnPush=true --image-tag-mutability MUTABLE

    If successful, you see a response like this:

    { "repository": { "repositoryArn": "arn:aws:ecr:cn-north-1:111122223333:repository/hello-world", "registryId": "111122223333", "repositoryName": "hello-world", "repositoryUri": "", "createdAt": "2023-03-09T10:39:01+00:00", "imageTagMutability": "MUTABLE", "imageScanningConfiguration": { "scanOnPush": true }, "encryptionConfiguration": { "encryptionType": "AES256" } } }
  3. Copy the repositoryUri from the output in the previous step.

  4. Run the docker tag command to tag your local image into your Amazon ECR repository as the latest version. In this command:

    • Replace docker-image:test with the name and tag of your Docker image.

    • Replace <ECRrepositoryUri> with the repositoryUri that you copied. Make sure to include :latest at the end of the URI.

    docker tag docker-image:test <ECRrepositoryUri>:latest


    docker tag docker-image:test
  5. Run the docker push command to deploy your local image to the Amazon ECR repository. Make sure to include :latest at the end of the repository URI.

    docker push
  6. Create an execution role for the function, if you don't already have one. You need the Amazon Resource Name (ARN) of the role in the next step.

  7. Create the Lambda function. For ImageUri, specify the repository URI from earlier. Make sure to include :latest at the end of the URI.

    aws lambda create-function \ --function-name hello-world \ --package-type Image \ --code \ --role arn:aws:iam::111122223333:role/lambda-ex
  8. Invoke the function.

    aws lambda invoke --function-name hello-world response.json

    You should see a response like this:

    { "ExecutedVersion": "$LATEST", "StatusCode": 200 }
  9. To see the output of the function, check the response.json file.

To update the function code, you must build the image again, upload the new image to the Amazon ECR repository, and then use the update-function-code command to deploy the image to the Lambda function.