Deploying a Laravel App on AWS App Runner
Tags: laravel, aws, docker, k8s
Published: 2023-01-17 10:21:22

---
title: Deploying a Laravel App on AWS App Runner
published: true
description: 
tags: laravel, aws, docker, k8s
# cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7cgvxlcvkge6j29lcwpq.png
# Use a ratio of 100:42 for best results.
# published_at: 202-11-30 22:13 +0000
---


Deploying a containerized app gets easier everyday as cloud providers release new products. One of such products by AWS is AWS App Runner.

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.

Ever want to just deploy an app without the Kubernetes or complex networking overhead? Or have a couple of services to maintain without alot of configuration? - Try AWS App Runner. Read more [Here](https://aws.amazon.com/apprunner)

### Following this tutorial
For ease of following this tutorial, I have created a default `Laravel` app with all the files referenced in this post. Click [Here](https://github.com/massivebrains/laravel-aws-apprunner) to view the public github repo.

### Dockerizing Laravel
Let's start with a Docker file. In this post, I will be using `php7.4`. In the root of your Laravel application, create a `Dockerfile`. See example [Here](https://github.com/massivebrains/laravel-aws-apprunner/blob/master/Dockerfile)

### Other deployment related files
If you look at the contents of the Dockerfile above, `/app/deploy` folder was referenced. This folder contains files for nginx, superiviser and a `run` script that would start the laravel app. [Click here](https://github.com/massivebrains/laravel-aws-apprunner/tree/master/deploy) to copy the contents of this folder to your local Laravel app.

### Build and run your image
To ensure your docker image works locally, run `docker build .` to build your image.

When this builds successfully, you can find your image when you execute `docker images` on your cli.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/go9ys8qcbw3n00w7slj4.png)

Since the docker image exposes port `80`, you can test your image by running:

```docker run -p 8000:80 <image id>``` 

(Ensure you pass valid database credentials or modify .env.example with reachable database credentials)


### Setting up AWS App Runner
Now let's setup AWS App Runner. First of, AWS App Runner has an automatic deployment option, what this means is that, once our docker repository changes, our app automatically deploys. This is one of the simplicity that makes this product easy to use.


### AWS Elastic Container Registry
Since we want to automate the entire process, we would be pushing our image automatically to AWS Elastic Container Registry.

Login to AWS and search for `Elastic Container Registry`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8dxqymwabqops2sy9tim.png)

If you don't have an existing repository for your app, go ahead and create one. I will be creating a repository called `laravel-aws-app-runner`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6o0y1e1ravwlsof14l36.png)

Take note of the URI, we would need it later.

#### Setting up Github Actions
For us to automatically build our images and push to ECR from Github we would be using [Github Actions](https://github.com/features/actions)

Let's start by adding 2 secrets to our Github repo, `AWS_ACCESS_KEY_ID` and `AWS_SECRET_ACCESS_KEY`. These two values would be used by the actions to access AWS. Ensure you set your AWS credentials that has access to the ECR you just created.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zivgicgab2b36ntfr0ma.png)

In your repo, create a Github actions file `/.github/production.yml` just like [this](https://github.com/massivebrains/laravel-aws-apprunner/blob/master/.github/workflows/production.yml)

Take note of the `ECR_REPOSITORY` key, update the value to the name of the repository you created in ECR.

The Github actions tries to checkout the code, login to AWS, build the image and then push it up to the ECR repository.

Note that it also runs only when there is changes to master, feel free to change this configuration if you want a different branch.

You may push an empty commit to master to trigger your actions if it has not already been triggered. On your Actions tab, you should see a successful Github Actions run.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hl4lgimo6tz86dmsrthr.png)


### Creating an AWS App Runner Service
Finally, we have our image pushed to ECR, a Github action to update the image when we merge to master, we can now create a service on App runner that would automatically listen for changes on ECR and update our App.

On AWS, search for AWS App Runner and click on `Create Service`


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f0v9y2nsm05nkcmp3mtn.png)

If AWS App runner is not available in your preferred region, you may consider using a different region where this product is available.

In the `Source and Deployment` Select `Container Registry` and `Amazon ECR` as the provider. Choose the correct repository in the list and the default tag is `latest` according to our Github actions configuration. 


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/09m18v01qe342xhnglt6.png)

As you can see, it is actually possible to reference a different docker repository outside of AWS ECR.

In Deployment settings, select `Automatic` - This is very important, with automatic, when our ECR image changes, the service will automatically be deployed.

If you already have a service role, feel free to choose one of them, other than that you can simply select `Create a new service role`

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tofiig0au84c02jbu4am.png)

Then click on Next.

On the Service settings, this is where we configure Environment variables, the CPU & RAM of the service, and the port exposed by the Docker image.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/k1jtmacrwpm7fpdk96p6.png)

Add all the env and values for your service, set the port to `80` (Except the Docker file port has been updated). Feel free to change the virtual CPU to 2vCPU, for now i'll leave the default.

I generally leave the `Auto Scaling`, `Health Check` `Security`, `Observability` and `Tags` tabs with the default configuration from AWS, but if you are an experienced AWS user and want custom configuration, feel free to modify these tabs to what you want.

For networking, which is quite important for your service to have access to other resources on your VPC. Your incoming network traffic has to stay as `public endpoint` if not your service would not be available on the internet.

If you would like to change your outgoing access, feel free to do that, but for now, i'll leave both with the defaults.

One major reason you may change your outgoing access later is because of your database connections as it would most likely be behind a security group in a custom VPC.

Now that we have all the configurations (mostly all defaults 🙈) We can now go ahead to create & Deploy the service.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4ne0mnne4e247uk0e2ew.png)

After successful deployment, you should have a running service as displayed above.

### Handling failed deployment
Just incase your deployment fails, you can view the application logs in Cloudwatch to know what the issue is 
![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/v17ma04vungfj8ta26mw.png)

Once you see the log and figure out what the issue is from the Image, you can delete the failed service and create a new service.

### Automatic deployments
Now that we have a running service, every time you push to your master branch and Github actions run, the ECR image would be updated and AWS App runner will automatically deploy the app.

### Custom Domains
Obviously you may want to add Custom domain to your service and not use the default AWS domain. You can do that on the Custom Domains tab. Simply follow the instructions.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yubnapx4cdngs8cvlcl4.png)

### Conclusion
Once you get a hang of creating services and setting up Github actions to update the ECR Images, you can pretty much do anything you like such as even having Staging environments.

AWS App runner is quite straightforward and eliminates setting up your own ServerLess environment from ground up. And since our applications are containerized, you can pretty much switch to another platform in the future if you have too.