[Github Action] Github Action을 사용하여 Spring Boot + Docker(Docker Compose) + AWS EC2 프로젝트 배포하기

이전 포스팅에서 나의 개인 프로젝트에 변화를 주고싶었다고 언급했다.  
저번에 Spring Boot 프로젝트를 Docker를 통해 배포를 진행했다. 그러다가 문득 든생각이 있다. 
자주 들어왔던 Git Hub Action을 통해 자동으로 소스가 배포되면서 Docker 이미지를 생성하고, AWS EC2 인스턴스에 자동으로 반영해보고 싶다는 생각이 들었다.

막연하게 그저 소스 Push 하면 적용되는거겠지 라는 생각을 했지만, 막상 해본적도 없기에 진행해보고자 한다.


먼저 진행할 프로젝트는 간단하게 아래로 구성한채 진행한다. 

  • Java 17 | Spring Boot
  • Docker
  • AWS EC2
  • Github Action

일단 Docker 까지는 로컬에서 배포가 가능해야하기 때문에 이전 포스팅을 참고하기 바란다.

 

[Docker] Spring Boot로 Docker Image 배포하기

시작하기에 앞서 이번에 맨날 사용하던 Spring Boot, JPA , Spring Security 말고 무언가 기술적이나 재미를 통해 변화를 주고싶었다. 그래서 이번 개인프로젝트에서는 Dokcer를 활용하여 AWS에 배포하는 것

frenchruin.tistory.com


WorkFlow 설정

먼저 Github action을 사용하기 위해서는 WorkFlow 관련 yml 파일을 생성해야 한다.
파일을 생성하면 깃헙에서는 Github action 을 사용하는 Repository라는것을 인식한다.
필자는 아래와 같은 구조로 테스트를위해 생성했다.

.github/workflows/docker-image.yml

참고로 repository의 action탭으로 들어가게 되면 프로젝트 특징별로 깃헙에서 템플릿을 제공한다.
필자는 Docker관련 템플릿을 사용했다.

repository > actions


docker-image.yml 파일 설정

파일을 생성했다면 내가 Github Action을 이렇게 사용하겠다고 작성해주자.

docker-image.yml

소스코드는 아래를 펼치자

더보기

소스코드 

name: Spring + Docker + AWS EC2

on:
  push:
    branches: [ "master" ]

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3
      - name: SetUp Java 17 😊
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Grant execute permission for gradlew 👍
        run: chmod +x gradlew

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

      - name: Docker Image Build and Push to Docker Hub 👍
        run: |
          docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
          docker build -t app .
          docker tag app ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}
          docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}

      - name: Deploy to AWS EC2 👍
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.AWS_HOST }}
          username: ubuntu
          key: ${{ secrets.AWS_SECRET_KEY }}
          port: ${{ secrets.AWS_PORT }}
          script: |
            sudo docker rm -f $(docker ps -qa)
            sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}
            docker-compose up -d
            docker image prune -f


하나씩 살펴보자


name: Spring + Docker + AWS EC2

on:
  push:
    branches: [ "master" ]
GitHub Action 이름을 name을 통해 설정한후, GitHub Action이 어떠한 상황일때 작동할 것인지, on을 통해 설정해준다.
필자는 단순히 "master" 브랜치에 소스가 커밋이 되면 작동하게 설정했다.

permissions:
  contents: read
단순하게 읽기 권한만 부여한다고 생각하면 될것같다. 자세한 내용은 아래를 참고하자
 

작업에 권한 할당 - GitHub Docs

GITHUB_TOKEN에 부여된 기본 사용 권한을 수정합니다.

docs.github.com


jobs:
  build:
    runs-on: ubuntu-latest
이러한 Github Action 동작을 ubuntu 환경에서 진행하겠다는 내용이다.

steps:
  - uses: actions/checkout@v3
  - name: SetUp Java 17 😊
    uses: actions/setup-java@v3
    with:
      java-version: '17'
      distribution: 'temurin'

  - name: Grant execute permission for gradlew 👍
    run: chmod +x gradlew

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

  - name: Docker Image Build and Push to Docker Hub 👍
    run: |
      docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
      docker build -t app .
      docker tag app ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}
      docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}

  - name: Deploy to AWS EC2 👍
    uses: appleboy/ssh-action@v1.0.3
    with:
      host: ${{ secrets.AWS_HOST }}
      username: ubuntu
      key: ${{ secrets.AWS_SECRET_KEY }}
      port: ${{ secrets.AWS_PORT }}
      script: |
        sudo docker rm -f $(docker ps -qa)
        sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}
        docker-compose up -d
        docker image prune -f
아마 여기가 제일 중요한 포인트가 아닐까 싶다.
Steps 안에 순서대로 실행할 내용을 포함한다.
순서가 매우 중요하다. 가끔 순서가 뒤바뀌어 에러를 발생시킬수있다.

- uses: actions/checkout@v3
우리가 git repository에 있는 소스들을 체크아웃을 해주어야 github action에서 수행할 명분이 생긴다고 생각하면 되는데
이전에는 우리가 일일이 아래의 일들을 모두 처리해줘야했지만, 해당 액션으로 간편하게 수행할 수 있다고 생각하면 된다.

actions/checkout@v3 Log


- name: SetUp Java 17 😊
  uses: actions/setup-java@v3
  with:
    java-version: '17'
    distribution: 'temurin'
먼저 Java를 구성해줘야하는데, 필자는 Java 17을 사용하기 때문에 위와 같은 action을 통해서 설정해주었다.

- name: Grant execute permission for gradlew 👍
  run: chmod +x gradlew

- name: Build with Gradle 👍
  run: ./gradlew build -x test
이제 Gradle을 통해서 소스들을 build를 해주어야하는데, Github Action 환경에서 다음과 같은 명령어들을 통해서 Gradle Build를 수행할 수 있는 권한을 부여하고 실제로 Build를 실행한다고 생각하면 된다.

Gradle Build 시 Test는 통과한다는 의미도 작성해주었다. [ ./gradlew build -x test ] 

- name: Docker Image Build and Push to Docker Hub 👍
  run: |
    docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
    docker build -t app .
    docker tag app ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}
    docker push ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}
그 다음에는 우리가 Docker 이미지를 생성하고 Docker Hub에 Push를 해줘야하는데, 위와 같은 명령어로 수행한다.
  • Docker 에 Login
  • Docker 이미지 생성
  • Docker Hub Push

위와 같은 순서로 진행한다.

참고로, ${{ secrets.DOCKER_USERNAME }} 같은 것들은 무엇이냐 말한다면, 우리가 민감한 정보들을 기존에는 application.yml 이나, env를 따로 설정해서 넣어줬을 것이다. 하지만 Github Action에서는 민감한 정보들을 관리해주는 서비스가 존재한다.

아래를 확인해보자

repository > settings > Secrets and variables > Actions > Repository Secrets

위와 같이 New repository Secret 을 통해서 사용할 이름과 값들을 설정해주면 소스에서 보다시피 ${{ secrets.이름 }} 과 같이 사용할 수 있다.

필자는 참고로 아래와 같이 설정했다.

  • AWS_HOST => AWS 접근할 IP
  • AWS_SECRET_KEY => 인스턴스를 생성할 당시 만들었던 ***.pem 파일이다. 이 파일은 메모장으로 열면 내용이 들어있는데, 그 값들을 설정해주면된다.
  • DOCKER_IMAGE => Docker Image 이름
  • DOCKER_PASSWORD => Docker 사용자 비밀번호
  • DOCKER_USERNAME => Docker 사용자 ID

이외의 정보들은 테스트를 위해서 포함했다.


- name: Deploy to AWS EC2 👍
  uses: appleboy/ssh-action@v1.0.3
  with:
    host: ${{ secrets.AWS_HOST }}
    username: ubuntu
    key: ${{ secrets.AWS_SECRET_KEY }}
    port: ${{ secrets.AWS_PORT }}
    script: |
      sudo docker rm -f $(docker ps -qa)
      sudo docker pull ${{ secrets.DOCKER_USERNAME }}/${{ secrets.DOCKER_IMAGE }}
      docker-compose up -d
      docker image prune -f
그다음 AWS EC2 환경에 SSH로 접속 한 후, Docker 이미지를 Pull 받고, Docker-Compose를 통해 Container를 실행하고, 실행하지 않는 이미지를 삭제시켰다.

AWS EC2의 우분투 인스턴스는 기본적으로 username이 ubuntu 이다.
필자는 docker-compose 는 여러개의 Docker 이미지들을 한번에 배포할 수 있게 도와주는 거라고 이해하고 있다.

그리고 보통 SSH Port의 경우 22를 기본으로 한다.

SSH 접속을 위해서는 아래의 라이브러리를 사용했다.

appleboy/ssh-action@v1.0.3

 

 

GitHub - appleboy/ssh-action: GitHub Actions for executing remote ssh commands.

GitHub Actions for executing remote ssh commands. Contribute to appleboy/ssh-action development by creating an account on GitHub.

github.com


Github Action 실행하기

위와 같은 설정들을 모두 마무리했다면 이제 소스를 실제로 push 한 후, 동작하는지 확인해보자.

실제로, 소스를 Push하면 해당 reposirtory의 action 탭에서 자동으로 Deploy를 수행한다.
혹시나 Deploy를 실행하다가 오류 발생시, 오류도 확인시켜주니 매우 편리하다고 느꼈다. 

아래 나의 시행착오를 보면 알수있다. 내가 모자라건가..?? 😂

수많은.. 시행착오 ... 😂


마무리

Github Action을 사용하면서 느꼈던점은 개발자라면 많이 들어보았을 Github Page가 있을 것이다.
필자도 블로그 운영을 위해서 경험해본적이 있는데, 그것과 똑같다는 생각이 들었다. 
그래도 Github page 경험이 있으니 의외로 시간을 낭비하지 않은 것 같다.

실제로 운영되는 프로젝트의 Github action 설정은 더 복잡할수있다.

내용들을 잘 정리했고 깊은 이해를 가지고 작성했는지는 잘 모르겠다. 하지만 나만 이해할 수 있게 정리하면 그만인듯하다나를 위한 블로그니까 👍👍

이제는 테스트 소스가 아닌 실제 개인프로젝트로 Github Action을 적용해보고자 한다.


참조👍

 

GitHub Actions의 체크아웃(Checkout) 액션으로 코드 내려받기

Engineering Blog by Dale Seo

www.daleseo.com

 

'BE > DevOps' 카테고리의 다른 글

[Docker] Spring Boot로 Docker Image 배포하기  (0) 2024.02.02