From Source Code to Web Service with AWS AppRunner

Yogesh Rajput, Senior NodeJS Developer / Dhruv Chevli, AWS DevOps Engineer

In the ever-evolving landscape of cloud computing and application deployment, simplicity, efficiency, and automation are paramount. Engineers and developers, whether seasoned professionals or passionate hobbyists, often find themselves grappling with the challenge of converting their source code into a fully functioning web service.

While there are countless modern tools and platforms available for this purpose, sometimes the best approach is to stick with what you know best—your trusted tool-set.

For us, the path of least resistance begins with Amazon Web Services (AWS) and its Serverless capabilities or Docker containers. AWS offers a robust ecosystem that simplifies the process of transitioning from code to a live web service, and one of the standout tools in this arsenal is AWS AppRunner.

imageHeader

In this guide, we'll embark on a journey that starts with your source code and ends with a fully deployed web service, all orchestrated seamlessly by AWS AppRunner. Whether you're an AWS professional or just getting started with AWS, this tutorial will demystify the process and empower you to deploy your applications quickly and efficiently.

We'll dive into the essential steps, including AWS setup, AWS CLI configuration, and ensuring that you have the necessary permissions to access AWS services. You'll learn how to containerize your application using Docker, store your container image in Amazon Elastic Container Registry (ECR), and use AWS AppRunner to take care of the deployment heavy lifting.

App Runner in Use: We are using AWS App Runner as a Dev/QA environment for one of our customers since it's inception. While App Runner is still a relatively new services compared to other AWS Compute Services, it does the job really well.


Specially on the Initial Setup, Auto-Scaling, VPC Connectivity, HTTPS-Enabled,Easy to Integrate with Certificate Manager, Auto deploy etc.


For us, the only downside so far is the No Support for Web Socket.


https://github.com/aws/apprunner-roadmap/issues/13

By the end of this guide, you'll have the skills and knowledge to turn your source code into a running web service with ease, and you'll be equipped with the tools to automate and streamline this process for future projects. Let's get started on this exciting journey from source code to web service with AWS AppRunner.

We will be using following tools and services for the post:

  • NodeJS: To build and test a basic Web App.
  • Docker: Docker Container to package and deploy the application.
  • AWS Elastic Container Repository (ECR): AWS ECR to privately host our Docker Container images.
  • AWS AppRunner: AppRunner is going to be our application hosting service.

So let's get started.

AWS Account and Deployment Setup

If you don't already have an AWS account, follow these steps to create one:

  • Go to the AWS Sign-Up page.
  • Ideally, you MUST NOT USE ROOT ACCOUNT for any actual hosting and it should just be a paying account. But for this example any working account should be fine.

Next, if you haven't already installed and configured the AWS Command Line Interface (CLI), follow these steps:

  • Download and install the AWS CLI for your operating system from the official AWS CLI download page.

  • Configure your CLI with AWS Profile and Access Keys with these steps.

Next, to ensure you have the necessary permissions for Amazon ECR and AWS AppRunner, follow these steps:

  • Create a new IAM user or use an existing one. Ensure you have the user's access key and secret key.
  • Attach the following managed policies to the IAM user: IAMFullAccess: Provides full access to IAM service. AmazonEC2ContainerRegistryFullAccess: Provides full access to Amazon ECR. AWSAppRunnerFullAccess: Grants full access to AWS AppRunner.
  • Optionally, you can also set up permissions boundaries if needed to further control what resources the IAM user can access.
  • Ensure that you have the access key ID and secret access key for this IAM user. You'll use these credentials to authenticate AWS CLI requests.

To verify that your permissions are set up correctly:

  • Open a terminal or command prompt.
  • Run the following AWS CLI command to check ECR permissions:
  aws ecr describe-repositories
  • If you receive a response without errors, your IAM user has the necessary permissions for ECR.
  • Run the following AWS CLI command to check AppRunner permissions:
  aws apprunner list-services

If you receive a response without errors, your IAM user has the necessary permissions for AWS AppRunner.

With these steps, you can ensure that you have a working AWS account, AWS CLI, and the appropriate permissions for ECR and AppRunner deployment. Users can now move forward confidently with containerizing their applications and deploying them on AWS using AWS AppRunner.

NodeJS Application

Let's create a basic Node.js application with Express.js that includes a single route to return "Hello, World!" as the response. You can follow these steps:

mkdir my-nodejs-app
cd my-nodejs-app

# Initialize the NodeJs Project
npm init -y

# Install Express module
npm install express

Create a file named app.js (or any other name you prefer) and open it in your code editor. Then, add the following code to create a basic Express.js application with a single "Hello, World!" route:

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => {
  res.send('Hello, World!')
})

app.listen(port, () => {
  console.log(`Server is running on port ${port}`)
})

Save the app.js file and return to your terminal. To start your Node.js application, run:

node app.js

Open a web browser or use a tool like curl to access your "Hello, World!" route:

curl http://localhost:3000

Create Docker Container

In the root directory of your Node.js application (where your app.js is located), create a new file named Dockerfile. You can do this using a text editor or by running the following command in your terminal:

touch Dockerfile

In your Dockerfile, specify the base image that you want to use for your Node.js application. You can use an official Node.js image as the base.

FROM node:16.20.2-alpine3.18

RUN mkdir -p /opt/app

# Set the working directory
WORKDIR /opt/app

# Copy package.json and package-lock.json (if available)
COPY package*.json ./

# Install application dependencies
RUN npm install

# Copy the rest of the application code
COPY . .

# Expose port 3000 for the application
EXPOSE 3000

# Define the command to start the application
CMD ["node", "app.js"]

Save the Dockerfile, and in the same directory where the Dockerfile is located, build the Docker image using the docker build command. Provide a name and tag for your image (e.g., my-node-app:v1):

docker build -t my-node-app:v1 .

This command tells Docker to build an image using the current directory as the build context (indicated by .) and tag it with the name my-node-app and version v1.

You can verify that your Docker image has been created by running:

docker images

You should see your newly created image listed among the images.

Congratulations! You've successfully created a Docker image for your Node.js application. You can now use this image for containerization and deployment on AWS AppRunner or any other container orchestration platform.

Push Docker Container to AWS ECR

To push your newly created Docker image to Amazon Elastic Container Registry (ECR) in preparation for AWS AppRunner deployment, follow these steps:

Authenticate Docker with ECR

Before pushing the image to ECR, you need to authenticate Docker with your AWS account. Run the following command, replacing your-aws-region with the AWS region where you want to create the ECR repository (e.g., us-east-1):

aws ecr get-login-password --region your-aws-region | docker login --username AWS --password-stdin <your-account-id>.dkr.ecr.your-aws-region.amazonaws.com

Replace your-account-id with your AWS account ID, and ensure you specify the correct AWS region.

Create an ECR Repository

If you haven't already created an ECR repository, you can do so using the AWS CLI. Replace your-aws-region with your desired AWS region:

aws ecr create-repository --repository-name my-node-app --image-scanning-configuration scanOnPush=true --region your-aws-region

This command creates an ECR repository named my-node-app. You can change the repository name as needed.

Tag Your Docker Image

Before pushing the image, tag it with the ECR repository URI. Run the following command, replacing your-account-id and your-aws-region with your AWS account ID and region:

docker tag my-node-app:v1 <your-account-id>.dkr.ecr.<your-aws-region>.amazonaws.com/my-node-app:v1

This command tags your Docker image with the ECR repository URI.

Now, you can push the Docker image to ECR:

docker push <your-account-id>.dkr.ecr.<your-aws-region>.amazonaws.com/my-node-app:v1

Replace your-account-id and your-aws-region with your AWS account ID and region, and ensure you use the correct image name and tag.

Verify the Push

After the push is successful, you can verify that your Docker image is available in the ECR repository by running:

aws ecr describe-images --repository-name my-node-app --region your-aws-region

You should see information about your pushed image in the output.

Your Docker image is now stored in Amazon ECR and ready for deployment with AWS AppRunner. You can reference this image when configuring your AppRunner service.

Further Reading

Create AppRunner Web Service

Now that we have the ground work ready, let's host this Docker image to a running AppRunner service.

Create a Service Definition JSON File

Before you can create the AppRunner service, you need to create the IAM Role required for the AppRunner service to access the ECR repository. This is required for the private ECR repository access.

aws iam create-role \
  --role-name AppRunnerECRAccessRole \
  --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Effect": "Allow",
        "Principal": {
          "Service": [
            "build.apprunner.amazonaws.com",
            "tasks.apprunner.amazonaws.com"
          ]
        },
        "Action": "sts:AssumeRole"
      }
    ]
  }'

This command creates an IAM role named AppRunnerECRAccessRole with a trust policy that allows AWS AppRunner to assume this role.

Next, you'll need to attach a managed policy that provides ECR permissions to this role. You can use the following command to attach the AWSAppRunnerServicePolicyForECRAccess policy:

aws iam attach-role-policy \
  --role-name AppRunnerECRAccessRole \
  --policy-arn arn:aws:iam::aws:policy/AWSAppRunnerServicePolicyForECRAccess

Now we have basic blocks ready, we can create a JSON file (e.g., apprunner-service.json) with the following structure to define your AppRunner service. Replace your-account-id and your-aws-region with your AWS account ID and region. You should also specify the ECR image URL you pushed earlier:

{
  "ServiceName": "my-node-app-service",
  "SourceConfiguration": {
    "AuthenticationConfiguration": {
      "AccessRoleArn": "arn:aws:iam::<your-account-id>:role/service-role/AppRunnerECRAccessRole"
    },
    "AutoDeploymentsEnabled": false,
    "ImageRepository": {
      "ImageIdentifier": "<your-account-id>.dkr.ecr.<your-aws-region>.amazonaws.com/my-node-app:v1",
      "ImageConfiguration": {
        "Port": "3000"
      },
      "ImageRepositoryType": "ECR"
    }
  },
  "InstanceConfiguration": {
    "Cpu": "0.5 vCPU",
    "Memory": "1 GB"
  }
}

In this JSON file:

  • ServiceName is the name of your AppRunner service.
  • AccessRoleArn is the IAM role that AppRunner assumes to pull the container image.
  • ImageIdentifier is the ECR image URL.
  • AutoDeploymentsEnabled if true, each repository change starts a deployment.
  • InstanceConfiguration is the runtime configuration of instances (scaling units) of this service.

For more detail please refer to this documentation page.

Create the AppRunner Service

Run the following AWS CLI command to create your AppRunner service using the service definition JSON file:

aws apprunner create-service \
  --cli-input-json file://apprunner-service.json

This command tells AppRunner to create a service using the configuration specified in the JSON file. Ensure that you are in the same directory where your JSON file is located.

Validate the Web Service

You can monitor the progress and verify the status of your AppRunner service by running:

aws apprunner describe-service \
  --service-arn <your-service-arn>

Replace your-service-arn with the actual ARN of your AppRunner service. The command will provide details about the service, including its status and endpoint.

That's it! You've created an AWS AppRunner service using the AWS CLI and a service definition JSON file. Your Node.js application should now be running in the AppRunner service, and you can access it via the provided endpoint.

Further Reading

Next Steps

We've open-sourced our fully working Terraform project on GitHub. This project simplifies the deployment of Docker images from ECR to AWS AppRunner using Terraform.

You can find the complete project, including Terraform configuration files and detailed documentation, on our GitHub repository: Link to GitHub Repo.

Feel free to explore the code, use it as a reference, or even contribute to the project if you find ways to improve it. We hope it serves as a valuable resource for your AWS deployments.

Happy Learning!!

More articles

Rapid Prototyping: Building MVPs with Serverless Architecture

In this blog post, we'll explore how serverless architecture can fast-track the way you build early-version of your application, allowing you to focus on what is important: delivering differentiated value to your users.

Read more

Celebrating a Decade of Innovation: Kubernetes and AWS Lambda

The last ten years have been a transformative period in the world of technology, marked by the emergence and maturation of two groundbreaking technologies: Kubernetes and AWS Lambda. As Kubernetes celebrates its 10th anniversary and AWS Lambda approaches the same milestone in coming months, it's an opportune moment to highlight on their substantial impact on application development and management.

Read more

Tell us about your project

Our office

  • 408-409, SNS Platina
    Opp Shrenik Residecy
    Vesu, Surat, India
    Google Map