A Step-by-Step Guide to Deploying an Application on AWS App Runner with GitHub Action workflow
Tags: awsapprunner, githubactions, docker
Published: 2023-05-31 17:11:07

###**Privacy-Protect**

Share passwords and sensitive files over email or store them in insecure locations like cloud drives using nothing more than desktop or mobile web browsers like chrome and safari.

No special software. No need to create an account. It's free, open-source, keeps your private data a secret, and leave you alone.

###**App Runner**

AWS App Runner is a fully managed container application service that lets you build, deploy, and run containerized web application and API services without prior infrastructure or container experience.

###**Cons of App Runner**

_Lack of EFS Mount Support:_

The absence of support for mounting the Elastic File System (EFS). Instead, AWS offers an [alternative solution](https://aws.amazon.com/blogs/containers/deploy-python-application-using-aws-app-runner/) with DynamoDB for handling data storage. The lack of EFS mount support might be a challenge for certain use cases:Limited File Storage Flexibility, Potential Performance Impact, Additional Configuration Complexity. However, by leveraging AWS's alternative storage solution, DynamoDB, developers can work around this limitation and continue to build scalable applications.

Go through this Architecture diagram.


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

###᛫ _**Create a IAM role**_

This role is used by AWS App runner to access AWS ECR docker images.

The following are the step-by-step instructions to create a service role and associating `AWSAppRunnerServicePolicyForECRAccess` policy.

_**step 1**_
Create a role named with `app-runner-service-role`

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "build.apprunner.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
```
_**step 2**_

Attach the `AWSAppRunnerServicePolicyForECRAccess` existing policy to the role `app-runner-service-role`.

**Here the steps to deploy Privacy-Protect application in App Runner using GitHub Action**

###᛫ _**Create a AWS ECR private repostiory**_


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

###᛫ _**Clone the repository**_
```
git clone https://github.com/r4jeshwar/privacy-protect.git
cd privacy-protect
```

###᛫ _**Migrate from Server deployment(Vercel-@sveltejs/adapter-vercel) to static site generator(@sveltejs/adapter-static)**_

First, Install `npm i -D @sveltejs/adapter-static`

Go to the `svelte.config.js` file delete the existing content and paste the below content in `svelte.config.js` file.

```
import adapter from "@sveltejs/adapter-static";
import { vitePreprocess } from "@sveltejs/kit/vite";
import { mdsvex } from "mdsvex";
import { resolve } from "path";

/** @type {import('@sveltejs/kit').Config} */
export default {
  extensions: [".md", ".svelte"],
  kit: {
    adapter: adapter({
       pages: 'build',
       assets: 'build',
      fallback: null,
      precompress: false,
      strict: true
    }),
    alias: {
      $components: resolve("src/components"),
      $icons: resolve("src/assets/icons"),
    },
    csp: {
      directives: {
        "base-uri": ["none"],
        "default-src": ["self"],
        "frame-ancestors": ["none"],
        "img-src": ["self", "data:"],
        "object-src": ["none"],
        // See https://github.com/sveltejs/svelte/issues/6662
        "style-src": ["self", "unsafe-inline"],
        "upgrade-insecure-requests": true,
        "worker-src": ["none"],
      },
      mode: "auto",
    },
  },
  preprocess: [
    mdsvex({
      extensions: [".md"],
      layout: {
        blog: "src/routes/blog/post.svelte",
      },
    }),
    vitePreprocess(),
  ],
};
```
_Note: This changes is to deploy in various infrastructure and to dockerize in small size. If you need to deploy in vercel ignore this._

_**Why we need to switch out the adapter from vercel to static ?**_

Adapter-Static allows deploying Vite.js application to various static hosting providers.It also simplifies the deployment process by eliminating the need for serverless infrastructure and configuration specific to Vercel. 

Overall, migrating from Adapter-Vercel to Adapter-Static empowers you with greater flexibility, simplicity.

###᛫ _**Dockerfile for privacy-protect to deploy in App Runner**_

```
FROM node:18-alpine as build

WORKDIR /app

COPY . .

RUN npm i
RUN npm run build


FROM nginx:stable-alpine

COPY --from=build /app/build/ /usr/share/nginx/html
```
Push the changes to your repository to be picked up by the GH workflow we'll be setting up next


###᛫ _**Configure the GitHub Action secrets**_

Go to your project repository, Go to `settings` in the security section click the `Secrets and variables` drop down and click `Actions`. Configure the variables.


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

- `AWS_ACCESS_KEY_ID` is your AWS user access key.

- `AWS_SECRET_ACCESS_KEY` is your AWS user secret key.

- `AWS_REGION` is the region of AWS services where you creating.

- `ROLE_ARN` is your IAM role ARN which you have created before which you named `app-runner-service-role`

###᛫ _**Configure the new workflow in GitHub Action**_

Click `set up a workflow by yourself`

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

Next, on the file editor(main.yml), populate the below YAML file
```
name: Deploy to App Runner - Image based # Name of the workflow
on:
  push:
    branches: [ main ] # Trigger workflow on git push to main branch
  workflow_dispatch: # Allow manual invocation of the workflow
jobs:  
  deploy:
    runs-on: ubuntu-latest
    
    steps:      
      - name: Checkout
        uses: actions/checkout@v2
        with:
          persist-credentials: false
          
      - name: Configure AWS credentials
        id: aws-credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_REGION }}

      - name: Login to Amazon ECR
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v1        

      - name: Build, tag, and push image to Amazon ECR
        id: build-image
        env:
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          ECR_REPOSITORY: privacy-protect
          IMAGE_TAG: ${{ github.sha }}
        run: |
          docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
          docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
          echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"  
          
      - name: Deploy to App Runner
        id: deploy-apprunner
        uses: awslabs/amazon-app-runner-deploy@main        
        with:
          service: privacy-protect-app-runner
          image: ${{ steps.build-image.outputs.image }}          
          access-role-arn: ${{ secrets.ROLE_ARN }}       
          region: ${{ secrets.AWS_REGION }}
          cpu : 1
          memory : 2
          port: 80
          wait-for-service-stability: true
      
      - name: App Runner ID
        run: echo "App runner ID ${{ steps.deploy-apprunner.outputs.service-id }}"
```
###᛫ _**GitHub Action runs successfully after a few minutes**_

You can see the AWS App Runner dashboard your application is up and running successfully.



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