GitHub Actions로 CI/CD 구축 #4

artp·2024년 12월 18일

CI/CD

목록 보기
7/9
post-thumbnail

GitHub Actions로 CI/CD 구축 #3에서는 확장성을 고려한 프로젝트에서 많이 사용하는 CI/CD 구축 방법을 소개했습니다.

이번 글에서는 DockerAWS ECR을 사용하여 컨테이너 기반의 프로젝트에서 많이 사용하는 CI/CD 구축 방법을 알아보도록 하겠습니다.

이 방식은 Docker 기반 서비스 운영 시 가장 단순하게 구성할 수 있는 인프라 구조입니다. 컨테이너 기반 인프라에서 자주 사용되며, 서버 수가 많지 않은 소규모 프로젝트에 특히 적합합니다.

EC2 세팅

EC2에 Docker, Docker Compose 설치

다음의 명령어를 EC2에 입력하여 Docker와 Docker Compose를 설치합니다.

$ sudo apt-get update && \
	sudo apt-get install -y apt-transport-https ca-certificates curl software-properties-common && \
	curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - && \
	sudo apt-key fingerprint 0EBFCD88 && \
	sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" && \
	sudo apt-get update && \
	sudo apt-get install -y docker-ce && \
	sudo usermod -aG docker ubuntu && \
	sudo curl -L "https://github.com/docker/compose/releases/download/1.23.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && \
	sudo chmod +x /usr/local/bin/docker-compose && \
	sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

설치 확인 명령어는 다음과 같습니다.

$ docker -v # Docker 버전 확인
$ docker compose version # Docker Compose 버전 확인

EC2가 Private ECR에 접근할 수 있도록 세팅

1. Amazon ECR Docker Credential Helper 설치

Amazon ECR Docker Credential Helper란?

  • ECR에 저장된 Docker 이미지를 Private Repository에서 가져오기(Pull)나 푸시(Push)할 때, 인증 과정을 단순화하는 도구입니다.
  • AWS CLI를 통해 매번 인증 토큰을 수동으로 생성할 필요 없이, Docker가 자동으로 AWS IAM 인증을 처리합니다.
# Ubuntu일 경우
$ sudo apt update
$ sudo apt install amazon-ecr-credential-helper

2. Configuration 설정

Amazon ECR Docker Credential Helper 설치가 완료되면 Docker 클라이언트가 Amazon ECR Docker Credential Helper를 사용할 수 있도록 구성해야 합니다.

  1. ~ 경로(홈 디렉터리)에 .docker 폴더 생성
    $ mkdir -p ~/.docker
  2. .docker 폴더 내에 config.json 파일 생성
    $ vi ~/.docker/config.json
  3. 파일 내용 작성
    config.json 파일에 아래 내용을 입력 후 저장합니다:
	{
  	  "credsStore": "ecr-login"
	}
  1. 설정 확인
    • 설정이 제대로 저장되었는지 확인하려면 다음 명령어를 실행하면 됩니다:
      $ cat ~/.docker/config.json

3. EC2 IAM 역할에 ECR 접근 권한 추가

  • IAM - 역할 - 이전에 생성했던 EC2 역할 선택 - 권한 추가 선택
  • AmazonEC2ContainerRegistryFullAccess 권한을 추가합니다 (ECR에 대한 전체 액세스 권한을 부여).

GitHub Actions의 IAM에 권한 추가

이전에 생성했던 GitHub Actions의 IAM 사용자에 ECR 권한을 추가합니다.
AmazonEC2ContainerRegistryFullAccess 권한을 추가하면 됩니다 (ECR에 대한 전체 액세스 권한을 부여).

  • IAM - 사용자 - 이전에 생성했던 GitHub Actions 사용자 선택 - 권한 추가 선택
  • 직접 정책 연결 - AmazonEC2ContainerRegistryFullAccess 권한 추가
  • 권한 추가 선택

ECR 세팅

ECR (Elastic Container Registry)이란?

AWS ECR(Amazon Elastic Container Registry)은 컨테이너 이미지를 저장하고 관리하는 AWS 서비스입니다. 쉽게 말해, 이미지를 저장하고 공유하는 Docker Hub와 비슷한 역할을 합니다. AWS ECR을 사용하면 도커 이미지를 안전하게 저장하고 관리할 수 있으며, 이를 필요할 때 EC2, ECS 등 다양한 AWS 리소스와 연동해 실행할 수 있습니다.

Docker Hub와 AWS ECR의 차이점

  • Docker Hub:
    Docker 이미지를 전 세계적으로 공유하거나 다운로드하는 데 주로 사용됩니다. 퍼블릭 레지스트리로, 전 세계 개발자가 널리 사용하는 저장소입니다.
  • AWS ECR:
    Docker Hub와 비슷하지만, AWS 서비스와의 높은 연동성과 AWS 환경에서 통합 관리의 장점이 있습니다. ECR은 AWS의 IAM(Identity and Access Management)을 통해 접근 제어와 보안도 간편하게 설정할 수 있습니다.

ECR 생성

  • ECR 프라이빗 리포지토리를 생성합니다.
  • 리포지토리 이름을 작성합니다.
  • 리포지토리 생성 완료를 확인합니다.

Docker 기반으로 프로젝트 수정

프로젝트 최상단 경로(루트 경로)에 Dockerfile을 생성 및 작성합니다.

# 베이스 이미지로 Eclipse Temurin 17 JDK Alpine 버전을 사용
# 이 이미지는 OpenJDK 17 기반이며, Alpine Linux를 사용하여 경량화되어 있음
FROM eclipse-temurin:17-jdk-alpine

# 현재 디렉토리의 build/libs 폴더에 있는 *SNAPSHOT.jar 파일을 도커 컨테이너의 루트 디렉토리에 project.jar로 복사
# 일반적으로 Gradle 빌드 결과물(JAR 파일)이 이 경로에 생성됨
COPY ./build/libs/*SNAPSHOT.jar project.jar

# 도커 컨테이너가 실행될 때 JAR 파일을 실행하는 명령어를 설정
# ENTRYPOINT는 도커 컨테이너가 시작될 때 실행할 명령어를 지정함
ENTRYPOINT ["java", "-jar", "project.jar"]

GitHub Actions 파일 작성

  • .github/workflows/deploy.yml
name: Deploy To EC2  # 워크플로 이름 정의, Actions 탭에서 이 이름으로 표시됨

on:
  # main 브랜치에 코드가 푸시되었을 때 워크플로가 실행됨
  push:
    branches:
      - main

jobs:
  deploy:
    # GitHub Actions에서 제공하는 최신 Ubuntu 환경 사용
    runs-on: ubuntu-latest
    steps:
      # GitHub 저장소의 코드를 가져옵니다.
      - name: GitHub Repository 파일 불러오기
        uses: actions/checkout@v4

      # Java 애플리케이션 실행을 위해 JDK 17을 설치합니다.
      - name: JDK 17버전 설치
        uses: actions/setup-java@v4
        with:
          distribution: temurin  # Temurin JDK 사용
          java-version: 17  # Java 17 버전 설치

      # GitHub Secrets에서 가져온 설정값으로 application.yml 파일을 생성합니다.
      - name: application.yml 파일 만들기
        run: echo "${{ secrets.APPLICATION_PROPERTIES }}" > ./src/main/resources/application.yml

      # Gradle을 사용해 코드를 테스트하고 빌드합니다.
      - name: 테스트 및 빌드하기
        run: ./gradlew clean build

      # AWS 서비스에 접근할 수 있도록 자격 증명을 설정합니다.
      - name: AWS Resource에 접근할 수 있게 AWS credentials 설정
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-region: ap-northeast-2  # AWS 리전 (서울 리전)
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}  # AWS Access Key
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}  # AWS Secret Key

      # AWS Elastic Container Registry(ECR)에 로그인합니다.
      - name: ECR에 로그인하기
        id: login-ecr
        uses: aws-actions/amazon-ecr-login@v2

      # Docker 이미지를 'test-server' 이름으로 빌드합니다.
      - name: Docker 이미지 빌드
        run: docker build -t test-server .

      # 빌드된 Docker 이미지에 ECR 레지스트리를 기반으로 태그를 추가합니다.
      - name: Docker 이미지에 Tag 붙이기
        run: docker tag test-server ${{ steps.login-ecr.outputs.registry }}/test-server:latest

      # 태그된 Docker 이미지를 AWS ECR로 푸시합니다.
      - name: ECR에 Docker 이미지 Push
        run: docker push ${{ steps.login-ecr.outputs.registry }}/test-server:latest

      # EC2에 SSH로 접속해 기존 컨테이너를 중단 및 삭제하고, 최신 Docker 이미지를 실행합니다.
      - name: SSH로 EC2에 접속하기
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.EC2_HOST }}  # EC2 호스트 주소 (GitHub Secrets에서 가져옴)
          username: ${{ secrets.EC2_USERNAME }}  # EC2 사용자 이름
          key: ${{ secrets.EC2_PRIVATE_KEY }}  # EC2 비밀 키
          script_stop: true  # 스크립트 실행 중 오류 발생 시 워크플로 중단
          script: |
            docker stop test-server || true  # 실행 중인 컨테이너 중지 (실패 무시)
            docker rm test-server || true  # 기존 컨테이너 삭제 (실패 무시)
            docker pull ${{ steps.login-ecr.outputs.registry }}/test-server:latest  # 최신 Docker 이미지 가져오기
            docker run -d --name test-server -p 8080:8080 ${{ steps.login-ecr.outputs.registry }}/test-server:latest
            # 새로운 Docker 컨테이너를 실행하고, 8080 포트를 매핑하여 애플리케이션 노출

결과 확인

배포가 잘 된 것을 확인할 수 있습니다.

profile
donggyun_ee

0개의 댓글