상세 컨텐츠

본문 제목

Github Actions + AWS Elastic Beanstalk으로 Springboot 어플리케이션 CI/CD 파이프라인 구축하기

Infrastructure

by 촬쓰으 2023. 4. 30. 14:57

본문

CI/CD 툴인 Github Actions와 웹 애플리케이션 개발/배포/관리를 완전관리형(PaaS) 서비스 AWS Elastic Beanstalk을 사용합니다.

컨테이너 환경에서 Springboot 어플리케이션을 자동으로 빌드, 테스트, 배포하기 위한 CI/CD 파이프라인을 구축해보겠습니다. 

 

왜 Docker 컨테이너 환경에서 Springboot 어플리케이션을 실행해야 할까

Springboot 어플리케이션을 컨테이너 환경에서 배포하려면 운영 체제와 라이브러리, 실행 환경 등 모든 요구 사항을 수동으로 설치 및 구성해야 합니다. 이 작업은 어플리케이션을 여러 환경에서 실행할 때 일관성을 유지하기 어렵고, 매우 복잡하고 시간이 많이 소요됩니다.

Dockerfile을 사용하면 Springboot 어플리케이션의 실행 환경을 정의할 수 있으며, 컨테이너를 쉽게 빌드 및 배포할 수 있습니다. Dockerfile에는 컨테이너 이미지를 빌드하는 데 필요한 모든 정보가 포함되어 있으므로, Docker를 사용하면 Springboot 어플리케이션을 어디서든 쉽게 배포하고 실행할 수 있습니다.

또한 Docker를 사용하면 컨테이너화된 Springboot 어플리케이션의 환경을 일관성 있게 유지할 수 있습니다. 예를 들어, 로컬 환경에서 작동하는 어플리케이션이 테스트 환경에서 작동하지 않는 경우, Dockerfile을 수정하여 테스트 환경에서도 정확히 같은 실행 환경을 유지할 수 있습니다. 이를 통해 어플리케이션 배포 및 유지 보수 과정에서 발생할 수 있는 많은 문제를 예방할 수 있습니다.

 

구축할 아키텍쳐

 

Dockerfile 작성하기

FROM eclipse-temurin:17-jdk
CMD ["./gradlew", "clean", "build"]
ARG JAR_FILE_PATH=build/libs/server-0.0.1-SNAPSHOT.jar
COPY ${JAR_FILE_PATH} app.jar
ENTRYPOINT ["nohup", "java", "-jar", "app.jar", "2>&1", "&"]

이 Dockerfile은 Eclipse Temurin 17 JDK를 기반으로하는 Java 애플리케이션을 컨테이너화하는 데 사용됩니다.

  • CMD 구문은 컨테이너가 시작될 때 실행될 명령어를 정의합니다. 여기서는 "./gradlew clean build" 명령어가 실행됩니다.
  • ARG 구문은 Docker 빌드 중에 전달할 인수를 정의합니다. 여기서는 "JAR_FILE_PATH"라는 변수를 정의하고 "build/libs/server-0.0.1-SNAPSHOT.jar"로 해당 변수 값을 설정합니다.
  • COPY 구문은 호스트에서 컨테이너로 파일을 복사합니다. 여기서는 "JAR_FILE_PATH"에서 정의된 경로에 있는 "server-0.0.1-SNAPSHOT.jar" 파일을 "app.jar"로 복사합니다.
  • ENTRYPOINT 구문은 컨테이너가 시작될 때 실행될 기본 실행 파일을 정의합니다.
    여기서는 "nohup java -jar app.jar 2>&1 &" 명령어가 실행됩니다.
    이 명령어는 "app.jar" 파일을 백그라운드에서 실행하고, 표준 출력 및 오류를 "nohup.out" 파일로 리디렉션합니다.

 

AWS EB 환경세팅하기

아래의 포스팅을 참고하여 환경을 세팅해주세요. 

https://blog-sluv.tistory.com/entry/AWS-AWS-Elastic-Beanstalk-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%84%B1%ED%95%B4%EB%B3%B4%EA%B8%B0

 

[AWS] AWS Elastic Beanstalk 환경 구성해보기

AWS Elastic Beanstalk이란 AWS Elastic Beanstalk는 클라우드에서 웹 애플리케이션을 개발, 배포 및 관리하기 위한 완전관리형(PaaS) 서비스입니다. 개발자는 Elastic Beanstalk를 사용하여 웹 애플리케이션의 인

blog-sluv.tistory.com

 

AWS IAM ACCESS KEY, SECRET KEY 발급받기

같은 AWS 서비스가 아닌 외부 서비스인 Github Actions에서는 AWS 서비스에 명령을 내릴 수 있는 권한을 받아야 합니다.

해당 권한을 받기 위해 IAM 사용자를 이용한 인증키(accessKey, secretKey)를 활용하겠습니다. 

 

[IAM] - [사용자]에서 [사용자 추가]를 선택합니다. 

 

accessKey, secretKey를 발급받을 수 있는 사용자 정보를 생성합니다.

 

[직접 정책 연결]을 선택하고 [AdministratorAccess-AWSElasticBeanstalk] 정책을 연결한 후 사용자를 생성해줍니다. 

 

생성한 사용자 대시보드로 접속한 후 [보안 자격 증명] 탭에서 액세스 키를 만들어줍니다.

액세스 키는 csv 파일로 다운로드 받아 관리하는 것을 추천합니다. 

 

Github Repository에 Github Actions를 위한 환경변수 등록하기

AWS 및 Dockerhub 접근을 위해 발급받은 AWS IAM 키와 Dockerhub ID, PW를 secrets에 등록해주어야 합니다.

Repository의 [Settings] - [Secrets and variables] - [Actions]로 이동한 후 아래 4개의 환경변수를 등록해줍니다. 

  • AWS_ACCESS_KEY_ID : AWS IAM 액세스 키 ID
  • AWS_SECRET_ACCESS_KEY : AWS IAM 시크릿 액세스 키
  • DOCKERHUB_USERNAME : Dockerhub 아이디
  • DOCKERHUB_TOKEN : Dockerhub 비밀번호

 

Github Actions 사용을 위한 yml 파일 작성

Github Actions는 자동화된 빌드, 테스트, 배포 등의 작업을 수행하기 위한 도구입니다. 이러한 작업들은 일반적으로 workflow라고 하는 하나 이상의 작업을 포함하고 있습니다.
Workflow 파일은 Github Actions에서 실행되는 작업을 정의하는데 사용됩니다. 이 파일은 YAML 구문으로 작성되며, 빌드, 테스트, 배포 등의 단계를 명시하고 실행되는 조건과 이벤트를 지정할 수 있습니다.

 

아래 코드는 GitHub Actions를 사용하여 개발 브랜치(develop)에 대한 CI/CD를 구성하는 YAML 파일입니다. 이 workflow 파일은 개발자가 코드를 push할 때마다 실행됩니다.

이 workflow 파일은 다음과 같은 작업 단계(steps)를 포함합니다:

  • 최신 리포지토리를 체크아웃합니다.
  • JDK 17을 설정합니다.
  • gradlew 파일에 실행 권한을 부여합니다.
  • Gradle로 빌드합니다.
  • Docker 이미지를 빌드하고, Docker Hub에 푸시합니다.
  • 현재 시간을 가져와서 타임스탬프를 생성합니다.
  • 타임스탬프를 형식에 맞게 변환합니다.
  • AWS Elastic Beanstalk에 배포합니다.

이 workflow 파일은 개발자들이 코드를 변경하고 push할 때마다 코드를 자동으로 빌드하고 테스트하며, Docker 이미지를 빌드하고 AWS Elastic Beanstalk에 배포합니다. 따라서 개발자들은 더욱 안정적인 배포를 보장할 수 있습니다.

name: dev CI/CD

on:
  push:
    branches: [ develop ]

jobs:
  dev-ci-cd:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout Latest Repo
        uses: actions/checkout@v3
      - name: Set up JDK 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 clean build

      - name: Docker build
        run: |
          docker login -u ${{ secrets.DOCKERHUB_USERNAME }} -p ${{ secrets.DOCKERHUB_TOKEN }}
          docker build -t sluv-springboot-main-cicd . 
          docker tag sluv-springboot-main-cicd sluv2323/sluv-springboot-main-cicd:latest
          docker push sluv2323/sluv-springboot-main-cicd:latest
      - name: Get timestamp
        uses: gerred/actions/current-time@master
        id: current-time

      - name: Run string replace
        uses: frabert/replace-string-action@master
        id: format-time
        with:
          pattern: '[:\.]+'
          string: "${{ steps.current-time.outputs.time }}"
          replace-with: '-'
          flags: 'g'

      - name: Beanstalk Deploy
        uses: einaregilsson/beanstalk-deploy@v21
        with:
          aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          application_name: sluv-dev
          environment_name: Sluvdev-env
          version_label: "github-action--${{ steps.format-time.outputs.replaced }}"
          region: ap-northeast-2
          deployment_package: Dockerrun.aws.json
          wait_for_environment_recovery: 180

 

Dockerrun.aws.json 파일 작성하기

Docker 컨테이너를 Elastic Beanstalk에서 실행하려면 Dockerrun.aws.json 파일을 작성해야 합니다.

 

Dockerrun.aws.json 파일은 Docker 컨테이너를 배포하기 위한 AWS Elastic Beanstalk의 설정 파일입니다. 이 파일은 AWS Elastic Beanstalk에게 Docker 이미지를 빌드하고 실행하는 방법에 대한 정보를 제공합니다. 이 파일은 Docker 이미지, 환경 변수, 포트 번호, 리소스 제한 등을 정의할 수 있습니다.

GitHub Actions를 통해 Docker Hub로 이미지를 push 할 때 Dockerrun.aws.json 파일을 작성해야 하는 이유는 AWS Elastic Beanstalk에 Docker 컨테이너를 배포하기 위해서는 이 파일이 필요하기 때문입니다. Dockerrun.aws.json 파일을 작성하면 AWS Elastic Beanstalk에서 Docker 컨테이너를 쉽게 배포할 수 있습니다.

 

빌드한 프로젝트의 포트를 꼭 확인한 뒤 ContainerPort에 적어줍니다. 

HostPort에는 Beanstalk의 서버포트인 5000번을 적어줍니다. 

{
  "AWSEBDockerrunVersion": "1",
  "Image": {
    "Name": "sluv2323/sluv-springboot-main-cicd:latest",
    "Update": "true"
  },
  "Ports": [
    {
      "ContainerPort": 8080,
      "HostPort": 5000
    }
  ]
}

 

배포 확인하기

지정한 Github Repo 브랜치에 Code가 Merge되면 자동으로 빌드/테스트/배포 과정을 거쳐 정상적으로 자동 배포가 진행되었습니다. 

 

'Infrastructure' 카테고리의 다른 글

[AWS] AWS Elastic Beanstalk 환경 구성해보기  (0) 2023.04.30

관련글 더보기

댓글 영역