Review: App Runner - Simply containers on AWS!

Andreas Wittig – 15 Jun 2022

How many options are there for deploying containers on AWS? ECS, EKS, Elastic Beanstalk, EC2, and Fargate, to name a few. And there’s another service I’d like to take a closer look at in this review: AWS App Runner. And I promise you already; it’s worth it! App Runner is an underrated option for running containers on AWS.

Review: App Runner - Simply containers on AWS!

AWS announced App Runner in May 2021. I did ignore the service for almost a year. But when writing a new chapter for the 3rd edition of our book Amazon Web Services in Action, I decided to give App Runner a try, and I was astonished by its simplicity and pricing.

What is App Runner?

App Runner is designed to deploy containerized web applications and is built for request-response type apps. I’d classify App Runner as a Platform-as-a-Service offering targeted at developers looking for a simple way to deploy their applications.

How does App Runner work?

How long does it take to deploy a container image with ECS/EKS and Fargate for the first time? I’d say at least a few hours when you are lucky. There are so many resources that you need to provision and configure: a cluster, a service, automated scaling, and a load balancer, to name a few.

In contrast, it takes 5 minutes to deploy a container image with App Runner. Don’t believe me? Just type in the following command into your terminal.

aws apprunner create-service --service-name simple \
--source-configuration \
'{"ImageRepository": {"ImageIdentifier": "public.ecr.aws/s5r5a1t5/simple:latest", "ImageRepositoryType": "ECR_PUBLIC"}}'

The command will output information about the App Runner service. Most importantly, the ServiecUrl and the ServiecArn.

{
"Service":
{
"ServiceName": "simple",
"ServiceId": "f6fc1c6232324461aa96ed11cf1e37cb",
"ServiceArn": "arn:aws:apprunner:us-east-1:xxx:service/simple/...",
"ServiceUrl": "sprruvd23i.us-east-1.awsapprunner.com",
"CreatedAt": "2022-06-15T09:39:22.651000+02:00",
"UpdatedAt": "2022-06-15T09:39:22.651000+02:00",
"Status": "OPERATION_IN_PROGRESS",
"...": "..."
},
"OperationId": "1a1b1e72ca044acdaa74a1c7689227bf"
}

It takes a few minutes until the service is up and running. After that, point your browser to the ServiceUrl, which is https://sprruvd23i.us-east-1.awsapprunner.com in my example.

If you want to check the state of the service deployment, use the following command. Make sure to use ServiceArn from the previous command’s output.

aws apprunner describe-service --service-arn arn:aws:apprunner:us-east-1:...

It could not be simpler to deploy a container image on AWS.

So, App Runner provides a new layer of abstraction. Mainly, I appreciate that the whole complexity is hidden from me as the customer. In contrast to Elastic Beanstalk, App Runner does not provision resources like CloudFormation stacks, EC2 instances, and more in the background.

Also, I want to highlight that App Runner is not automation like the CDK, cfn-modules, or AWS Copilot. Instead, App Runner is an abstraction.

How much does App Runner cost?

An active container instance is charged per vCPU- and GB-hour.

USD/hour
vCPU $0.064
GB $0.007

Note that there are no additional charges for load balancing.

The unique feature of App Runner is that the CPU consumption can be decreased to 0. App Runner will first reduce the number of container instances when no requests are coming in. Next, App Runner will pause the remaining container instances. A paused instance is called provisioned instance by AWS.

For provisioned container instances, you only pay for the memory, not the vCPU.

While a container instance pauses, App Runner will throttle the available CPU capacity to almost 0. But, when a request comes in, the container instance is available to process the request without any significant delay. Think of provisioned instances as hot standby.

Next, let me try to compare costs for App Runner with ECS and Fargate. As always, the calculation is not valid for all scenarios. Therefore, you should do your calculations for your specific case.

For comparison, let’s consider a small web application used by 100 users processing 200 GB of HTTPS traffic. To achieve high availability, we provision two containers with 1 vCPU and 2 GB memory. Also, the web application does not receive requests 50% of the time.

App Runner ECS + Fargate
Active Containers 56.94 72.08
Provisioned Containers 10.22
Load Balancer (ALB) 18.06
Total Costs 67.16 90.11

In this scenario, App Runner is cheaper than ECS + Fargate. However, the calculation looks different if we assume that the application processes requests 24/7.

App Runner ECS + Fargate
Active Containers 113.88 72.08
Provisioned Containers
Load Balancer (ALB) 18.06
Total Costs 113.88 90.11

I would also note that ECS and Fargate are ahead when running more than two containers.

In summary, App Runner is an exciting choice for small web applications with more than 25% idle periods.

Networking

App Runner provides a public endpoint HTTPS endpoint for each service. The service I created as an example at the beginning of this blog post was accessible through https://sprruvd23i.us-east-1.awsapprunner.com. It is also worth noting that by default, an App Runner service is running in a public VPC owned by AWS. So it is possible to connect your container to public endpoints such as S3, DynamoDB, or 3rd party APIs. But it is impossible to connect to an RDS database in your VPC.

By default, App Runner is only able to access public available endpoints

However, AWS recently announced the possibility of connecting your App Runner service with your VPC. It works a lot like VPC connectivity for Lambda. App Runner creates an ENI within every subnet you choose for the service. Please consider that containers require a NAT gateway in case outbound Internet connectivity is needed.

A VPC connection enables the container to access resources within a VPC

Besides that, a VPC endpoint is available for the App Runner service. Using such an endpoint gives you the chance to connect to App Runner without letting traffic flow through the Internet. However, be warned that the App Runner service is still accessible from the Internet.

VPC Endpoints make sure traffic to App Runner does not flow through the Internet

This brings me to a feature that App Runner is missing. There is no way to control incoming traffic. There is no way to restrict access to the public ServiceUrl. The ability to create private App Runner services only accessible from a VPC, for example, by using PrivateLink, would enable many use cases. Also, support for AWS WAF is a must.

How to automate deployments with App Runner?

App Runner supports three different sources.

  1. ECR Private
  2. ECR Public
  3. GitHub

For the first two options, you need to manually push a container image to ECR or in an automated way, for example, by using AWS CodePipeline. App Runner supports deploying the latest image pushed to a private ECR repository.

When connecting App Runner with GitHub, App Runner will take care of setting up a deployment pipeline. All you need to do, is to add a configuration file named apprunner.yaml to your GitHub repository to configure the build process (see Setting App Runner service options using a configuration file). App Runner comes with built-in runtime environments for Python, Node.js, and Java. After my experience with Elastic Beanstalk, I avoid relying on prebuild environments because I want full control over the lifecycle. However, using runtime environments managed by AWS might be an exciting shortcut for some scenarios.

Custom domain names

App Runner assigns a domain name to each service you create by default. sprruvd23i.us-east-1.awsapprunner.com, for example. However, you might want to point your domain name to a service. App Runner supports doing so and even creates the required SSL/TLS certificate.

All you have to do is add two TXT and a CNAME record to your hosted zone. Unfortunately, CloudFormation does not support this feature yet.

What are the limitations of App Runner?

App Runner is built for request-response type apps talking HTTP. Other scenarios like batch processing are not supported yet.

On top of that, App Runner comes with a few limitations. Those seem to be hard limits for now.

  • A container instance comes with a maximum of 2 vCPU and 4 GB memory.
  • A service spins up no more than 25 container instances.
  • A container instance cannot process more than 200 concurrent requests.

What’s missing?

As mentioned before, the most crucial missing feature is the ability to control and restrict inbound traffic.

So far, AWS did not define a Service Level Agreement (SLA) for App Runner. That’s a must before deploying production workloads, in my opinion.

Also, App Runner is only available in the following regions so far.

  • US East (N. Virginia)
  • US East (Ohio)
  • US West (Oregon)
  • Europe (Ireland)
  • Asia Pacific (Tokyo)

The service did not expand to additional regions after launching in 2021, which is a bummer and hopefully not a sign that AWS has lost interest in this service.

Besides that, App Runner is not supported by AWS Config and does not emit CloudWatch events, which is crucial for compliance and monitoring.

Service Maturity Table

Last but not least, I would like to evaluate the service maturity of App Runner.

Criteria Summary Score
Feature Completeness ⚠️ 5
Documentation detailedness 7
Tags (Grouping + Billing) ✅️ 10
CloudFormation + Terraform support ✅️️ 8
Emits CloudWatch Events ⚠️ 0
IAM granularity ✅️️ 10
Integrated with AWS Config ⚠️ 0
Auditing via AWS CloudTrail 10
Available in all commercial regions ⚠️ 3
SLA ⚠️ 0
Compliance (ISO, SOC HIPAA) 10
Total Maturity Score (0-10) ⚠️ 5.7

Our maturity score for App Runner is 5.7 on a scale from 0 to 10. I see great potential in this service. An important feature missing is the ability to restrict access to the public endpoint. Things like a missing SLA or more vCPU and memory capacity per container instance are on the roadmap. I would not recommend App Runner for critical production workloads, but the service is definitely on my watchlist.

Andreas Wittig

Andreas Wittig

I’ve been building on AWS since 2012 together with my brother Michael. We are sharing our insights into all things AWS on cloudonaut and have written the book AWS in Action. Besides that, we’re currently working on bucketAV,HyperEnv for GitHub Actions, and marbot.

Here are the contact options for feedback and questions.