Github Actions: how to deploy application to AWS ECS and migrate database with Flyway
Piotr Łagowski
Posted on May 14, 2024
Automatization is extremely important in the context of application development and this is where Github Actions will be great. In this article, we will focus on the necessary instructions to run a workflow that will perform the deployment of our application on AWS ECS and run the database migration using Flyway. An application built using the Spring Framework will be used as an example.
The following instructions necessary for deployment have been developed for the deployment of CRESH, a great platform for validating business ideas.
Adding secrets in Github Repo
The first step will be to add secrets relating to information such as:
- aws user access key
- aws use secret access key
- datasource connection pool
- database username
- database password
Those fields are necessary for the deployment and database migration.
Setting workflow environment variables
At the very beginning, we can define the environment variables that we will use in the workflow area. Below are the necessary variables that we will need for deployment:
env:
ECR_REPOSITORY: <ecr_repo_name>
ECS_SERVICE: <ecs_service_name>
ECS_CLUSTER: <ecs_cluster_name>
CONTAINER_NAME: <container_name>
Action Steps
Setup AWS CLI
Logging into the AWS CLI is essential for the entire workflow. An Access Key and Secret Access Key can be created on the AWS Console for a specific user. Let's assume that for this article, a github_user user has been created to allow you to perform any action using the AWS CLI. Remember that the user you create on AWS should have the appropriate roles.
- name: Setup AWS CLI
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: eu-west-1
Setup Java
A simple step that will be used to set the Java version:
- name: Setup Java
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'
Setup Flyway
Downloading and unpacking a specific version of the flyway. This will enable us to run the migration:
- name: Setup Flyway
run: |
curl -LJO https://repo1.maven.org/maven2/org/flywaydb/flyway-commandline/7.14.0/flyway-commandline-7.14.0-linux-x64.tar.gz
tar xvzf flyway-commandline-7.14.0-linux-x64.tar.gz
sudo mv flyway-7.14.0 /usr/local/flyway
sudo ln -s /usr/local/flyway/flyway /usr/local/bin/flyway
Run Flyway Migration
Start the migration process, in which it is necessary to provide database access secrets and indicate the location of the migration files:
- name: Run Flyway Migration
run: |
/usr/local/flyway/flyway -url=${{ secrets.SPRING_DATASOURCE_URL }} -user=${{ secrets.SPRING_DATASOURCE_USERNAME }} -password=${{ secrets.SPRING_DATASOURCE_PASSWORD }} -locations=filesystem:src/main/resources/database/migrations migrate
Login to Amazon ECR
And here app deployment starts! The AWS Github actions repo comes to your aid here. Logging can be done as follows:
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@62f4f872db3836360b72999f4b87f1ff13310f3a
Build and Push Docker Image to AWS ECR
Building our application and pushing it to the AWS Elastic Container Registry. In order to build the application, you will need a Dockerfile, which will contain the maven command that prepares the jar file. Example Dockefile:
# Use an official Maven image as the build image with Java 17
FROM maven:3.8.4-openjdk-17-slim AS build
# Set the working directory in the container
WORKDIR /app
# Copy the project files into the container
COPY . .
# Build the application
RUN mvn clean install
# Use a lightweight JRE image with Java 17 as the final base image
FROM openjdk:17-jdk-slim
# Set the working directory in the container
WORKDIR /app
# Copy the JAR file from the build image to the runtime image
COPY --from=build /app/target/app_name.jar .
# Specify the command to run the application
CMD ["java", "-jar", "app_name.jar"]
In this step, we can also determine how we want to version the pushed image. In the example below, the timestamp will be used along with the short revision specifier, e.g: 2024.05.13_08-18-37-<git_rev>
- name: Build and Push Docker Image to AWS ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
run: |
VERSION="$(date +'%Y.%m.%d_%H-%M-%S')-$(git rev-parse --short HEAD)"
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$VERSION .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$VERSION
echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$VERSION" >> $GITHUB_OUTPUT
Download task definition
This step will download the existing task-definition file, which contains the necessary information about the container, including the Image ID.
- name: Download task definition
run: |
aws ecs describe-task-definition --task-definition cresh-backend-ecs-task --query taskDefinition > task-definition.json
echo "Docker Image URI: ${{ steps.build-image.outputs.image }}"
replacement_image=${{ steps.build-image.outputs.image }}
json_file="task-definition.json"
jq --arg replacement_image "$replacement_image" '.containerDefinitions[0].image = $replacement_image' "$json_file" > tmp.json && mv tmp.json "$json_file"
Fill the new Image ID in the Amazon ECS task definition
Replacing the image ID in the downloaded task-definition.json file is necessary.
- name: Fill in the new image ID in the Amazon ECS task definition
id: task-def
uses: aws-actions/amazon-ecs-render-task-definition@v1
with:
task-definition: ./task-definition.json
container-name: ${{ env.CONTAINER_NAME }}
image: ${{ steps.build-image.outputs.image }}
Trigger deployment
Finally, the deployment process takes place by replacing the task definition file with the image ID we want to deploy.
- name: Deploy Amazon ECS task definition
uses: aws-actions/amazon-ecs-deploy-task-definition@v1
with:
task-definition: ./task-definition.json
service: ${{ env.ECS_SERVICE }}
cluster: ${{ env.ECS_CLUSTER }}
wait-for-service-stability: true
Summary
The above article provides the necessary instructions needed to create the workflow responsible for deploying the application on AWS ECS and migrating the database using Flyway. What do you think about this? Maybe you know other ways to build such a workflow? Share it in the comments!
Useful links
AWS Github Actions Repo
Information about ECS
Information about ECR
Posted on May 14, 2024
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.
Related
May 14, 2024