Terraform — Deploy Nodejs Application with AWS AppRunner
Tags: terraform, aws, node, devops
Published: 2021-08-17 07:49:58

In this article, we are talking about How we can deploy Nodejs Application with AWS AppRunner service deployment using Terraform.

![Terraform — Deploy Nodejs Application with AWS AppRunner](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/elwbc3o2zy8j7kjdhwib.jpg)

AWS App Runner is a fully managed service that makes it easy for developers to quickly deploy containerized web applications and APIs, at scale and with no prior infrastructure experience required. Start with your source code or a container image. App Runner automatically builds and deploys the web application and load balances traffic with encryption. App Runner also scales up or down automatically to meet your traffic needs. With App Runner, rather than thinking about servers or scaling, you have more time to focus on your applications.

## Prerequisites

* We require AWS IAM API keys (access key and secret key) for creating and deleting permissions for all AWS resources.
* Github account and new repository.
* Terraform should be installed on the machine. If Terraform does not exist you can download and install it from here.

## Prepare a Demo NodeJS Application

Create a project directory named demo-application anywhere in your system and make it your current directory:

```
mkdir demo-application
cd demo-application
```

Execute the following command within the demo-application directory to initialize your Node.js project with default settings:

```
npm init -y
```

## Set Up Express with Node.js

To use the Express framework in your application, install it as a project dependency:

```
npm i express
```

After that package.json look like below

```
{
  "name": "demo-application",
  "version": "1.0.0",
  "description": "demo-application",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "express",
    "hello-world"
  ],
  "author": "Prashant_B",
  "license": "MIT",
  "dependencies": {
    "express": "^4.15.0"
  }
}
```

Then, create the entry point of the application, a file named index.js:

```
touch index.js
```

Add following code in index.js file.

```
var express = require('express')
var app = express() 
app.get('/', function (req, res) {
  res.send('Hello World!')
}) 
app.listen(3000, function () {
  console.log('Listening on port 3000...')
})
```

This app starts a server and listens on port 3000 for connections. The app responds with “Hello World!” for requests to the root URL (/) or route. For every other path, it will respond with a 404 Not Found.

Our demo application was ready now goto GitHub, create new repository and push application source code to GitHub repository.
Let’s move to Terraform
version

To build AWS App Runner, you need to meet the following versions:

* Terraform v0.12 or higher
* Latest version of AWS provider (3.42.0)
    Configuring App Runner in the Terraform AWS Provider

This time I built it with the following version.

```
$ terraform version
Terraform v1.0.0
on linux_amd64
```

Amazon Resources Created Using Terraform

A Terraform module is a set of Terraform configuration files in a single directory. Even a simple configuration consisting of a single directory with one or more .tf files is a module. When you run Terraform commands directly from such a directory, it is considered the root module

1. IAM Module

* IAM Role and policy

2. AppRunner Module

* Auto scaling configuration
* AWS Apprunner service
* AWS Apprunner github connection

Create an IAM role to grant to App Runner

Following code create IAM role and policy for Build AWS App Runner service.

The key `build.apprunner.amazonaws.com` is `tasks.apprunner.amazonaws.com` to specify and for the service to which AssumeRole is assigned.

After that, AWS has prepared a policy for App Runner, so attach it to the IAM role.

```
resource "aws_iam_role" "role" {
   name = "test-role"
   assume_role_policy = <<EOF 
{
   "Version": "2012-10-17",
   "Statement": [
     {
       "Action": "sts:AssumeRole",
       "Principal": {
         "Service": [
           "build.apprunner.amazonaws.com",
           "tasks.apprunner.amazonaws.com"
         ]
       },
       "Effect": "Allow",
       "Sid": ""
     }
   ]
 } EOF 
}
resource "aws_iam_role_policy_attachment" "test-attach" {
   role       = aws_iam_role.role.name
   policy_arn = "arn:aws:iam::aws:policy/service-role/AWSAppRunnerServicePolicyForECRAccess"
 }
```

## Create an App Runner

Finally, create an App Runner resource in Terraform.

There are some App Runner related resources, but they are the main resources for actually creating App Runner aws_apprunner_service,
source_configuration

We have 2 ways to deploy App Runner with ECR repository.

* Deploy App Runner with ECR private repository
* Deploy App Runner with ECR public repository

###Deploy App Runner with ECR private repository

```
resource "aws_apprunner_auto_scaling_configuration_version" "ngnix-apprunner-autoscaling" {
  auto_scaling_configuration_name = "demo_auto_scalling"
  max_concurrency = 100
  max_size        = 5
  min_size        = 1

  tags = {
    Name = "demo_auto_scalling"
  }
}

resource "aws_apprunner_service" "ngnix-apprunner-service-ecr" {
  service_name = "demo_apprunner"

  source_configuration {
    image_repository {
      image_configuration {
        port = "80"
      }
      image_identifier      = "XXXXX.dkr.ecr.us-east-2.amazonaws.com/nginx-web:latest"
      image_repository_type = "ECR"
    }
    authentication_configuration{
      access_role_arn = aws_iam_role.role.arn
    }
    auto_deployments_enabled = true
  }

  auto_scaling_configuration_arn = aws_apprunner_auto_scaling_configuration_version.ngnix-apprunner-autoscaling.arn

  health_check_configuration {
          healthy_threshold   = 1
          interval            = 10
          path                = "/"
          protocol            = "TCP"
          timeout             = 5
          unhealthy_threshold = 5
        }

  tags = {
    Name = "demo_apprunner"
  }
}
```

###Deploy App Runner with ECR public repository

>Note: In this approach we don't need IAM role.

```
resource "aws_apprunner_auto_scaling_configuration_version" "ngnix-apprunner-autoscaling" {
  auto_scaling_configuration_name = "demo_auto_scalling"
  max_concurrency = 100
  max_size        = 5
  min_size        = 1

  tags = {
    Name = "demo_auto_scalling"
  }
}

resource "aws_apprunner_service" "ngnix-apprunner-service-ecr-public" {
  service_name = "demo_apprunner"

  source_configuration {
    image_repository {
      image_configuration {
        port = var.port
      }
      image_identifier      = "public.ecr.aws/nginx/nginx:latest"
      image_repository_type = "ECR_PUBLIC"
    }
    auto_deployments_enabled = false
  }

  auto_scaling_configuration_arn = aws_apprunner_auto_scaling_configuration_version.ngnix-apprunner-autoscaling.arn

  health_check_configuration {
          healthy_threshold   = 1
          interval            = 10
          path                = "/"
          protocol            = "TCP"
          timeout             = 5
          unhealthy_threshold = 5
        }

  tags = {
    Name = "demo_apprunner"
  }
}
```

### Check the URL of App Runner created by applying

I want to check the URL of the created App Runner as the execution result of the apply command, so `output` set.

```
output "app_runner_url" {
  value = aws_apprunner_service.example.service_url
}
```

After that, just run the following commands.

>terraform init
>terraform plan
>terraform apply

it will take 2 to 3 minutes to complete the execution.
When the execution is completed, the URL will be displayed as shown below, so let’s access it.
```
app_runner_url = "xxxxx.us-east-2.awsapprunner.com/"
```

*Thank you for reading, if you have anything to add please send a response or add a note!*