AWS App Runner: Simplify Your Deployment

Introduction

AWS App Runner is a fully managed service that helps developers easily deploy containerized web applications and APIs quickly without worrying about managing complex server infrastructure or Kubernetes clusters. With App Runner, you only need to provide source code or a container image; the service will automatically handle everything from building and deployment to load balancing and traffic encryption.

Advantages

  • Maximum Simplification: No need to configure VPCs, set up Load Balancers, or manage security patches for the operating system. Everything is automated by AWS "from A to Z".
  • Auto Scaling: The system automatically adjusts the number of resources based on actual traffic. When there are no requests, the application can maintain a minimum level to save costs.
  • Seamless CI/CD Integration: App Runner supports direct connection to source code repositories (such as GitHub) or container registries (Amazon ECR). When you push new code, the service will automatically trigger the Automatic Deployment process.
  • Security by Default: Applications run in isolated environments and come with built-in HTTPS (TLS) support. You can also easily manage access permissions through IAM Roles.
  • Reasonable Cost: You only pay for the compute resources (CPU and Memory) that the application actually consumes, helping to optimize the budget for projects or microservices.


Detail

Using AWS CDK, first create the file lib/app-runner-stack.ts

import * as cdk from "aws-cdk-lib"
import * as apprunner from "aws-cdk-lib/aws-apprunner"
import * as iam from "aws-cdk-lib/aws-iam"
import { Construct } from "constructs"

export class AppRunnerStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props)

    const imageIdentifier = process.env.IMAGE || ""
    const bucket = process.env.BUCKET || ""

    const accessRole = new iam.Role(this, "AppRunnerAccessRole", {
      assumedBy: new iam.ServicePrincipal("build.apprunner.amazonaws.com"),
    })

    accessRole.addManagedPolicy(
      iam.ManagedPolicy.fromAwsManagedPolicyName(
        "service-role/AWSAppRunnerServicePolicyForECRAccess",
      ),
    )

    const instanceRole = new iam.Role(this, "AppRunnerInstanceRole", {
      assumedBy: new iam.ServicePrincipal("tasks.apprunner.amazonaws.com"),
    })

    instanceRole.addManagedPolicy(
      iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonS3FullAccess"),
    )

    const appRunnerService = new apprunner.CfnService(
      this,
      "MyAppRunnerService",
      {
        serviceName: "my-typescript-app-service",
        sourceConfiguration: {
          authenticationConfiguration: {
            accessRoleArn: accessRole.roleArn,
          },
          autoDeploymentsEnabled: true,
          imageRepository: {
            imageIdentifier,
            imageRepositoryType: "ECR",
            imageConfiguration: {
              port: "3000",
              runtimeEnvironmentVariables: [
                { name: "REGION", value: this.region },
                { name: "BUCKET", value: bucket },
              ],
            },
          },
        },
        instanceConfiguration: {
          cpu: "1 vCPU",
          memory: "2 GB",
          instanceRoleArn: instanceRole.roleArn,
        },
      },
    )

    new cdk.CfnOutput(this, "AppRunnerURL", {
      value: `https://${appRunnerService.attrServiceUrl}`,
      description: "The URL of the App Runner service",
    })
  }
}

  • accessRole: create a role to allow App Runner to have permission to pull docker images from AWS ECR
  • instanceRole: create a role to allow App Runner to have permission to use S3
  • appRunnerService: create an App Runner with the following main information
    • imageRepository: define information about docker image, port, and environment variables
    • authenticationConfiguration: add the created accessRole information
    • instanceConfiguration: add machine config and the created instanceRole information


Update the file bin/aws-cdk.ts to use the stack just created

#!/usr/bin/env node
import 'dotenv/config';
import * as cdk from "aws-cdk-lib/core"
import { AppRunnerStack } from '../lib/app-runner-stack';

const app = new cdk.App()
new AppRunnerStack(app, "AppRunnerStack")


Result after deployment

 AppRunnerStack
 Deployment time: 314.56s

Outputs:
AppRunnerStack.AppRunnerURL = https://pbwt4phxsb.ap-southeast-1.awsapprunner.com
 Total time: 321.59s


Corresponding resource created on AWS Console


Check using Postman


View logs during operation as follows


Happy coding!

See more articles here.

Comments

Popular posts from this blog

All practice series

Deploying a NodeJS Server on Google Kubernetes Engine

Setting up Kubernetes Dashboard with Kind

Using Kafka with Docker and NodeJS

Monitoring with cAdvisor, Prometheus and Grafana on Docker

Kubernetes Practice Series

Kubernetes Deployment for Zero Downtime

Practicing with Google Cloud Platform - Google Kubernetes Engine to deploy nginx

NodeJS Practice Series

Helm for beginer - Deploy nginx to Google Kubernetes Engine