How to deploy your next FastAPI app on AWS with AppRunner in less than 5 minutes?
Tags: aws, apprunner, python, fastapi
Published: 2023-04-20 18:44:29

In May 2021, AWS announced the General Availability of its service `AWS App Runner`, described as "_the simplest way to build and run a containerized web application in AWS_". At that time, the service was extremely limited (no support for VPC connectivity) and only a few runtimes were supported.

02 years later, the service has evolved and now supports many interesting features.

In this article, you will see what AppRunner is and how it can help you to deploy FastAPI web apps in a couple of minutes.


### Why AppRunner?
When it comes to deploying a web application on AWS, you have several ways, depending on the application’s requirements, team capabilities, budget and various constraints.

However, regardless of the deployment method chosen, there are some mandatory configurations that need to be in place to ensure the application is highly available.

This typically falls under the responsibility of the `operations team (ops)`, who must set up:

- Load balancing
- Target groups
- Scaling
- Security groups
- Domains
- Certificates
- Observability (monitoring, logging, metrics)
- And more.

Despite this complexity, developers simply want to deploy their application and focus on its development. This observation led AWS to offer a fully managed service to simplify the deployment of applications: **AppRunner**.


### Definition
The official page states _“AWS App Runner is a fully managed container application service that lets you build, deploy, and run containerized web applications and API services without prior infrastructure or container experience”_.

At this moment, you are probably wondering if AppRunner is a:

- Platform as a Service (PaaS)?
- Container as a Service (CaaS)?
- New Serverless Service?
- Managed Service
- or All at once?

Let’s try to understand how the service operates. This will probably help us to respond to the question.


### Modes of Operation
Under the hood, AppRunner creates an ECS cluster and uses [Fargate](https://docs.aws.amazon.com/AmazonECS/latest/userguide/what-is-fargate.html) to effortlessly run your containers, saving you time and effort.

While some may argue that sacrificing granularity is a compromise, the benefits of simplicity and speed are undeniable. With built-in `continuous integration` and integration with CloudWatch for logs and monitoring, **App Runner** eliminates the need for additional third-party services.

Streamline your container management with App Runner and focus on what matters most – **your business**!

![AppRunner Architecture](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/z9d6z2m0kwlta5y03idc.jpg)

When it comes to configuring App Runner, you have two options to choose from – **manual** and **automatic**.

The `manual mode` is ideal for those who prefer to have more control over the configuration process. With this mode, you can configure your application's environment variables, networking, and other settings using the AWS Management Console or CLI.

On the other hand, the `automatic mode` is interesting for those who prefer a more hands-off approach. With this mode, App Runner automatically loads your application configuration from its source code allowing you to focus on other aspects of your project.

In addition to the modes of configuration, App Runner offers two modes of operation – **Container Mode** and **Build Mode**.

`Container Mode` is recommended for running pre-built containers from a container registry, such as Amazon ECR or Docker Hub. With this mode, you can quickly deploy and scale your application without worrying about the underlying infrastructure.

The `Build Mode` is perfect for building and deploying applications from source code. With this mode, App Runner automatically builds your application from your source code, dependencies, and build instructions, making it easy to deploy and manage your applications.

Whether you prefer to use pre-built containers or build your applications from source code, App Runner offers flexible options to meet your needs.


### App Runner in Action
Now that we have a complete overview of the service, let’s practice using `build` and `automatic` modes.

In a [previous article](https://dev.to/abdelino17/package-your-fastapi-application-with-distroless-docker-images-16k9), I set up a basic python api with FastAPI Framework. I will reuse the code for the rest of this article.

```python
import fastapi, uvicorn
from starlette.requests import Request
import prometheus_client
import os

api = fastapi.FastAPI()

...

if __name__ == "__main__":
    print("Starting webserver...")
    uvicorn.run(
        api,
        host="0.0.0.0",
        port=int(os.getenv("PORT", 8080)),
        debug=os.getenv("DEBUG", False),
        log_level=os.getenv('LOG_LEVEL', "info"),
        proxy_headers=True
    )
```

The AWS Console provides all you need for the deployment. You should see a page like this:

![AppRunner Getting Started](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/38tz3p2d8vsi3aw42dho.png)

Click on _Create an App Runner Service_ button, you have now this:

![AppRunner Creation Page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/p7j8yuffhgjmvtbb0x2e.png)

For the while, **AppRunner** supports only `Github as Source code repository`. So, click on the _Add new_ button to add a new repository.

A new window is opened. Set a name for your connection and click on the Install button.

![AppRunner Connection](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/afo64q6dtfvlhqbv24gg.png)

Indeed, AWS will install the `Github connect` and you will be able to select the repository and the branch you want to deploy. The connection could be reused for all your other services.

Don’t forget to check the repositories the AWS Connector has access to.

![AppRunner Integration](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zt7lss4u48eaoyr2xgq4.png)

At this step, you should have all your fields filled in as follows:

![AppRunner Service](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7jrfuopyea28xrfdwbe6.png)

On the _Next Page_, it’s time to configure your build settings.

Add the configuration file `apprunner.yaml` at the root of your project with the following content:

```yaml
version: 1.0 # version of the specification
runtime: python3 # runtime to use
build:
  commands:
    build:
      - pip install -r requirements.txt # install dependencies

  env: # define environment variables
    - name: PORT
      value: '8080'

run:
  command: python app.py # command to run fastapi
  network:
    port: 8080 # port AppRunner will expose
```

On the _Next Page,_ you can enable _various options_ to make stand out your service:

- **Auto Scaling**: Define the scaling behaviour for you service by setting the number of requests, concurrency, [etc.](https://docs.aws.amazon.com/apprunner/latest/dg/manage-autoscaling.html?icmpid=docs_apprunner_console)

- **Health Check**: Configure the health checks that the load balancer performs on your App Runner service instances (the path to request, the number of consecutive health check failures, etc.). The health check path of our service is `/ping`.

- **Security**: A custom instance role to call AWS services

- **Networking**: Public, private endpoints, custom VPC, etc.

- **Observability**: Tracing with [AWS X-Ray.](https://docs.aws.amazon.com/xray/latest/devguide/aws-xray.html)

The last page is the _Review and create Page_. You will be able check your settings one last time before the deployment. If everything is good, click on the *Create and deploy*  button, which will trigger the deployment process:

![AppRunner Deployment](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ui5cz1ucril0lvaw3x69.png)

It will take a couple of minutes for AppRunner to deploy your application. After that, the status turns into **Running** and a message indicates that your application is running.

![AppRunner Running](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b06aoez72h1h7ekuinph.png)

**Congratulations, You nailed it!**


### Testing the continuous deployment
In automatic mode, every push on your repository will trigger the deployment of your service. Let’s test it!

Open the [app.py](https://github.com/abdelino17/python-api/blob/main/app.py) file and add the following code:

```python
...

@api.get('/hello')
def hello(request: Request):
    REQUESTS.labels(endpoint='/hello').inc()
    return "Hello World!"
...
```

Commit your changes and push them.

If you go back to your AWS Console, you should see the status of your service status transitioning from **running** to **Operation in progress**. This indicates the detection of changes and a redeployment in progress.

![AppRunner CICD](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/plqx7jbhn9lltf0eer9n.png)

A few minutes later, your application should be running again and the new endpoint should now be available:

![AppRunner Hello](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2huh5uagx56wfgxmdl2g.png)


**Awesome! our automatic deployment is fully operational.**

If you prefer command line, feel free to check out the [AWS CLI Docs](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/apprunner/index.html) page.


### Conclusion
To sum up, AWS AppRunner is definitely **THE** service you should consider to deploy your next FastAPI service quickly and efficiently. It is developer-centric and easy to set up.

A lot of effort of integration with the AWS Ecosystem has been done these last months and the service is now production-ready for most of use cases. Just enjoy!

That’s all for today!

If you have any questions or experience with AppRunner, do not hesitate to share them in the comments section.

I’d love to hear from you 😉.