DEV Community

A Step-by-Step Guide to Deploying an Application on AWS App Runner with GitHub Action workflow


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 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

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": ""
      "Action": "sts:AssumeRole"
Enter fullscreen mode Exit fullscreen mode

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

Clone the repository

git clone
cd privacy-protect
Enter fullscreen mode Exit fullscreen mode

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
        "style-src": ["self", "unsafe-inline"],
        "upgrade-insecure-requests": true,
        "worker-src": ["none"],
      mode: "auto",
  preprocess: [
      extensions: [".md"],
      layout: {
        blog: "src/routes/blog/post.svelte",
Enter fullscreen mode Exit fullscreen mode

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


COPY . .

RUN npm i
RUN npm run build

FROM nginx:stable-alpine

COPY --from=build /app/build/ /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode

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

  • 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

Next, on the file editor(main.yml), populate the below YAML file

name: Deploy to App Runner - Image based # Name of the workflow
    branches: [ main ] # Trigger workflow on git push to main branch
  workflow_dispatch: # Allow manual invocation of the workflow
    runs-on: ubuntu-latest

      - name: Checkout
        uses: actions/checkout@v2
          persist-credentials: false

      - name: Configure AWS credentials
        id: aws-credentials
        uses: aws-actions/configure-aws-credentials@v1
          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
          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 .
          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        
          service: privacy-protect-app-runner
          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 }}"
Enter fullscreen mode Exit fullscreen mode

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

Top comments (0)