Skip to content

FSP Deployment Steps

  • Elastic Beans talk, ECS, EC2, RDS
  • image image

EC2 Generate New Key Pair

image - Download .pem file [private key]

Getting Started With Elastic Beanstalk

Create application deploy manually

image image - https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/create_deploy_docker_ecs.html - Dockerrun.aws.json

{
  "AWSEBDockerrunVersion": 2,
  "containerDefinitions": [
    {
      "name": "amigoscode-api",
      "image": "amigoscode/amigoscode-api:latest",
      "essential": true,
      "memory": 512,
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 8080
        }
      ],
      "environment": [
        {
          "name": "SPRING_DATASOURCE_URL",
          "value": "jdbc:postgresql://TODO:5432/customer"
        }
      ]
    }
  ]
}
  • uplaod the Dockerrun.aws.json image
  • follow other steps to create application image image image image

  • Application will be created

  • Resource will be created: EBS, ECS, EC2, RDS
  • As of now DB won't connect becasue we didn't provide the correct host for DB

Change the DB host

  • update DB host into Dockerrun.aws.json
  • upload and deploy updated Dockerrun.aws.json
  • We are getting error database "customer" doesn't exists

Create Customer DB

  • SSH into EC2 machine and using ec2 maching we will connect postgress db and create customer db ssh -i your-private-key.pem ec2-user@instance-public-ip-address
  • ssh "permissions are too open" 🤔

The error message "permissions are too open" occurs when the permissions on your SSH key files are too permissive, meaning they allow read or write access to users who should not have access. This can happen when the file permissions are set to 777 or similar values. To fix this error, you can change the permissions on the SSH key files using the following command in your terminal:

chmod 600 <path-to-ssh-key>

This command sets the permissions on the SSH key file to 600, which means that only the owner of the file has read and write access, and no one else can read or write to the file. If you still get the error message after changing the file permissions, you may also need to check the permissions on the directory that contains the SSH key files. The directory should have permissions set to 700, which means that only the owner can read, write, and access the directory.

chmod 700 <path-to-directory>

After changing the permissions on both the SSH key files and the directory that contains them, try connecting to your SSH server again. The error message should no longer appear.

  • Windows Users

  • To SSH to an EC2 instance on Windows, you can follow these steps:

    Download and install PuTTY, a free and open-source SSH client for Windows. Open PuTTY and enter the public DNS or IP address of your EC2 instance in the "Host Name (or IP address)" field. Under the "Connection" tab, select "SSH" and "Auth". Under "Auth", click "Browse" and select the private key file (.pem) for your EC2 instance. Go back to the "Session" tab, and give your session a name under "Saved Sessions", and click "Save". Click "Open" to start the SSH connection. If this is your first time connecting to the instance, you may see a security alert. Click "Yes" to continue. You should now be connected to your EC2 instance via SSH and can run commands in the terminal.

Alternatively, you can use the Windows Subsystem for Linux (WSL) to SSH to your EC2 instance. WSL provides a Linux-compatible kernel interface to Windows, allowing you to run Linux commands natively on Windows. You can follow these steps:

Install WSL on your Windows machine.
Install an SSH client on your WSL distribution. For example, you can install OpenSSH by running the command sudo apt-get install openssh-client.
Follow the steps above to SSH to your EC2 instance, but use the SSH client installed in your WSL distribution instead of PuTTY.

Let me know if you get stuck - We will connect using mobaxtream and SSH into EC2 - SSH into ec2 for postgresql connection

sudo -i
docker run --rm -it postgres:alpine bash
psql -U amigoscode -h host -d postgres 
or
psql -U amigoscode -h host -d ebdb
create database customer;
docker ps
docker logs -f container-id
  • JD Practice
  • As We need to connect postgress DB we need psql client there are two way for this either we can install psql in EC2 using sudo apt update sudo apt install postgresql-client or we can run docker image of postgress DB and bash into enter into psql
[ec2-user@ip-172-31-14-241 ~]$ sudo -i
[root@ip-172-31-14-241 ~]# docker ps


docker run --rm -it postgres:alpine bash
Unable to find image 'postgres:alpine' locally
alpine: Pulling from library/postgres
08409d417260: Pull complete
6450d4e89514: Pull complete
fb127fe040bf: Pull complete
e07c05a5a317: Pull complete
14a4a63fb0e0: Pull complete
fd170937e677: Pull complete
3597d3193ab4: Pull complete
09ed13dfda56: Pull complete
Digest: sha256:bb2769783686897b370c061b4ad1aac5a819bccec7945d03c3b45a9b077bcea0
Status: Downloaded newer image for postgres:alpine
855e40190f4c:/# psql -U amigoscode -d postgres \
> -h awseb-e-3jehispapr-stack-awsebrdsdatabase-yfimkboo5dgu.creha7e2qzbs.ap-south-1.rds.amazonaws.com
Password for user amigoscode:
psql (15.3)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.

postgres=> \l
                                                    List of databases
   Name    |   Owner    | Encoding |   Collate   |    Ctype    | ICU Locale | Locale Provider |     Access privileges
-----------+------------+----------+-------------+-------------+------------+-----------------+---------------------------
 ebdb      | amigoscode | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            |
 postgres  | amigoscode | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            |
 rdsadmin  | rdsadmin   | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | rdsadmin=CTc/rdsadmin    +
           |            |          |             |             |            |                 | rdstopmgr=Tc/rdsadmin
 template0 | rdsadmin   | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/rdsadmin              +
           |            |          |             |             |            |                 | rdsadmin=CTc/rdsadmin
 template1 | amigoscode | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/amigoscode            +
           |            |          |             |             |            |                 | amigoscode=CTc/amigoscode
(5 rows)

ostgres=> create database customer;
CREATE DATABASE
postgres=> \l
                                                    List of databases
   Name    |   Owner    | Encoding |   Collate   |    Ctype    | ICU Locale | Locale Provider |     Access privileges
-----------+------------+----------+-------------+-------------+------------+-----------------+---------------------------
 customer  | amigoscode | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            |
 ebdb      | amigoscode | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            |
 postgres  | amigoscode | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            |
 rdsadmin  | rdsadmin   | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | rdsadmin=CTc/rdsadmin    +
           |            |          |             |             |            |                 | rdstopmgr=Tc/rdsadmin
 template0 | rdsadmin   | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/rdsadmin              +
           |            |          |             |             |            |                 | rdsadmin=CTc/rdsadmin
 template1 | amigoscode | UTF8     | en_US.UTF-8 | en_US.UTF-8 |            | libc            | =c/amigoscode            +
           |            |          |             |             |            |                 | amigoscode=CTc/amigoscode
(6 rows)

postgres=> ^D\q  (ctrl +d)
855e40190f4c:/#

[root@ip-172-31-14-241 ~]# docker ps
CONTAINER ID   IMAGE                            COMMAND                  CREATED          STATUS                    PORTS                                   NAMES
a735406e0163   jbirla/spring-boot-api:latest    "java -cp @/app/jib-…"   24 seconds ago   Up 23 seconds             0.0.0.0:80->8080/tcp, :::80->8080/tcp   ecs-awseb-Jdbirla-backend-env-3jehispapr-2-jdbirla-api-e48383e4a5a69bd96800
6f472f69f2fa   amazon/amazon-ecs-agent:latest   "/agent"                 36 minutes ago   Up 36 minutes (healthy)                                           ecs-agent
[root@ip-172-31-14-241 ~]#

02ba955c4fa9:/# psql -U amigoscode -d customer -h awseb-e-3jehispapr-stack-awsebrdsdatabase-yfimkboo5dgu.creha7e2qzbs.ap-south-1.rds.amazonaws.com
Password for user amigoscode:
psql (15.3)
SSL connection (protocol: TLSv1.2, cipher: ECDHE-RSA-AES256-GCM-SHA384, compression: off)
Type "help" for help.

customer=> select * from customer;
 id |       name       |              email              | age
----+------------------+---------------------------------+-----
  1 | Kelsie Abernathy | kelsie.abernathy@amigoscode.com |  23
(1 row)

Deploy Automatically using Github Actions

CI

image - create folder .github\workflows in repo - Create backend-ci.yml file - JD

name: CI - Build Backend

on:
  pull_request:
    branches:
      - master
    paths:
      - spring-boot-example/**

jobs:
  build:
    runs-on: ubuntu-latest
    services:
      # Label used to access the service container
      postgres:
        # Docker Hub image
        image: postgres:15.3
        # Provide the password for postgres
        env:
          POSTGRES_USER: amigoscode
          POSTGRES_PASSWORD: password
          POSTGRES_DB: customer
        ports:
          - 5332:5432
          # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    defaults:
      run:
        working-directory: ./spring-boot-example
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'
          cache: 'maven'
      - name : Build and run Unit/Integration Test with Maven
        run: mvn -ntp -B verify
  • Commit and push this workflow into github
  • Create new branch git checkout -b testing-ci-build-workflow
  • Now commit this changes into this new branch and push
  • create pull request from new branch to master branch image
  • The work flow will start automatically

### CD image - create file into workflow backend-cd.yaml - Follow these steps and create Dockerhub access token https://docs.docker.com/docker-hub/access-tokens/ - Then add the following as Secrets in Github. Follow steps here https://docs.github.com/en/actions/security-guides/encrypted-secrets#creating-encrypted-secrets-for-a-repository

    DOCKERHUB_USERNAME = your username
    DOCKERHUB_ACCESS_TOKEN = you access token from step 1
date '+%d.%m.%Y.%H.%M.%S'
  • Creating new users for deployment image
  • Create a group and attache permission to group
  • AWS Permissions
  • It should be enough for your AWS user to have the policies AWSElasticBeanstalkWebTier and AWSElasticBeanstalkManagedUpdatesCustomerRolePolicy attached to be able to deploy your project. image image
  • download access key and secrek key
  • Create github secrets image image
  • Add secrets for EB_APPLICATION_NAME , EB_ENVIRONMENT_NAME and EB_REGION
  • Commit some change in master and push
  • CD job will start automatically

JD Slack Integration

  • JD slack integration CD
name: CD - Deploy Backend

on:
  workflow_dispatch:
  push:
    branches:
      - master
    paths:
      - spring-boot-example/**

jobs:
  build:
    runs-on: ubuntu-latest
    services:
      # Label used to access the service container
      postgres:
        # Docker Hub image
        image: postgres:15.3
        # Provide the password for postgres
        env:
          POSTGRES_USER: amigoscode
          POSTGRES_PASSWORD: password
          POSTGRES_DB: customer
        ports:
          - 5332:5432
          # Set health checks to wait until postgres has started
        options: >-
          --health-cmd pg_isready
          --health-interval 10s
          --health-timeout 5s
          --health-retries 5
    defaults:
      run:
        working-directory: ./spring-boot-example
    steps:
      - uses: actions/checkout@v3
      - name: Slack commit message and sha
        run: >
            curl -X POST -H 'Content-type: application/json'
            --data '{"text":":github: https://github.com/amigoscode/spring-boot-full-stack/commit/${{ github.sha }} - ${{ github.event.head_commit.message }}"}' 
            ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Send Slack Message
        run: >
            curl -X POST -H 'Content-type: application/json'
            --data '{"text":"Deployment started :progress_bar: :fingerscrossed:"}' 
            ${{ secrets.SLACK_WEBHOOK_URL }}
      - uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'
          cache: 'maven'
      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{secrets.DOCKERHUB_USERNAME }}
          password: ${{secrets.DOCKERHUB_ACCESS_TOKEN }}
      - name: Set Build Number
        id: build-number
        run: echo "BUILD_NUMBER=$(date '+%d.%m.%Y.%H.%M.%S')" >> $GITHUB_OUTPUT
      - name: Send Slack Message
        run: >
            curl -X POST -H 'Content-type: application/json' 
            --data '{"text":":maven: Building with Maven"}' 
            ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Build Package Push with Maven
        run: mvn -ntp -B verify -Ddocker.image.tag=${{steps.build-number.outputs.BUILD_NUMBER}} jib:build
      - name: Send Slack Message
        run: >
             curl -X POST -H 'Content-type: application/json' 
             --data '{"text":":docker: Image tag:${{steps.build-number.outputs.BUILD_NUMBER}} pushed to https://hub.docker.com/repository/docker/amigoscode/amigoscode-api"}' 
             ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Update Dockerrun.aws.json api image tag with new build number
        run: |
            echo "Dockerrun.aws.json before updating tag"
            cat Dockerrun.aws.json
            sed -i -E 's_(jbirla/spring-boot-api:)([^"]*)_\1'${{steps.build-number.outputs.BUILD_NUMBER}}'_' Dockerrun.aws.json
            echo "Dockerrun.aws.json after updating tag"
            cat Dockerrun.aws.json
      - name: Send Slack Message
        run: >
            curl -X POST -H 'Content-type: application/json' 
            --data '{"text":":aws: Starting deployment to Elastic Beanstalk"}' 
            ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Deploy to Elastic Bean
        uses: einaregilsson/beanstalk-deploy@v21
        with:
            aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
            aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
            application_name: ${{ secrets.EB_APPLICATION_NAME }}
            environment_name: ${{ secrets.EB_ENVIRONMENT_NAME }}
            version_label: ${{ steps.build-number.outputs.BUILD_NUMBER }}
            version_description: ${{github.SHA}}
            region: ${{ secrets.EB_REGION }}
            deployment_package: spring-boot-example/Dockerrun.aws.json
      - name: Send Slack Message
        run: >
            curl -X POST -H 'Content-type: application/json' 
            --data '{"text":":githubloading: Committing to repo https://github.com/amigoscode/spring-boot-full-stack/"}' 
            ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Commit and Push Dockerrun.aws.json
        run: |
          git config user.name github-actions
          git config user.email github-actions@github.com
          git add Dockerrun.aws.json
          git commit -m "Update Dockerrun.aws.json docker image with new tag ${{ steps.build-number.outputs.BUILD_NUMBER }}"
          git push
        env:
          GITHUB_TOKEN: ${{ secrets.YOUR_ACCESS_TOKEN }}
      - name: Send Slack Message
        run: >
            curl -X POST -H 'Content-type: application/json' 
            --data '{"text":"Deployment and commit completed :github-check-mark: :party_blob: - http://amigoscodeapi-env.eba-ymxutmev.eu-west-1.elasticbeanstalk.com/"}' 
            ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Send Slack Message
        if: always()
        run: >
              curl -X POST -H 'Content-type: application/json' 
              --data '{"text":"Job Status ${{ job.status }}"}' 
              ${{ secrets.SLACK_WEBHOOK_URL }}

Dockerize the React app and run manually in local

image - Here we will use Dockerfile for image generation - Below Docker file insructions : In summary, this Dockerfile sets up a Node.js environment, installs the application's dependencies, copies the application code into the container, sets an environment variable, exposes a port, and specifies the command to run the application when the container starts.

  1. FROM node:19-alpine: This line specifies the base image for the Docker image. In this case, it's using the node:19-alpine image, which is a lightweight image based on Alpine Linux that includes Node.js.

  2. ARG api_base_url: This line declares an argument named api_base_url. Arguments in Dockerfiles are used to provide values that can be passed at build time.

  3. WORKDIR /app: This line sets the working directory within the container to /app. It means that any subsequent commands will be executed relative to this directory.

  4. COPY package*.json .: This line copies the package.json and package-lock.json files from the host machine to the current directory (.) in the container. These files are necessary for installing dependencies.

  5. RUN npm i --silent: This line runs the command npm i --silent in the container. It installs the dependencies specified in the package.json file. The --silent flag is used to suppress verbose output during the installation process.

  6. COPY . .: This line copies all the files and directories from the host machine's current directory to the current directory (.) in the container. It includes the application source code. Please nota that it won't copy .dockerignore file contains

node_modules
Dockerfile
.env
.dockerignore
  1. RUN echo "VITE_API_BASE_URL = ${api_base_url}" > .env: This line creates an .env file in the container and writes a line with the environment variable VITE_API_BASE_URL and its value, which is the value of the api_base_url argument passed during the build process.

  2. EXPOSE 5173: This line exposes port 5173 in the container. It indicates that the container will listen on this port at runtime.

  3. CMD ["npm", "run", "dev"]: This line specifies the default command to run when the container starts. It runs the command npm run dev, which is typically a script defined in the package.json file. This command is responsible for starting the application.

  4. Dockerfile

 FROM node:19-alpine
ARG api_base_url
WORKDIR /app
COPY package*.json .
RUN npm i --silent
COPY . .
RUN echo "VITE_API_BASE_URL = ${api_base_url}" > .env
EXPOSE 5173
CMD ["npm", "run", "dev"]

image

  • execute below commands for generating image
docker build . -t amigoscode/amigoscode-react
docker push amigoscode/amigoscode-react
  • Look inside the container image image image

Create compose file for running all services locally in docker

  • docker-compose.yml
services:
  db:
    container_name: postgres
    image: postgres:15.3
    environment:
      POSTGRES_USER: amigoscode
      POSTGRES_PASSWORD: password
      PGDATA: /data/postgres
    volumes:
      - db:/data/postgres
    ports:
      - "5332:5432"
    networks:
      - db
    restart: unless-stopped
  amigoscode-api:
    container_name: spring-boot-api
    image: jbirla/spring-boot-api:latest
    environment:
      SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/customer
    ports:
      - "8088:8080"
    networks:
      - db
    depends_on:
      - db
    restart: unless-stopped

  amigoscode-react:
      container_name: amigoscode-react
      image: jbirla/jbirla-react:latest
      build:
        context: frontend/react
        args:
          api_base_url: http://localhost:8088
      ports:
          - "3000:5173"
      depends_on:
          - amigoscode-api
      restart: unless-stopped


networks:
  db:
    driver: bridge

volumes:
  db:

Deploy React App into EBS manually

image - Creating Docker app image based on EBS backend host url using pass api_base_ulr arg image - Push this image inot dockerhub - Now up[date Dockerrun.aws.json for react app for deploying manually into EBS - We are udating the react app host port to 80 for http by default port

{
  "AWSEBDockerrunVersion": 2,
  "containerDefinitions": [
    {
      "name": "jbirla-react",
      "image": "jbirla/jbirla-react:30.05.2023.11.43.57",
      "essential": true,
      "memory": 256,
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 5173
        }
      ]
    },
    {
      "name": "jdbirla-api",
      "image": "jbirla/spring-boot-api:02.06.2023.06.36.17",
      "essential": true,
      "memory": 512,
      "portMappings": [
        {
          "hostPort": 8080,
          "containerPort": 8080
        }
      ],
      "environment": [
        {
          "name": "SPRING_DATASOURCE_URL",
          "value": "EBS RDS URL"
        }
      ]
    }
  ]
}
  • upload and deploy latest docker.run.json
  • But the frontend can't access backend as now due to security group permission, we have to add inbound rule for 8080 image image image

Add Create React App in Github workflow

image

  • Create forntend-react-cd.yml file for workflow
name: CD - Deploy React Frontend

on:
  workflow_dispatch:
  push:
   branches:
     - master
   paths:
     - frontend/react/**

jobs:
  deploy:
    ##if: false # put false if you don't want to github action to deploy this as we already configured deployment using amplify else true
    runs-on: ubuntu-latest
    defaults:
      run:
        working-directory: ./frontend/react

    steps:
      - uses: actions/checkout@v3
      - name: Slack commit message and sha
        run: >
          curl -X POST -H 'Content-type: application/json'
          --data '{"text":":github: ${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }} - ${{ github.event.head_commit.message }}"}' 
          ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Send Slack Message
        run: >
          curl -X POST -H 'Content-type: application/json'
          --data '{"text":"Deployment started :progress_bar: :fingerscrossed:"}' 
          ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Set build number
        id: build-number
        run: echo "BUILD_NUMBER=$(date '+%d.%m.%Y.%H.%M.%S')" >> $GITHUB_OUTPUT
      - name: Login to Docker Hub
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_ACCESS_TOKEN }}
      - name: Docker Build and push
        run: |
          chmod +x ../../.ci/build-publish.sh
          USERNAME=jbirla \
          REPO=jbirla-react \
          TAG=${{ steps.build-number.outputs.BUILD_NUMBER }} \
          ../../.ci/build-publish.sh . \
            --build-arg api_base_url=http://amigoscode-fsp-prod.ap-south-1.elasticbeanstalk.com:8080
      - name: Send Slack Message
        run: >
          curl -X POST -H 'Content-type: application/json' 
          --data '{"text":":docker: Image tag:${{steps.build-number.outputs.BUILD_NUMBER}} pushed to https://hub.docker.com/repository/docker/amigoscode/amigoscode-react"}' 
          ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Update Dockerrun.aws.json react image tag with new build number
        run: |
          echo "Dockerrun.aws.json before updating tag"
          cat ../../Dockerrun.aws.json
          sed -i -E 's_(jbirla/jbirla-react:)([^"]*)_\1'${{steps.build-number.outputs.BUILD_NUMBER}}'_' ../../Dockerrun.aws.json
          echo "Dockerrun.aws.json after updating tag"
          cat ../../Dockerrun.aws.json
      - name: Send Slack Message
        run: >
          curl -X POST -H 'Content-type: application/json' 
          --data '{"text":":aws: Starting deployment to Elastic Beanstalk"}' 
          ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Deploy to Elastic Beanstalk
        uses: einaregilsson/beanstalk-deploy@v21
        with:
          aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          application_name: ${{ secrets.EB_APPLICATION_NAME }}
          environment_name: ${{ secrets.EB_ENVIRONMENT_NAME }}
          version_label: ${{ steps.build-number.outputs.BUILD_NUMBER }}
          version_description: ${{ github.SHA }}
          region: ${{ secrets.EB_REGION }}
          deployment_package: Dockerrun.aws.json
          wait_for_environment_recovery: 60
      - name: Send Slack Message
        run: >
          curl -X POST -H 'Content-type: application/json' 
          --data '{"text":":githubloading: Committing to repo https://github.com/amigoscode/spring-boot-full-stack/"}' 
          ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Commit and push Dockerrun.aws.json
        run: |
          git config user.name github-actions
          git config user.email github-actions@github.com
          git add ../../Dockerrun.aws.json
          git commit -m "Update Dockerrun.aws.json docker image with new tag ${{ steps.build-number.outputs.BUILD_NUMBER }}"
          git push
        env:
          GITHUB_TOKEN: ${{ secrets.YOUR_ACCESS_TOKEN }}
      - name: Send Slack Message
        run: >
          curl -X POST -H 'Content-type: application/json' 
          --data '{"text":"Deployment and commit completed :github-check-mark: :party_blob: - http://amigoscodeapi-env.eba-ymxutmev.eu-west-1.elasticbeanstalk.com/"}' 
          ${{ secrets.SLACK_WEBHOOK_URL }}
      - name: Send Slack Message
        if: always()
        run: >
          curl -X POST -H 'Content-type: application/json' 
          --data '{"text":"Job Status ${{ job.status }}"}' 
          ${{ secrets.SLACK_WEBHOOK_URL }}
  • build-publish.sh
: "${USERNAME:?USERNAME not set or empty}"
: "${REPO:?REPO not set or empty}"
: "${TAG:?TAG not set or empty}"

docker buildx create --use

docker buildx build \
    --platform=linux/amd64,linux/arm64 \
    -t "${USERNAME}/${REPO}:${TAG}" \
    -t "${USERNAME}/${REPO}:latest" \
    "${@:2}" \
    --push \
    "$1"

AWS Loadbalancer, Auto scaling, Route 53, SSL

image image - Create new env - Load balancer will be in public subnet image image image

  • aws.json
  • We removed the react container defination becasue will deploy react using aws amplify and chnage tithe port aws well
{
  "AWSEBDockerrunVersion": 2,
  "containerDefinitions": [
{
      "name": "jdbirla-api",
      "image": "jbirla/spring-boot-api:30.05.2023.11.38.43",
      "essential": true,
      "memory": 512,
      "portMappings": [
        {
          "hostPort": 80,
          "containerPort": 8080
        }
      ],
      "environment": [
        {
        "name": "SPRING_DATASOURCE_URL",
          "value": "EBS RDS URL"
        }
      ]
    }
  ]
}
  • upload this file image image image image image
  • Autoscaling triggers image image

  • change RDS host in aws json and redeploy

  • We will face health check issue for solving this issue we have exposed info and health actuator in applicaiton
  • We need to requestpermission into securityfilterchainconfig
  • Update github secrets for new env
  • Github action willl deploy after commit
  • Change health check path image image

  • Route 53 take a domain

  • Create a record
  • image
  • SSL TSL using certificate manager image image
  • create a reacord in certificayte image
  • add listern for load balanser for hhtps image
  • HTTP to HTTPs redirect

AWS Amplify

image image image image

version: 1
applications:
  - frontend:
      phases:
        preBuild:
          commands:
            - nvm use ${VERSION_NODE_17}
            - npm ci
        build:
          commands:
            - nvm use ${VERSION_NODE_17}
            - echo "VITE_API_BASE_URL=$VITE_API_BASE_URL" > .env.production
            - npm run build
      artifacts:
        baseDirectory: /dist
        files:
          - '**/*'
      cache:
        paths:
          - node_modules/**/*
    appRoot: frontend/react

image image image image - custom domain a free SSL certificate image

  • Preview and CICD
  • We can disable React-workflow using a condition if: false image image image

Secrets Manager

image image - We have granted permission to the EC2 role for access secrets manager image image - add dependecy for secrectsmanager

spring:
  datasource:
    url: jdbc-secretsmanager:postgresql://awseb-e-ezjnxfjb44-stack-awsebrdsdatabase-f2ocmocryc5g.celswdmxhcr1.eu-west-1.rds.amazonaws.com:5432/ebdb
    username: test/full-stack/postgres
    driver-class-name: com.amazonaws.secretsmanager.sql.AWSSecretsManagerPostgreSQLDriver