introduction
This walk through will teach you how to use GitHub actions to deploy your changes to Apprunner. This is especially useful if you will be using the image based deployment. So, rather than manually building the docker image and then push to the repository, before AWS Apprunner will pick it up for deployment.
We will see how with just one push to the GitHub repository, GitHub Actions will build the image, push it to ECR and then run the Apprunner to deploy the application. Also, we will see how to use this GitHub Actions works when using the Source Code method to deploy application in AWS Apprunner.
One interesting thing about working with cloud technology is the ability to automate most of the tasks. And this is just one very good use case.
PREREQUISITE
To follow this tutorial, you will need:
1. A user with permissions to ECR, Apprunner and IAM.
2. The secret and access key of the user. Which you can create from your IAM console
3. An Elastic Container Repository. You can create a quick one here
4. A GitHub repository. Follow the tutorial to create one. You can also clone the repository for this tutorial from here.
Once you have those, let’s get the ball rolling. We will begin by using the Source Code method to deploy to Apprunner using GitHub Actions. However, you can skip it to use image method to deploy the application.
NB: The web application used was developed and listed for free download at startbootstrap.com. Start Bootstrap creates free, open source, MIT license, Bootstrap themes, templates, and code snippets for you to use on any project
connect source code to github actions
We begin by first generating the Connection ARN of the Apprunner service. Here, we only need to create a connection and not configure the Service further because GitHub actions will create it. We will use the ARN of the connection in the GitHub secrets later. There is a previous post showing how to manually create the AWS Apprunner service with Source Code and Docker image.
Click Source Code Repository. Select the Add New.
![Select source code repository for apprunner service settings](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/1-7.png?resize=624%2C240&ssl=1)
In the next window, use the Install Another to install the Apprunner app on your GitHub account. However, if you follow this tutorial, you probably will have one, just click the dropdown on GitHub app to select it.
Click Next. It will take you to the Service configuration window. Close the window and expand the side panel.
![Create a GitHub connections for apprunner](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/2-8.png?resize=781%2C286&ssl=1)
On the side panel, select GitHub connections, and you will see the connection you create in the previous step. Take note of the ARN as you will need it later.
![The GitHub connect ARN](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/3-8.png?resize=955%2C232&ssl=1)
Create IAM ROLE FOR APPRUNNER
Now, we need to create an IAM Role for the Apprunner service. We will use the Custom Trust Policy and select the sts:AssumeRole and sts:TagSession action.
For the Principal, us the ARN of the AWS user with the ECR and Apprunner permissions. You can paste in the JSON below for this policy. Click Next.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Statement1", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::00000000000:user/userName" }, "Action": [ "sts:AssumeRole", "sts:TagSession" ] } ] }
![Custom IAM trust policy for apprunner service](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/6-9.png?resize=761%2C424&ssl=1)
On the next screen, attach the AWSAppRunnerFullAccess and AWSAppRunnerServicePolicyForECRAccess permissions to the role you are creating.
Click Next.
![attach the AWSApprunnerFullAccess and AWSAppRunnerServicePolicyForECRAccess to deploy apprunner application with github](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/7-9.png?resize=1024%2C386&ssl=1)
Add role name and review the policy and permissions attached to this role. Then click Create Role.
![Name the service role for apprunner](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/8-10.png?resize=642%2C243&ssl=1)
To see more detail about the role, click on the role name. Take note of the role ARN. You will need it for the GitHub secrets later.
![ARN service role](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/8a.png?resize=999%2C231&ssl=1)
CREATE IAM POLICY FOR USER
For the role we create above to work properly, it needs to be attached to the user we will use for GitHub secrets authentication. Therefore, click on the user name, under Permissions, Click Add Permissions and select Create Inline Policy
![Create User policy for IAM](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/9-8.png?resize=1024%2C412&ssl=1)
Using the visual editor, select the STS service, add TagSession and AssumeRole, then under the Resources, paste the ARN of the service role you create in the previous step.
![Add the Tagging and AssumeRole Actions for STS policy.](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/9a-1.png?resize=809%2C464&ssl=1)
To use JSON to create the policy, add the json code below
{ "Version": "2012-10-17", "Statement": [ { "Sid": "VisualEditor0", "Effect": "Allow", "Action": [ "sts:AssumeRole", "sts:TagSession" ], "Resource": "arn:aws:iam::0000000000:role/apprunner-role-for-web-app" } ] }
ADD SECRETS TO GITHUB
Once you get that settled, you will need to add some sensitive information to authenticate and authorize GitHub action to access the Apprunner service and deploy the application. Add the Apprunner GitHub connection ARN, AWS Region, Secret and Access key of the user that has the sts policy create earlier, and the service role ARN create earlier too.
GitHub Secrets will encrypt these information and will only decrypt it only during runtime thereby the credentials are protected from unathorize access and use.
In your GitHub account, locate the Organization and the Repository containing the source code. Click the Setting > Secrets and Variables > Actions > New Repository Secret.
![Create new repository secrets to authenticate GitHub action for Apprunner service](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/4-9.png?resize=1024%2C281&ssl=1)
Type AWS_CONNECTION_SOURCE_ARN in the Name* box, and then paste in the Apprunner GitHub connection in the Secret* box. Click on Add Secret.
![Add new GitHub secret](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/5-9.png?resize=627%2C404&ssl=1)
Repeat the step above for AWS_ACCESS_KEY_ID (put the user access key ID), AWS_REGION (add the region you want Github Actions to deploy Apprunner service), AWS_SECRET_ACCESS_KEY (the secret key of the user), and ROLE_ARN (the service role ARN created earlier)
![List of GitHub secrets](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/5a.png?resize=425%2C391&ssl=1)
![](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/10-7.png?resize=856%2C47&ssl=1)
CREATE THE .GITHUB/WORKFLOWS DIRECTORY AND ADD APPRUNNER YAML FILE
The next step and final step to complete the configuration for GitHub Actions to deploy your web application to AWS AppCenter is to add the GitHub Action configuration file.
The configuration file is a yaml file that contains the steps and commands that GitHub will run on our behalf without any further input from us. GutHub Actions will pick up the credentials from the secrets, decode it, temporarily access our AWS account, deploy the application to Apprunner, and then sign out of the account.
Using the GitHub dashboard, click the New Folder button, the create .github/workflows directory. Create an apprunner.yml file in the .github/workflows directory. Then add the yaml configuration to it.
![Create the apprunner yaml file for Github deploy](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/11-6.png?resize=1024%2C89&ssl=1)
Using a command-line, run
sudo mkdir .github && sudo mkdir .github/workflows sudo nano .github/workflows/appcenter.yml
![make .github/workflows directory command line](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/12-4.png?resize=787%2C94&ssl=1)
name: Deploy to App Runner 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 # These permissions are needed to interact with GitHub's OIDC Token endpoint. permissions: id-token: write contents: read steps: - name: Configure AWS credentials uses: aws-actions/configure-aws-credentials@v1-node16 with: # Use GitHub OIDC provider aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} role-to-assume: ${{ secrets.ROLE_ARN }} aws-region: ${{ secrets.AWS_REGION }} role-duration-seconds: 1200 - name: Deploy to App Runner id: deploy-apprunner uses: awslabs/amazon-app-runner-deploy@main env: SERVER_PORT: 3000 with: service: app-runner-git-deploy-service source-connection-arn: ${{ secrets.AWS_CONNECTION_SOURCE_ARN }} repo: https://github.com/${{ github.repository }} branch: ${{ github.ref }} runtime: NODEJS_16 build-command: npm install start-command: npm start port: 3000 region: ${{ secrets.AWS_REGION }} cpu : 1 memory : 2 # Deprecated: wait-for-service-stability: true # The new way to control service stability timeout wait-for-service-stability-seconds: 600 copy-env-vars: | SERVER_PORT # tags: > # { "env": "test" } - name: App Runner URL run: echo "App runner URL ${{ steps.deploy-apprunner.outputs.service-url }}"
IMPORTANT: Take note of the PORT, runtime, and the commands. Modify them to suite your environment.
Once you are done, commit the file to GitHub repository.
git add . git commit -m "commit message" git push
Click on the Actions tab in your GitHub repository to see the job running in GitHub. After a while, you will see the check showing that the Action run successfully.
![](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/13-4.png?resize=976%2C76&ssl=1)
![Success deploy application from Github to Apprunner](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/14-6.png?resize=354%2C362&ssl=1)
CHECK THE APPRUNNER SERVICE TO CONFIRM DEPLOYMENT
Go back into you AWS Console, in the Apprunner service, you will find the newly deployed application from GitHub. Click the service name to reveal the details including the Default domain to access your application.
![apprunner url](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/15-4.png?resize=1024%2C296&ssl=1)
Well done coming so far. Now you will only do one push, and Github Actions will update and deploy your web application in your AWS Apprunner service
USE IMAGE TO DEPLOY TO APPRUNNER USING GITHUB ACTIONS
Let’s use a docker image for the same process of letting GitHub Actions deploy our web application to AWS Apprunner service. Remember to create your AWS Elastic Container Registry to use this method.
CREATE AWS ELASTIC CONTAINER REGISTRY
Once you create the registry and repository on AWS ECR, click on the name and take note of the repository name and the image tag. You will need to add them in the GitHub Actions yaml configuration file.
![aws ecr details](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/16-4.png?resize=550%2C279&ssl=1)
create iam role and attach user policy for docker
You will create the IAM Trusted Entity service role for the Apprunner service and also attach an sts policy to the user just like for the Source Code method above.
So, follow the steps outlined in Create IAM ROLE FOR APPRUNNER, CREATE IAM POLICY FOR USER, and ADD SECRETS TO GITHUB above.
For IAM ROLE FOR APPRUNNER there is a slight change in the principal. Use the "Service": "build.apprunner.amazon.com"
as the principal.
Just like in JSON configuration below. Remember to attach the AWSAppRunnerFullAccess and AWSAppRunnerServicePolicyForECRAccess permissions too.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "Statement1", "Effect": "Allow", "Principal": { "Service": "build.apprunner.amazonaws.com", }, "Action": [ "sts:AssumeRole", "sts:TagSession" ] } ] }
The other two configurations remain the same as what is used in the Source Code Method.
ADD DOCKERFILE TO YOUR PROJECT
Since you will deploy the application from GitHub Actions to Apprunner using image, it is expected we have a Dockerfile in the root of your project source code.
![Dockerfile at root of project directory](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/17a.png?resize=695%2C39&ssl=1)
Create a Dockerfile and paste the configuration there. sudo nano Dockerfile
FROM node:16-alpine AS build WORKDIR /app RUN chmod -R 755 /app COPY package.json /app RUN npm install COPY . . FROM nginx AS runner WORKDIR /usr/share/nginx/html COPY --from=build /app/dist/ /usr/share/nginx/html EXPOSE 80
ADD THE YAML CONFIGURATION FOR IMAGE DEPLOYMENT
Once you added the Dockerfile, the next step is to create the yaml configuration file that GitHub will use to build and push the application to ECR and then deploy it to AWS Apprunner. See the steps on CREATE THE .GITHUB/WORKFLOWS DIRECTORY AND ADD APPRUNNER YAML FILE in the steps above to create the directory and add it to .github/workflow/ directory.
Add the configuration to your dockerapprunner.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: nodejs 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: app-runner-image-deploy-service image: ${{ steps.build-image.outputs.image }} access-role-arn: ${{ secrets.ROLE_ARN }} runtime: NODEJS_12 region: ${{ secrets.AWS_REGION }} cpu : 1 memory : 2 port: 8080 wait-for-service-stability: true - name: App Runner output run: echo "App runner output ${{ steps.deploy-apprunner.outputs.service-id }}"
Add, commit and push your changes to GitHub.
![Git add commit and push the app to github to deploy to apprunner service](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/18-2.png?resize=904%2C246&ssl=1)
The GitHub actions successfully.
![successful deploy of the app to apprunner from github actions](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/19-1.png?resize=438%2C537&ssl=1)
CONFRIM DEPLOYMENT WITH IMAGE
Go to the AWS Apprunner service in your console to confirm that GitHub Actions correctly deploy the web application.
![application url in aws apprunner console](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/20-2.png?resize=549%2C401&ssl=1)
Grab the default domain and paste in your web browser to see the web application deployed with GitHub Actions to AWS Apprunner.
![the application github action deploy to apprunner service.](https://i0.wp.com/oxla.io/wp-content/uploads/2023/04/21-1.png?resize=1024%2C490&ssl=1)
use custom domain
It is not enough to use the default domain as your production URL to your customers, therefore, I recommend you create a CNAME or Alias Name record for the default domain to redirect to your custom domain and secure it with a SSL certificate. With that, your application will carry your business identity on the internet.
troubleshooting apprunner deployment using github actions
- ERROR: ***username is not authorized to perform: sts:TagSession on resource:
***username is not authorized to perform: sts:AssumeRole on resource:
SOLUTION: Add the STS inline policy (sts:AssumeRole and sts:TagSession) to the user that uses the secret and access key connected to GitHub secrets. - ERROR: Error: The requested DurationSeconds exceeds the MaxSessionDuration set for this role
SOLUTION: Add the role-duration-seconds to the YAML file. Or increase the timeout of the max session duration in the yml file to 1200 seconds.
role-duration-seconds: 1200
Leave a Reply