지식 정리/git

[Git] Github Actions CI/CD

27200 2025. 1. 23. 19:52

이전까지의 단계를 잘 마쳤다면 이제부턴 어렵지 않은 단계에 들어왔다.

자동 배포가 어렵게 다가올 수 있지만 천천히 따라오며 단계를 밟으면 쉽게 끝마칠 수 있을 것이다!


1. 도커 파일 설정

폴더의 바로 하단 디렉토리에 두 개의 파일을 만들 것이다. 1. Dokcerfile, 2. docker-compose.yml 이다.

Dockerfile

Dockerfile은 이미지를 빌드하기 위한 설정 파일이다.

Docker 이미지를 생성하는 데 필요한 명령어와 설정을 정의한다.

 

역할

  • 이미지 생성: 애플리케이션 실행 환경(예: 운영 체제, 라이브러리, 종속성 등)을 정의하고 이를 기반으로 Docker 이미지를 생성한다.
  • 자동화된 빌드: 수동으로 환경을 구성할 필요 없이 파일에 정의된 대로 이미지를 생성한다.
  • 재사용 가능: 동일한 Dockerfile로 동일한 환경의 이미지를 어디서든 쉽게 빌드할 수 있다.

주요 요소

  • FROM: 베이스 이미지를 지정한다. (예: FROM ubuntu:20.04)
  • RUN: 명령어를 실행하여 필요한 패키지나 라이브러리를 설치한다.
  • COPY 또는 ADD: 로컬 파일을 컨테이너 내부로 복사한다.
  • CMD 또는 ENTRYPOINT: 컨테이너가 시작될 때 실행될 명령어를 지정한다.
  • EXPOSE: 컨테이너가 외부에 노출할 포트를 설정한다.
FROM eclipse-temurin:17-jdk-alpine

ARG JAR_FILE=build/libs/test-0.0.1-SNAPSHOT.jar

COPY ${JAR_FILE} test.jar

ENV TZ Asia/Seoul

ENTRYPOINT ["java", "-jar", "test.jar"]

 

위와 같이 코드를 작성하여 만들어주자. ~/앱폴더/Dockerfile에 작성해 주면 된다.

각각의 내용은 간단하게 요약하자면 자바 17 버전의 jar파일을 만들어 넣겠다는 것이다.

필자의 경우 자바 17 버전을 사용했지만 이 외의 버전을 사용하고 싶다면 버전 부분을 맞추어 수정해 주자.


docker-compose.yml의 역할

docker-compose.yml은 여러 컨테이너를 정의하고 관리하기 위한 설정 파일이다.

단일 이미지를 빌드하는 Dockerfile과 달리, 컨테이너 간의 관계 및 설정을 작성하여 애플리케이션을 구성한다.

역할

  • 멀티 컨테이너 구성: 애플리케이션이 여러 서비스(예: 웹 서버, 데이터베이스)로 구성된 경우, 이를 쉽게 정의하고 실행할 수 있다.
  • 간단한 배포: 명령어 한 줄(docker-compose up)로 모든 컨테이너를 일괄적으로 관리하고 실행할 수 있다.
  • 네트워크 설정: 서비스 간의 네트워크를 자동으로 구성한다.
  • 환경 변수 관리: .env 파일과 연동하여 환경 변수를 관리할 수 있다.

주요 요소

  • services: 각 컨테이너(서비스)를 정의한다.
  • build: Dockerfile을 기반으로 이미지를 빌드한다.
  • image: 이미지를 직접 지정할 수 있다.
  • ports: 호스트와 컨테이너 간의 포트를 매핑한다.
  • volumes: 데이터를 컨테이너와 호스트 간에 공유하거나 유지한다.
  • depends_on: 서비스 간의 의존성을 정의한다.
version: '3.2'
services:
  remind:
    image: ${DOCKER_USERNAME}/test-image:latest
    restart: always
    env_file:
      - .env
    ports:
      - "8080:8080"
    volumes:
      - type: bind
        source: /home/ubuntu/Test/.env
        target: /.env

 

docker-compose를 작동시킬 파일이다.

여기서 volumes에 있는 부분은 secret 파일들을 관리하기 위하여 사용되는 것으로, 본인의 앱 경로에 맞추어 작성해 주면 된다.

혹은 단순하게 /home/ubuntu로만 작성해 주어도 된다. 결론은 경로만 기억하면 된다!


2. Github Actions 설정

깃허브 액션이란 말은 많이 들어봤을 것이다. 깃허브에서 작업을 할 때 특정 작업이 발생되면 이에 따라 정해진 작업들을 진행해 주는 것이다.

우리는 특정 작업(머지 혹은 푸시) 등이 되었을 때, docker 이미지를 만들고, 컨테이너를 띄워 서버를 구동시키게 해 줄 것이다.

그렇게 하기 위해서는 workflow를 만들어줘야 한다.

 

그렇게 하기 위해 Actions에 들어가서 workflow를 어디다 만들어야 하지...라고 헤매는 사람들이 있을 것이다.(필자도 그랬다 ㅎ)

 

실제로 workflow는 앱 안에 만들어주면 된다!

~/앱폴더/.github 안에 workflows 폴더를 만들어주고 deploy.yml을 만들어주자.

최종 경로는 ~/앱폴더/.github/workflows/deploy.yml이다 

여기서 yml 파일 명은 본인 마음대로 하면 된다.

 

name: Build and Push Docker Images


# main 브랜치에 push 될때 작동
on:
  push:
    branches:
      - main

jobs:
  build-image-and-push:
    runs-on: ubuntu-latest
    # 권한을 read로 제한
    permissions:
      contents: read
    # jdk 17 설정
    steps:
      - uses: actions/checkout@v4
      - name: Set up JDK 17
        uses: actions/setup-java@v4
        with:
          java-version: "17"
          distribution: "temurin"
      # gradle 설정
      - name: Setup Gradle
        uses: gradle/actions/setup-gradle@v3.1.0
      # 멀티플랫폼 이미지 빌드 환경 설정
      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3
      # 멀티플랫폼 이미지 빌드 환경 설정
      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3
      # 운영 서버에 .env 파일 생성
      - name: Set ".env" for configuration at NCP Server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.EC2_SERVER_IP }}
          username: ${{ secrets.EC2_SERVER_USERNAME }}
          key: ${{ secrets.EC2_SERVER_KEY }}
          script: |
            rm -rf ./.env
            touch ./.env
            
            echo "DB_HOST=${{ secrets.DB_HOST }}" >> ./.env
            echo "DB_PORT=${{ secrets.DB_PORT }}" >> ./.env
            
      # 권한 부여 후 gradle build
      - name: Set Gradle build Permission
        run: chmod +x gradlew

      - name: Gradle build
        run: ./gradlew build

      # Docker 이미지 빌드 및 푸시
      - name: Docker login
        run: |
          echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin

      - name: Build Docker Image
        run: |
          # 고유한 버전 태그로 빌드 및 푸시
          VERSION_TAG=$(git rev-parse --short HEAD)  # 커밋 해시를 태그로 사용
          docker build --no-cache -t ${{ secrets.DOCKER_USERNAME }}/market-api-backend:$VERSION_TAG .
          docker push ${{ secrets.DOCKER_USERNAME }}/market-api-backend:$VERSION_TAG
          docker tag ${{ secrets.DOCKER_USERNAME }}/market-api-backend:$VERSION_TAG ${{ secrets.DOCKER_USERNAME }}/market-api-backend:latest
          docker push ${{ secrets.DOCKER_USERNAME }}/market-api-backend:latest

      # 서버에 배포
      - name: Deploy to Server
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.DEV_SERVER_IP }}
          username: ${{ secrets.EC2_SERVER_USERNAME }}
          key: ${{ secrets.EC2_SERVER_KEY }}
          script: |
            cd ~/Market-API-Backend
            docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
            docker-compose down   # 기존 컨테이너 중지 및 삭제
            docker-compose pull   # 최신 이미지 가져오기
            docker-compose up -d  # 새로운 컨테이너 시작
            docker image prune -f # 사용되지 않는 이미지 삭제

 

중하단부에 있는 ./.env를 반드시 /home/ubuntu/Test/.env 이 경로와 동일하게 해 주자. 여기서는 다르지만 본인의 경로를 이용해서 꼭 맞춰주어야 한다.


3. Secret key 등록

 

settings -> Secrets and variables -> actions에 들어가면 된다.

New repository secrets를 누른 뒤 EC2_SERVER_IP와 같이 이름을 지어준 뒤 본인의 것에 맞게 만들어주면 된다.

이때 IP는 Public IPv4 DNS를 넣어주자. 만약 에러가 뜬다면 Public IPv4 address를 넣어보자.

username의 경우 ubuntu(필자는 우분투를 썼다.), key는 pem파일을 메모장으로 열어 붙여 넣기 해주자!

 

또한 이 외의 카카오톡 로그인을 위한 키 등을 등록해 주고, 등록해 주는 것들을 echo "DB_HOST=${{ secrets.DB_HOST }}" >> ./.env 양식에 맞추어서 추가해 주자.

예를 들어 KAKAO_KEY를 추가했다면 echo "DB_HOST=${{ secrets.KAKAO_KEY }}" >> ./.env 로 해주면 된다!!

 

이렇게 하게 되면 최종적으로 CI/CD 가 구성 완료되며 필자가 써둔 docker-compose 파일을 이용할 경우

# main 브랜치에 push 될때 작동
on:
  push:
    branches:
      - main

위와 같은 규칙에 의해 main 브랜치에 푸시될 때(pr이 돼서 머지될 때) 자동으로 작동되게 되어있다.

'지식 정리 > git' 카테고리의 다른 글

[Git] github.io 도메인 등록 & 페이지 털림  (0) 2025.03.21
[Git] CI/CD란?  (0) 2025.01.20