aws

spring boot, github action, docker 를 이용한 배포 자동화 (1)

cheesecrust1008 2024. 3. 20. 01:29

 

캡스톤 디자인을 진행하는 와중에 배포 주기를 짧게 만들어 제품을 쌓아 올리는게 좋을것 같다는 의견이 나와 배포 파이프라인을 미리 구축한 후 진행하게 되었습니다.

 

따라서 초반에 만든 유저 까지의 스프링 서버를 aws ec2에 자동 배포를 하도록 설정 하였습니다.

 

배포 자동화 구축시 고민

배포 자동화 구축을 하는데에 있어 우선 무엇을 사용할지 고민을 하였는데 우선 CI tool 에서 jenkins, github action, travis ci 에서 고민 하였습니다. 

이때 github action을 채택하였는데, 이유는 우선 github에서 제공하기에 다루기에 편리했고 jenkins의 경우 서버를 하나 더 올려야 했기 때문에 금액적으로도 생각을 하여 github action을 채택하였습니다.

 

배포 아키택쳐의 경우에는 두가지를 고민하였습니다. 

 

1.

2.

이에 2번째 방법을 택하였는데, 그 이유는 첫번쨰 방법은 aws 에 종속되기 때문에 혹시 나중에 다른데에 배포하게 되면 다시만들어야 할지도 모른다는 두려움이 있었고,

 

2번째의 경우에 docker 를 사용하면 환경 설정의 문제를 쉽게 해결 할 수 있을거라고 생각했기 때문입니다. 

 

이에 맞춰 github action을 위한 workflow 파일을 작성하였습니다. 

 

배포 과정

 

1. ec2 생성, docker 설치

2. github action 작성

3. 배포 테스팅

 

1의 ec2 생성과 docker 설치는 따로 정리하지 않겠습니다. 

 

하지만 주의할점

1. ec2 생성후 인바운드 규칙에서 8080 포트와 22 포트를 열어주어야 합니다.

    - 8080의 경우는 spring project 에서 사용하고 

    - 22 포트의 경우는 ssh 접속시 22로 접속하기 때문

 

2. github action 작성

name: Code deploy

on:
  pull_request:
    branches: [ "main" ]
    types: [ closed ]

jobs:
  build:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    permissions:
      contents: read

    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: make application-oauth.yml
        run: |
          cd ./src/main/resources
          touch ./application-prod.yml
          echo "${{ secrets.APPLICATION_PROD }}" > ./application-prod.yml

      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5

      - name: Build with Gradle Wrapper
        run: ./gradlew build -x test

      - name: Docker build
        run: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t app .
          docker tag app ${{ secrets.DOCKER_USERNAME }}/maru:latest
          docker push ${{ secrets.DOCKER_USERNAME }}/maru:latest
  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Deploy
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.AWS_HOST }} # EC2 인스턴스 퍼블릭 DNS
          username: ubuntu
          key: ${{ secrets.AWS_ACCESS_SECRET_KEY }} # pem 키
          # 도커 작업
          script: |
            docker pull ${{ secrets.DOCKER_USERNAME }}/maru:latest
            
            CONTAINERS=$(docker ps -q)
            for CONTAINER in $CONTAINERS; do
              docker stop $CONTAINER
            done
            
            docker rm $(docker ps -aq)
            docker run -d --log-driver=syslog -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod ${{ secrets.DOCKER_USERNAME }}/maru:latest
            docker image prune -a -f

 

하나씩 살펴보자

 

1. 

- name: Set up JDK 17
  uses: actions/setup-java@v4
  with:
    java-version: '17'
    distribution: 'temurin'

 

- jdk set up

 

2. 

- name: make application-oauth.yml
  run: |
    cd ./src/main/resources
    touch ./application-prod.yml
    echo "${{ secrets.APPLICATION_PROD }}" > ./application-prod.yml

 

.yml 파일 생성이다. 

이는 프로젝트에 oauth 설정이 들어가있으므로 이를 .gitignore 에서 빼주고 관리하기 때문에 배포시에 추가해서 배포해야한다. 

 

따라서 git secret 에 application-oauth.yml 파일을 넣어 놓고 그 값을 파일을 만들어 넣어서 넘깁니다.

 

3.

- name: Docker build
  run: |
    docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
    docker build -t app .
    docker tag app ${{ secrets.DOCKER_USERNAME }}/maru:latest
    docker push ${{ secrets.DOCKER_USERNAME }}/maru:latest

 

docker hub에 login 한 후 docker image 를 넘깁니다.

 

4. 

- name: Deploy
  uses: appleboy/ssh-action@master
  with:
    host: ${{ secrets.AWS_HOST }} # EC2 인스턴스 퍼블릭 DNS
    username: ubuntu
    key: ${{ secrets.AWS_ACCESS_SECRET_KEY }} # pem 키
    # 도커 작업
    script: |
      docker pull ${{ secrets.DOCKER_USERNAME }}/maru:latest
      
      CONTAINERS=$(docker ps -q)
      for CONTAINER in $CONTAINERS; do
        docker stop $CONTAINER
      done
      
      docker rm $(docker ps -aq)
      docker run -d --log-driver=syslog -p 8080:8080 -e SPRING_PROFILES_ACTIVE=prod ${{ secrets.DOCKER_USERNAME }}/maru:latest
      docker image prune -a -f

 

docker hub에서 이미지를 받은 후 이를 실행하는 스크립트를 실행합니다.

 

위처럼 github action을 작성한 후 main branch에 pull request 를 보낸후 합쳐지면 github action 이 실행되고 배포가 됩니다.

on:
  pull_request:
    branches: [ "main" ]
    types: [ closed ]

 

이 코드가 pull request가 닫혔을떄 실행하는 의미이다. 

 

뒤의 2편에서는 trouble shooting을 다루겠습니다.

 

'aws' 카테고리의 다른 글

AWS RDS 접속  (0) 2024.03.29
spring boot, github action, docker 를 이용한 배포 자동화 (2)  (3) 2024.03.20
aws 리전  (0) 2022.09.18