GitHub Actions와 Docker를 통한 CI/CD

jungseo·2024년 2월 7일

Cloud

목록 보기
4/4

프로젝트 진행 중 프론트엔드 개발자와 협업 중 배포환경에서 테스트를 해야하는 상황이 많았다. 그런데 변경 사항을 깃에 올리고 도커 이미지를 만들고 배포용 서버에서 구동중이던 어플리케이션을 종료하고 새로운 이미지로 실행하는 과정이 몹시 번거로웠고 이에 걸리는 시간을 줄이기 위해 CI/CD를 적용해 보았다.

Jenkis와 GitHub Actions 중 고민을 했었는데 Jenkis의 경우 별도의 서버가 필요하다 하여 비용적인 측면과 여러 사람이 공유한 Workflow를 사용할 수 있다는 점에서 Github Actions를 선택하였다.

DockerFile

# base-image
FROM openjdk:21

# COPY에서 사용될 경로 변수
ARG JAR_FILE=build/libs/*-SNAPSHOT.jar

# jar 빌드 파일을 도커 컨테이너로 복사
COPY ${JAR_FILE} app.jar

# jar 파일 실행
ENTRYPOINT ["java","-jar","/app.jar"]

빌드 시 생성된 SNAPSHOT.jar 파일을 app.jar이란 이름으로 도커 컨테이너로 복사하여 컨테이너 실행시 빌드된 jar파일이 실행되게 하였다.

server.yml

name: Java CICD with Gradle

on:
  push:
    branches: [ main ]

jobs:
  build:

    runs-on: ubuntu-latest

    env:
      working-directory: ./server/wonprice

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

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew
        working-directory: ${{ env.working-directory }}

      - name: Build with Gradle
        run: ./gradlew build
        working-directory: ${{ env.working-directory }}

      - name: Docker build
        run: |
          docker login -u ${{ secrets.DOCKER_HUB_USERNAME }} -p ${{ secrets.DOCKER_HUB_PASSWORD }}
          docker build -t wonprice . 
          docker tag wonprice jungseow/wonprice:${GITHUB_SHA::7}
          docker push jungseow/wonprice:${GITHUB_SHA::7}
        working-directory: ${{ env.working-directory }}

      - name: SSH Connection and Deploy to Server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.AWS_SSH_HOST }}
          username: ${{ secrets.AWS_SSH_USERNAME }}
          key: ${{ secrets.AWS_SSH_KEY }}
          envs: GITHUB_SHA
          script: |
            sudo docker rm -f wonprice
            sudo docker pull jungseow/wonprice:${GITHUB_SHA::7}
            sudo docker run -d --name wonprice -p 8080:8080 --env-file ./wonprice.env -e "SPRING_PROFILES_ACTIVE=server" jungseow/wonprice:${GITHUB_SHA::7}

흐름

과정은 저장소에 push 될때 gradlew 파일에 실행권한을 주고 빌드를 한후 빌드된 파일을 해당 커밋의 해시값을 태그로 도커 이미지를 빌드한다. 그후 ec2 인스턴스에 접속하여 기존 실행중인 어플리케이션을 종료하고 새로 만들어진 이미지를 실행한다.

최상위 경로에 .github/workflows 디렉토리를 만들고 그 안에 yml 파일을 만든다.

깃 저장소를 프론트엔드와 함께 사용하여 서버단의 ci/cd를 구성하기 위해 spring 프로젝트가 있는 경로를 환경변수로 넣어 사용하였다.

ec2 인스턴스에 ssh를 통해 접속하기 위해 필요한 값들은 git secret으로 추가하여 사용하였다.

SSH 접속

이 부분에서 시간이 가장 오래 걸렸다.

AWS_SSH_HOST -> 해당 ec2 인스턴스의 주소

AWS_SSH_USERNAME -> 사용자 이름(ec2-user, ubuntu 등 cmd에 whoami를 입력해도 나온다)

AWS_SSH_KEY -> 인스턴스에 ssh-keygen 명령어로 생성된 비밀키

생성된 키를 git secret으로 설정해도 계속해서 아래 오류 메세지와 함께 인증에서 실패했다..
ssh: handshake failed: ssh: unable to authenticate, attempted methods [none publickey]

이런 경우 ~/.ssh/authorized_keys에 생성한 퍼블릭 키를 넣어줘야 한다고 한다!

0개의 댓글