Git Action 과 Docker로 CI/CD 해보자! (GCE)

Panda·2022년 3월 15일
1

Git

목록 보기
2/3

지난번에 배운 Git Secret을 배운건 사실상 CI/CD를 하기 위한 추진력이였습니다.

CI / CD - Git Action

지난번에 배운 Git Secret을 적용 시켜서 Git Action을 작성해보자면

name: Spring Deploy to GCS

# workflow를 동작하게하는 trigger입니다.
# repository에 push 이벤트가 발생할 때마다 실행될 거예요.
on:
  push:
    branches: [ master ]

env:
  PROJECT_ID: ${{ secrets.GCS_PROJECT_ID }}
  GCE_INSTANCE: ${{ secrets.GCE_INSTANCE }}
  GCE_INSTANCE_ZONE: ${{ secrets.GCE_INSTANCE_ZONE }}

# job은 사용자가 정한 플랫폼을 통해 step이라는 일련의 과정을 실행할 수 있어요.
# 여러 개의 job을 사용할 수 있으며, 여러 개의 job을 사용할 때는 서로 정보도 교환할 수 있어요.
# 그리고 각각 독립적으로도 실행할 수도 있어요.
jobs:
  deploy:
    # 저는 해당 job을 리눅스 환경에서 사용할 거예요. 다른 플랫폼이 올 수도 있겠죠?
    runs-on: ubuntu-latest

 	# job 안에는 step이라는 키워드가 옵니다. step은 shell script를 실행할 수도 있고,
    # 누군가 만들어 놓은 Action을 사용할 수도 있어요.
    steps:
    
      # GitHub Actions는 해당 프로젝트를 리눅스 환경에 checkout하고 나서 실행을 합니다.
      # 마치 우리가 브랜치를 만들 때 checkout하는 것처럼요. 꼭 필요합니다.
      # 참고로 아래 코드는 누군가 만들어놓은 Action을 사용하는 겁니다.
      # 만들어놓은 Action을 사용할 때는 uses라는 키워드를 사용해야 돼요.
      - name: Checkout
        uses: actions/checkout@v2
		
        # CI 시작 부분
      - name: Set up JDK 11
        uses: actions/setup-java@v1
        # with라는 키워드로 Action에 값을 전달할 수 있어요.
        # 이 Action은 java-version이라는 값을 받을 수 있네요?
        with:
          java-version: 11

	  # push할 때마다 gradle을 install 해야될까요? (시간이 여간 많이 걸리는 게 아닐 텐데 ..)
      # 아닙니다. 해당 프로젝트의 gradle이 변했는지 안 변했는지를 이용해서
      # 모듈 변화가 있을 때만 gradle install을 해줄 수도 있어요.
      - name: Cache Gradle packages
        uses: actions/cache@v2
        with:
          path: |
            ~/.gradle/caches
            ~/.gradle/wrapper
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*') }}
          restore-keys: ${{ runner.os }}-gradle-
		
      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      # Git Secret을 이용한 application-dev.properties 생성
      - name: Create Spring Properties
        run: |
          touch server/src/main/resources/application-dev.properties
          echo "$DEV_SPRING_PROPERTIES" > application-dev.properties.b64
          base64 -d -i application-dev.properties.b64 > server/src/main/resources/application-dev.properties
        env:
          DEV_SPRING_PROPERTIES: ${{ secrets.DEV_SPRING_PROPERTIES }}
		
      # 빌드시 테스트 코드까지 전부 테스트 진행함.
      - name: Build with Gradle
        run: |
          ./gradlew clean :server:build -Pprofile=dev      


	  # CD 시작 부분 (GCE 배포 설정)
      - name: Setup gcloud
        uses: google-github-actions/setup-gcloud@v0
        with:
          service_account_key: ${{ secrets.GCS_SERVICE_ACCOUNT_KEY }}
          project_id: ${{ secrets.GCS_PROJECT_ID }}
          export_default_credentials: true

      # Configure Docker to use the gcloud command-line tool as a credential
      # helper for authentication
      # GCE Docker 인증
      - run: |-
          gcloud --quiet auth configure-docker
      # Build the Docker image
      - name: Build
        run: |-
          docker build --tag "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA" server
      # Push the Docker image to Google Container Registry
      # Docker image를 Google Container Registry push 함. 
      # 이때 Google Container Registry API 사용 해야함.
      - name: Publish
        run: |-
          docker push "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA"
          
      # GCE에 Docker 실제 배포 (도커 컨테이너 업데이트)
      # Google Container Registry에 등록된 Docker로 업데이트 되어 배포 되는 원리
      - name: Deploy
        run: |-
          gcloud compute instances update-container "$GCE_INSTANCE" \
            --zone "$GCE_INSTANCE_ZONE" \
            --container-image "gcr.io/$PROJECT_ID/$GCE_INSTANCE-image:$GITHUB_SHA"

GCE 서버에 배포하는 CI/CD Git Action 입니다.

CI 부분까지는 큰 문제 없이 삽질 그렇게 안하고 잘 적용을 했는데
문제는 CD 부분에서 삽질을 엄청나게 했습니다....

문제 발생

첫번째 문제

  • Docker를 이용한 배포여서 Docker에 대한 지식이 하나도 없어서
    Docker build, Docker push 시 각종 에러를 겪음

두번째 문제

  • Gcloud Docker 배포에서 각종 에러가 발생하여 정말 많은 삽질을 하였습니다.

해결 방법

1. Docker build 경우는 DockerFile이 필요하다는 것을 알게되어서 DockerFile을 작성하였다.

FROM openjdk:17-oracle
ARG JAR_FILE=build/libs/server-1.0.00.war
COPY ${JAR_FILE} app.war
ENTRYPOINT ["java", "-jar", "app.war", "--spring.profiles.active=dev"]

키워드 별 수행 기능

  • FROM : JDK 세팅 (반드시 FROM 으로 시작해야함)
  • ARG : Argument로 JAR_FILE 에 build/libs/server-1.0.00.war 경로를 담음
  • COPY : 위에서 할당한 변수를 app.war 이름으로 복사함.
  • ENTRYPOINT : java를 실행하는 parameter를 담음

DockerFile 처음 작성했을 떄는 구글링해서 작성한거라
ARG JAR_FILE=build/libs/*.war 으로 작성했는데 에러가 발생했었습니다.
그 이유는 server-1.0.00.war, server-1.0.00-plain.war 2개의 파일이 존재해서 그런거였습니다.
그래서 둘중 원하는 파일로 실행을 시키면 될것같습니다.

이렇게 작성하면 Docker build는 DockerFile을 기반으로 image를 만들게 됩니다.

참고로 DockerFile에서 CI 세팅도 할수있긴한데
이미 Git Action에서 CI 수행을 하기 때문에 Docker에서는 제외했습니다.

2. gcloud Docker 배포시 필요한 설정

별의별 에러가 났는데 그 이유는 Git Action 코드의 문제가 아닌 서버 설정이 잘못되어 일어난 일이였습니다.

Google Container Registry API
먼저 Google Container Registry API 사용한다 설정을 해줘야 Docker image가 push가 가능합니다.

GCE Instance 설정
GCE 생성할때 컨테이너 이미지 배포 옵션에 컨테이너 이미지 를 넣어줘야 합니다. (가장 중요!!)

저는 이것들을 모르고 컨테이너 이미지 배포 옵션이 없는 인스턴스에다가 도커 업데이트를 해줘서 에러가 난거였습니다.............

위에 해결방법을 적용해서 다시 Git Action을 작동시키니까 정상적으로 배포가 되어
해당 서버 인스턴스에 스프링부트가 작동하는 것을 확인할 수 있었습니다.

느낀점

CI / CD 구축하는 것이 엄청 어려운 작업이라는 것을 느꼈고
특히 배포할 서버측도 설정을 해줘야 하니까 서버를 제공하는 플랫폼에 대해서도 잘 알아야될 것 같습니다.
Docker는 공부하는 도중에는 엄청 어려웠는데 막상 작업 다 끝나고 되돌아보니까
적용시키는 것이 별거 아닌거 같았습니다. ( Docker는 공부하면서 재밌었어요)

이번 경험을 바탕으로 나중에는 Git Action을 바탕으로 한 AWS E3 배포라던지 혹은 다른서버들도 배포하면 좋을것 같습니다.

profile
실력있는 개발자가 되보자!

0개의 댓글