[DevOps] Github Action, Springboot, AWS EC2, Docker을 통한 CI/CD 구축

윤성철·2024년 7월 30일

DevOps

목록 보기
4/6
post-thumbnail

서론

5월부터 수행했던 사이드 프로젝트의 백엔드 서버 초기 배포를 수행했다. 기존에는 로컬에서 수동으로 Docker Image를 빌드하고 hub에 push한 뒤, ec2에 접속해서 pull하는 방식으로 배포를 진행했었다. 자동배포를 찾아보다가 Github-Action을 활용한 레퍼런스가 많아 적용해보게 되었다.

본론

개발환경

  • Java 17
  • SpringBoot
  • AWS EC2 Amazon Ubuntu
  • Gradle
  • Github-Action

순서

  1. AWS EC2 생성
  2. AWS RDS 생성
  3. ec2 docker 설치
  4. Dockerfile 생성(Springboot Root 디렉토리에)
  5. Github-action 설정

1, 2, 3은 레퍼런스가 워낙 많고 해당 포스트의 핵심이 아니기 때문에 생략하겠습니다..

CI/CD 아키텍처

Dockerfile 생성하기

FROM openjdk:17-jdk
ARG JAR_FILE=build/libs/*.jar
ADD ${JAR_FILE} demo-0.0.1-SNAPSHOT.jar
ENTRYPOINT ["java","-jar","/demo-0.0.1-SNAPSHOT.jar"]

Github action 설정하기

Java with Gradle configure로 들어가면, Github-action에서 gradle.yml 파일을 default로 만들어줍니다.

해당 yml 파일에서 jar로 build하는 부분은 수정할 부분이 없는데, .gradlew를 수행하는 사용자의 권한이 문제가 되어 permission denied 문제를 마주했습니다.

해당 부분을 추가해 권한 부여하여 해결했습니다.

다음으로 Github action의 Secret 값을 바인딩하는 설정을 진행하겠습니다.

HOST : EC2의 탄력적 IP주소
APPLICATION : 저는 기존에 레포지토리에서 .gitignore에 application.properties파일을 설정해주었기에, 따로 secret에서 추가해주었습니다.
EC2_SSH_PRIVATE_KEY : EC2 인스턴스를 개설하면서 받은 .pem 키
DOCKER_NAME : 도커 사용자명
DOCKER_PASSWORD : 도커 비밀번호
DOCKER_HUB_TOKEN : 도커 허브 ACCESS Token

gradle.yml

도움이 필요하신분들이 있을 것 같아, 설정 파일을 전부 올렸습니다.


name: Java CI with Gradle

on:
  push:
    branches: [ "dev" ]
  pull_request:
    branches: [ "dev" ]

jobs:
  build:

    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.properties
      run: |
        cd ./src/main/resources
        touch ./application.properties
        echo "${{ secrets.APPLICATION }}" > ./application.properties

    # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
    # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
    - name: Setup Gradle
      uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0

    - name: Make gradlew executable
      run: chmod +x ./gradlew

    - name: Gradle Build Action
      uses: gradle/gradle-build-action@v2.6.0
      with:
        arguments: clean build

    - name: Docker Login
      uses: docker/login-action@v2.2.0
      with:
        username: ${{ secrets.DOCKER_USERNAME }}
        password: ${{ secrets.DOCKER_PASSWORD }}
        
    - name: Build and push Docker images
      uses: docker/build-push-action@v4.1.1
      with:
        context: .
        push: true
        tags: ${{ secrets.DOCKER_USERNAME }}/spring-boot-server

    - name: Deploy to AWS EC2
      uses: appleboy/ssh-action@v0.1.10
      with:
        host: ${{ secrets.HOST }}
        username: ubuntu
        key: ${{ secrets.EC2_SSH_PRIVATE_KEY }} # pem key
        script: |
          docker pull ${{ secrets.DOCKER_USERNAME }}/spring-boot-server
          docker stop $(docker ps -a -q)
          docker run -d --log-driver=syslog -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/spring-boot-server
          docker rm $(docker ps --filter 'status=exited' -a -q)
          docker image prune -a -f


  dependency-submission:

    runs-on: ubuntu-latest
    permissions:
      contents: write

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

저는 tomcat port로 8080을 사용하고 있어서 docker 컨테이너의 port 역시 8080으로 설정했습니다.

성공적으로 자동배포를 구축했습니다!

참고

https://sum-mit45.tistory.com/58

profile
내 기억보단 내가 작성한 기록을 보자..

0개의 댓글