본문 바로가기
ASAC

Docker Image와 Github Actions를 사용한 CI/CD 자동화

by suhsein 2024. 10. 30.
728x90
이 글은 ASAC 06기를 수강하며 강의 자료 참고 및 추가 자료 수집을 통해 작성된 글입니다.

 

CI / CD 절차

CI (Continuous Integration 지속적 통합)

  1. Develop
  2. Test Java
  3. Build Java
  4. Build Docker Image
  5. Push Docker Image to Registry

CD (Continuous Deployment 지속적 배포)

  1. Pull Docker Image from Docker Registry
  2. Run Docker Image => Server에서 수행

1번 : (1) Local 에서 수행 <- 불변(고정) 절차
2~6번 : (1) Local 혹은 (2) Github Actions / Jenkins (CI/CD 자동화 툴) 에서 수행 <- 가변 절차
7번 : (3) Server 에서 수행 <- 불변(고정) 절차

CI / CD 자동화

CI/CD를 사람이 매번 직접 한다면 비효율적이며, 실수할 위험성이 있음.
CI/CD는 본래 DevOps 엔지니어가 하는 일이지만, 그렇지 못한 경우 자동화 툴을 이용한 간편한 CI/CD 설정을 한다.

자동화 툴 => Jenkins, Github Actions
자동화 툴을 이용해서 이벤트 발생 시 특정 작업이 일어나게 하거나, 주기적으로 어떤 작업들을 반복해서 실행

CI / CD 자동화를 통해서 할 수 있는 작업들

  1. 테스트
    • 누군가 코드 저장소에 Pull Request 생성 시 Github Actions을 통해 해당 코드에 문제가 없는지 각종 검사를 진행
  2. 배포
    • 새로운 코드가 기본 브랜치(master, main)에 유입되면(push) Github Actions를 통해 소프트웨어를 빌드하고 상용 서버에 배포할 수 있음
  3. 배치
    • 매일 밤 특정 시각에 그날 하루에 대한 통계 데이터를 수집시킬 수도 있다.

Github Actions

대표적인 CI / CD 자동화 툴로는 Jenkins와 Github Actions가 존재하는데, Jenkins는 직접 서버를 구축해야 한다는 단점이 존재하지만, Github Actions는 Github이 서버를 제공하며, Github Repository와 호환성이 좋다는 장점을 가진다. 그렇기 때문에 Github Actions를 통한 CI / CD 자동화에 대해서 알아보고 실습을 진행해보았다.

Github Actions 동작 원리

  • event : 작업 실행 시점
  • runner : job을 수행하는 가상머신 혹은 컨테이너
  • job : 작업 단위 (소작업(step)들의 집합)
  • step: 소작업. 다음과 같은 종류들이 있다.
    • command(단순)
    • script(복잡)
    • action(다른 사람이 만들어 올린 script. 라이브러리 같은 개념. 재사용 및 중복 제거)

Github Actions 사용 방법

1. Workflow 구성 및 작성

  • .github/workflows 디렉토리 하위에, yaml 파일로 워크 플로우 정의. (ex) .github/workflows/script.yaml )
    • 모든 작업 실행 순서를 정의.
    • 여러 개의 워크플로우 yaml 파일을 생성해놓을 수 있다.
on 속성 : Event = 작업 실행 시점 정의.

1) 브랜치 기준 : 어떤 브랜치에 어떤 액션이 발생했는지 기준으로 작업 수행

on:
  push:
    branches: [main]
jobs: 
 # ...(생략)...

2) 이슈 기준 : 브랜치와 비슷하게 이슈가 발행된 시점, 어떤 타입으로 발행되었는지 등을 기준으로 작업 수행

3) 시간 기준 : cron 문법을 통해 언제 몇 시 몇 분마다 수행할 것인지 스케줄에 따라 작업 수행

on:
  schedule:
    - cron: "0 0 * * *"
jobs: 
 # ...(생략)...
job 속성 : Job = 작업 처리 단위

독립된 가상 머신(VM) 혹은 컨테이너(Container)에서 수행되는 하나의 처리 단위로, 기본적으로 병렬 수행

  • 1 Workflow : N Job
  • 하나의 워크플로우는 여러 개의 Job으로 구성되며, 최소 하나의 Job은 있어야 한다.
# ...(생략)...

jobs:
  job1:
    # job1에 대한 세부 내용
  job2:
    # job2에 대한 세부 내용
  job3:
    # job3에 대한 세부 내용
runs-on 속성 : Runner = Job 수행을 위한 OS(머신) 정의
  • 1 Job : 1 Runner
    • Workflow 마다 Runner를 정의하는 게 아닌, Job 마다 Runner를 정의
      • Workflow 내 각각의 Job마다 별개의 OS(머신) 정의 가능
# ...(생략)...
jobs:
  job1:
    runs-on: ubuntu-latest
    steps:
      # ...(생략)...
step 속성 : 소작업 처리 단위 (Script 혹은 Action)
name: learn-github-actions 
run-name: ${{ github.actor }} is learning GitHub Actions 
on: [push]
jobs:
  check-bats-version:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'
      - run: npm install -g bats
      - run: bats -v
  • name : 각 workflow 식별에 사용됨
  • run-name : 실행의 컨텍스트나 정보를 담을 수 있음
  • run : command(단순) 혹은 script(복잡)
  • uses : action(라이브러리 같은 성격의 스크립트 사용)
    • 위 예시에서 체크아웃 액션(actions/checkout) : 코드 저장소로부터 코드 내려받는 스크립트

2. Github Repository에 push

Github Repository에 workflow 파일과 작업 디렉토리를 함께 push한다.

(Github Actions 수행을 위해서는 main 혹은 master 브랜치에 해야한다.)

그 후, Github Actions 탭에 들어가면, CI / CD 자동화가 이루어지는 과정을 확인할 수 있다.

진행 중일 때는 노란색 불이 들어오고, 정상적으로 완료되면 초록색 체크 표시를, 실패하면 빨간색 x 표시를 보여준다. (실패 시 이메일 전송)

수동 절차

=> Github Actions로 CI + 개발자가 직접 CD

3개 타입 인스턴스

(1) local (2) Github Actions / Jenkins (3) Server

Docker Image 업로드 방식

  1. Docker Image 준비
  2. EC2로 Docker Image 전달하기
    • 선택 1. SCP : tar로 압축 후, SCP(Secured Copy) 통해 EC2로 전달.
    • 선택 2. ECR : ECR(Elastic Container Registry) 업로드 후, EC2 내 ECR로부터 다운로드.
  3. EC2 내 실행

Registry(ECR(Elastic Container Registry) 혹은 Docker Registry)에 업로드 된 빌드 이미지는,
1. ECS(Elastic Container Service)를 통해, EC2와 연결하여 배포 파이프라인 구축 가능.
2. Terraform을 통해, EC2와 연결하여 배포 파이프라인 구축 가능.

  1. 프로젝트 디렉토리
  2. script.yml
    * github action에서 동작 수행을 위해 .github/workflows 하위에 스크립트 yml 파일 업로드
  3. Dockerfile
    * github action에서 docker를 통해 이미지를 빌드하기 위해 Dockerfile 함께 업로드

 

실습 1. Github Actions로 CI + 개발자가 직접 CD

  1. CI : Github Actions로 자동화
    • jar 파일 build
    • Docker Login
    • Docker Image Build
    • Docker Registry에 Push
  2. EC2 인스턴스 생성
    • 모든 곳(0.0.0.0/0)에서 SSH 접속하기 위한 VPC, 서브넷, 인터넷 게이트웨이, 라우트 테이블 설정
  3. CD : 개발자가 직접. 수동
    • EC2 인스턴스에 Docker 설치
    • Docker Registry로부터 Pull
    • Docker Image를 실행

Dockerfile 생성하기

Docker Image의 빌드는 Dockerfile에 정의된 내용을 기반으로 이루어지기 때문에, Dockerfile을 생성해야 한다. 

Dockerfile는 최상위 디렉토리의 바로 아래에 위치시킨다. 

 

#!/bin/bash

vi Dockerfile

 

# Dockerfile에서 다음을 붙여넣기

FROM amazoncorretto:17-alpine # JAR 파일을 구동할 엔진 버전
ARG JAR_FILE=build/libs/*.jar # 생성한 JAR 파일
COPY ${JAR_FILE} app.jar # 호스트의 파일이나 디렉토리를 Docker Image로 복사
ENTRYPOINT ["java","-jar","/app.jar"] # DockerImage 실행 시 default로 실행할 명령어
# ENTRYPOINT에 정의한 명령어들은 docker run에서 덮어쓰기가 불가능하다.

workflow 스크립트 파일 생성하기

github 원격 리포지토리와 연결된 로컬 디렉토리에서 .yml 형식의 workflow 스크립트 파일을 생성해야 한다. 최상위 작업 디렉토리의 바로 아래에 .github/workflows 디렉토리를 생성한 후, 해당 디렉토리 하위에 workflow 스크립트 파일을 생성한다. (스크립트 파일은 여러개 존재할 수 있음)

 

#!/bin/bash

mkdir .github
cd .github
mkdir workflows
cd workflows

vi script.yml # workflow 파일

 

# script.yml 내부에 다음 내용을 붙여넣기

name: Java CI with Gradle

# main 브랜치에 push 혹은 pull request 가 merged 시 동작.
on:
  push:
    branches: [ "main" ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      # (1) 프로그램 빌드 (Java 빌드) 1) Java 및 Docker 빌드를 위한 환경 설정
      - uses: actions/checkout@v3
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      # (1) 프로그램 빌드 (Java 빌드) 2) Java 빌드를 위한 ./gradlew 파일 권한 변경
      - name: Run chmod to make gradlew executable
        run: chmod +x ./gradlew

      # (1) 프로그램 빌드 (Java 빌드) 3) Java 빌드
      - name: Spring Boot Build
        run: ./gradlew clean build

      # (2) Docker 이미지 빌드 1) DockerFile 을 기반으로 Docker Image 빌드
      - name: docker image build
        run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/github-actions-demo .

      # (2) Docker 이미지 빌드 2) Docker Hub 에 Login
      - name: docker login
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_PW }}

      # (2) Docker 이미지 빌드 3) Docker Hub 에 빌드된 이미지 push
      - name: docker Hub push
        run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/github-actions-demo

 

Github Actions 변수 설정하기

민감한 정보들을 workflow에 담으면 안 되므로, 변수로 빼서 사용한다. workflow에서 변수들은 ${{}} 라는 기호를 통해 사용된다. 해당 변수들은 Github Action에서 다음과 같이 설정할 수 있다. 

 

Github Repository > Settings > Actions > Secrets 탭에서 New Repository Secret 버튼 클릭

 

 

Name에 변수명, Secret에 값 넣은 후, Add secret 버튼 클릭

 

위에서 정의한 workflow에는 Docker Hub의 사용자 이름과, 비밀번호를 담고 있으므로 그와 관련된 변수들을 설정해주어야 한다. 먼저 Docker에서 토큰을 생성한 후, 다시 돌아와서 변수들을 설정해주도록 하겠다.

Docker Token 생성하기

Docker 로그인 후 설정 탭에 들어간다.

https://app.docker.com/settings 

 

Acocunt Information의 이름이 DOCKERHUB_USERNAME이 되고, 발급한 토큰의 값이 DOCKERHUB_PW이 된다. 

토큰을 발급받기 위해서는 설정 탭에서 Security > Personal access tokens 메뉴로 들어가면 된다.

 

 Generate new token 버튼 클릭

 

Docker Registry에 Docker Image를 push하고, 이를 pull해서 사용하는 두가지 작업을 할 것이므로, Read & Write으로 권한을 설정하여 토큰을 생성한다. 

 

생성된 토큰 값은 초기 한 번만 볼 수 있으므로 반드시 따로 저장해두어야 한다. (저장하지 않을 경우 삭제 후 재생성해야 하는 번거로움...)

 

다시 Github으로 돌아가서 변수를 설정한다.

 

DOCKERHUB_USERNAME과 DOCKERHUB_PW에 대한 변수들을 설정해주었다. 

추가로, 변수들을 수정할 때도 기존에 설정했던 값을 확인할 수 없다. 그러니 토큰 값을 꼭 따로 저장해두자.

 

원격 리포지토리에 Push

이제 모든 설정들이 완료되었으니, 원격 리포지토리로 push를 하면 된다. 

 

Github Actions 탭에서 CI 자동화가 이루어지는 것을 확인할 수 있다. (커밋 메세지 한글 깨짐은 무시하자...)

진행 중일 때는 노란불이 들어온다.

deploy를 클릭하여 workflow 스크립트가 잘 수행되고 있는지 확인할 수 있다. 실패한 작업들은 에러 메세지를 출력하며 중지된다.

 

 

작업이 성공적으로 완료되면 초록색 체크로 변한다. 

(실패 시 글 마지막 참고)

 

workflow에 작성했던 대로, Docker Image가 빌드되고 Hub에 Push 된 것을 확인할 수 있다. 

 

EC2 인스턴스 생성 후 배포하기

먼저 Aws Console에 접속한 후, 먼저 네비게이션 바 우측의 Region을 Seoul로 바꿔준다. (실습 2에서 CD 자동화 절차 추가를 할 때, workflow 스크립트 파일의 region과 맞춰주기 위해서이다.)

 

VPC 생성

VPC 메뉴에 들어가서 Create VPC로 VPC를 생성한다.

CIDR은 추천하는 주소로 설정해주었다. 

Subnet 생성

Subnets 탭에 들어가서 서브넷을 생성한다. 

 

가용 영역을 Seoul로 설정해주었고, 편의를 위해 하나의 서브넷만 만들 것이므로 VPC의 CIDR과 동일한 CIDR을 가지는 서브넷을 만들었다. 

 

Internet Gateway 생성 및 VPC 연결

 

Internet Gateway 탭에 들어가서 Internet Gateway를 생성한다.

 

생성 후, 아까 만든 VPC에 부착시킨다.

 

Route table 생성

 

Route tables 탭에 들어가서 Route table을 생성한다.

아까 만든 VPC를 선택한다.

 

 

생성된 VPC를 클릭하고 Subnet associations 탭에 들어간다. 그리고 subnet associations를 편집한다.

역시 아까 만들어둔 서브넷을 선택한다.

 

 

Routes 탭에 들어가서 routes를 편집한다. 

 

모든 곳에서 들어오는 요청에 대하여 Internet Gateway로 향할 수 있도록 하고, 아까 만든 Internet Gateway를 선택한다.

 

EC2 인스턴스 생성

 

이제 EC2 인스턴스를 만들기 위해서 EC2 메뉴에 들어간다. 

Launch instances를 클릭하여 인스턴스를 생성한다.

 

OS는 default인 Amazon Linux로 선택하고, t2.micro 인스턴스 유형으로 선택해주었다. 그리고 Network Settings에서 아까 만들어둔 VPC를 선택했다. Public IP를 할당받기 위해 Enable 해준다.

그리고 보안 그룹의 인바운드 규칙을 추가한다. 모든 곳에서 들어오는 요청에 대해 8080 포트를 열어주도록 한다. 그리고 EC2 인스턴스 생성을 완료한다.

 

 

콘솔에서 connect 버튼을 클릭하여 생성한 인스턴스에 접속한 결과 정상적으로 접속된 것을 확인할 수 있다.

 

EC2 인스턴스에 Docker 설치 및 구동

접속한 EC2 인스턴스에서 다음 명령어들을 차례로 입력하여 도커를 설치하고 구동한다. 

sudo yum update -y # 패키지 업데이트
sudo yum install docker -y # 도커 설치
sudo service docker start # 설치 후 꼭 도커 구동

 

EC2 인스턴스에서 Docker Login

docker login # 도커에 로그인

 

변수로 설정해둔 docker의 id와 토큰값을 사용하여 도커에 로그인 한다.

 

 

Docker Image Pull

그리고 나서 도커 이미지를 pull 하려고 하면 다음과 같이 permission denied 오류가 발생한다. 

 

그렇기 때문에 다음과 같이 /var/run/docker.sock 파일의 권한을 먼저 설정해준 뒤, pull을 시도해야 한다. 

 

sudo chmod 666 /var/run/docker.sock # 권한 설정
docker pull 이미지이름 # docker hub에 저장된 docker image 이름을 사용해 pull
docker images # 인스턴스 내에 존재하는 docker image들을 확인

 

 

docker image가 정상적으로 pull 된 것을 확인할 수 있다.

 

Docker Image 실행 = Docker Container 띄우기

 

docker run -p 8080:8080 suhsein/github-actions-demo
# 앞의 포트번호는 host의 포트번호(ec2 인스턴스의 포트번호), 뒤의 포트번호는 docker container의 포트번호

 

컨테이너가 띄워지고 정상적으로 요청을 처리함을 확인할 수 있다.

 

실습 2. Github Actions로 CI + CD

 

이제 workflow 스크립트 파일에 CD 절차를 추가하여 CD도 자동화를 시켜보자. 

 

  1. CI : Github Actions로 자동화
    • jar 파일 Build
    • Docker Login
    • Docker Image Build
    • Docker Registry에 Push
  2. EC2 인스턴스 생성
    • 모든 곳(0.0.0.0/0)에서 SSH 접속하기 위한 VPC, 서브넷, 인터넷 게이트웨이, 라우트 테이블 설정
  3. CD : Github Actions로 자동화
    • EC2 아이디 / 비밀번호 사용하여 접속
    • Github IP에 대한 인바운드 규칙 EC2 보안그룹에 추가 (IAM User Access Key 사용)
    • Docker Registry로부터 Pull
    • Docker Image를 Run (Docker Container 띄우기)

IAM User 생성하기

workflow 내에서 보안 그룹에 Github Actions의 IP에 대한 인바운드 규칙을 추가하기 위해서, IAM User를 생성해야 한다.

 

Aws Console에서 IAM 메뉴에 들어가서 User를 생성한다.

 

EC2 인스턴스의 보안 그룹에 인바운드 규칙을 추가하기 위해서, EC2 접근 권한이 필요하다.

직접 정책 추가를 선택하고, AmazonEC2FullAccess 정책을 추가한다. 

 

생성된 IAM User를 사용하기 위해 Access Key를 생성한다. 

 

 

AWS 외부에서 실행하는 애플리케이션 (Github Actions의 인스턴스)에서 사용할 것이기 때문에, 해당 메뉴를 선택한다.

Access Key가 생성되면 반드시 csv 파일로 따로 저장하여 보관해놓는다. (재발급 가능하지만 번거로우므로)

 

EC2 인스턴스 ID 확인 / PW 설정

Github Actions 인스턴스에서 EC2 인스턴스에 SSH로 접속하는 방법은 여러가지가 있지만 두 가지 방식을 많이 사용한다.

 

  1. 비대칭 키인 .pem 키를 통해 EC2 인스턴스에 SSH 접속 (개발 친화적)
  2. EC2의 아이디 / 비밀번호를 통해 EC2 인스턴스에 SSH 접속 (초보 친화적)

기본적으로 .pem 방식이 사용되며, 아이디 / 비밀번호를 사용하려면 설정 파일에서 수정이 필요하다.

 

EC2 인스턴스에서 다음 명령어들을 통해 ID를 확인하고 PW를 설정한다.

 

whoami # EC2 인스턴스 아이디 확인
sudo passwd ec2-user # ec2-user에 대한 비밀번호 설정

 

EC2 SSH 연결을 위한 패스워드 연결 방식 사용 설정

EC2 인스턴스에서 다음 명령어를 사용해 설정 파일을 열고, PasswordAuthentication no yes 로 수정한 후 저장한다.   

그리고 변경 사항을 적용하기 위해 반드시 restart를 해주어야 한다.

 

sudo vi /etc/ssh/sshd_config # 설정 파일 vi 에디터로 열기
sudo systemctl restart sshd # 변경 사항 적용을 위한 restart

 

Workflow 스크립트 파일에 CD 절차 추가

최상위 작업 디렉토리로 가서 .github/workflows/script.yml 파일을 수정한다. 

기존에는 CI 절차만 존재했지만, CD 절차도 추가해야 한다.

#!/bin/bash

cd .github
cd workflows
vi script.yml

 

# 수정된 script.yml 전문

name: Java CI with Gradle

# main 브랜치에 push 혹은 pull request 가 merged 시 동작.
on:
  push:
    branches: [ "main" ]

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      # (1) 프로그램 빌드 (Java 빌드) 1) Java 및 Docker 빌드를 위한 환경 설정
      - uses: actions/checkout@v3
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      # (1) 프로그램 빌드 (Java 빌드) 2) Java 빌드를 위한 ./gradlew 파일 권한 변경
      - name: Run chmod to make gradlew executable
        run: chmod +x ./gradlew

      # (1) 프로그램 빌드 (Java 빌드) 3) Java 빌드
      - name: Spring Boot Build
        run: ./gradlew clean build

      # (2) Docker 이미지 빌드 1) DockerFile 을 기반으로 Docker Image 빌드
      - name: docker image build
        run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/github-actions-demo .

      # (2) Docker 이미지 빌드 2) Docker Hub 에 Login
      - name: docker login
        uses: docker/login-action@v2
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_PW }}

      # (2) Docker 이미지 빌드 3) Docker Hub 에 빌드된 이미지 push
      - name: docker Hub push
        run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/github-actions-demo

      # (3) CD : Docker 컨테이너 수행 1) Get GitHub IP
      - name: get GitHub IP
        id: ip
        uses: haythem/public-ip@v1.2

      # (3) CD : Docker 컨테이너 수행 2) Configure AWS Credentials - AWS 접근 권한 취득(IAM)
      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v1
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2

      # (3) CD : Docker 컨테이너 수행 3) Add github ip to AWS
      - name: Add GitHub IP to AWS
        run: |
          aws ec2 authorize-security-group-ingress --group-id ${{ secrets.AWS_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32

      # (3) CD : Docker 컨테이너 수행 4) AWS EC2 Server Connect & Docker 명령어 실행
      - name: AWS EC2 Connection
        uses: appleboy/ssh-action@v0.1.6
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          password: ${{ secrets.EC2_PASSWORD }}
          port: ${{ secrets.EC2_SSH_PORT }}
          timeout: 60s
          script: |
            sudo docker stop github-actions-demo
            sudo docker rm github-actions-demo
            sudo docker rmi ${{ secrets.DOCKERHUB_USERNAME }}/github-actions-demo
            #           sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/github-actions-demo
            sudo docker run -it -d -p 8080:8080 --name github-actions-demo ${{ secrets.DOCKERHUB_USERNAME }}/github-actions-demo

      # (3) CD : Docker 컨테이너 수행 5) Remove Github IP from security group
      - name: Remove IP FROM security group
        run: |
          aws ec2 revoke-security-group-ingress --group-id ${{ secrets.AWS_SG_ID }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32

 

스크립트 내 CD 절차 이해하기

  1. Get Github IP
    • Github Actions 스크립트를 실행하는 인스턴스의 IP를 얻어오기
    • EC2 인스턴스 보안 그룹에 Github Actions 인스턴스의 IP에 대한 22번 포트를 열어줘야 접속 가능
  2. Configure AWS Credentials
    • EC2 인스턴스 보안 그룹 수정을 위한 권한 : IAM User의 Access Key 사용  
  3. Add GitHub ip to AWS
    • EC2 인스턴스 보안 그룹에 Github Actions 인스턴스의 IP에 대한 22번 포트 인바운드 규칙을 추가
  4. AWS EC2 Server Connect
    • Github Actions 인스턴스가 EC2 인스턴스에 접속
    • 기존 Docker Container 중지 및 삭제, 기존 Docker Image 삭제
    • Docker Run으로 새로운 Docker Container 띄우기 (새로운 Docker Image 자동 Pull 후 Run)
  5. Remove Github IP from security group
    • EC2 인스턴스에 접근하기 위해서 보안 그룹에 임시로 추가한 인바운드 규칙을 삭제
    • Github Actions 수행 시마다 실행되는 Github Actions 인스턴스는 매번 다르므로, 삭제 필요 

 

Github Actions 변수 추가하기

새로 추가된 CD 절차에서 사용되는 변수들을 추가해주어야 한다. 

 

  • AWS_ACCESS_KEY_ID : IAM User Access Key
  • AWS_SECRET_ACCESS_KEY : IAM User Secret Access Key
  • EC2_HOST : EC2 인스턴스의 Public IP 주소
  • EC2_SSH_PORT : SSH 접근 포트 = 22
  • AWS_SG_ID : EC2 인스턴스의 보안그룹 id
  • EC2_USERNAME : EC2 인스턴스의 id (기본 ec2-user)
  • EC2_PASSWORD : EC2 인스턴스의 pw

 

Github Repository에 Push 

 

Github Repository에 Push를 하면, Github Actions가 수행된다.

CI / CD workflow 스크립트가 정상적으로 수행 완료되었음을 확인할 수 있다. 

(실패 시 글 마지막 참고)

 

컨테이너가 띄워지고 정상적으로 요청을 처리함을 확인할 수 있다.

 

Github Actions 수행 실패 시 의심해볼만한 사항들

  1. EC2 인스턴스의 Region, 보안 그룹의 Region, workflow 스크립트 파일 내의 Region 값이 동일한 지 확인 
  2. workflow 스크립트 파일 내에 들여쓰기 주의
    • .yml 파일은 들여쓰기(indentation)가 잘못되면 오류 발생
    • IntelliJ와 같은 IDE를 사용하여 자동 정렬 후 다시 push 해보기
  3. Github Actions 변수 값들을 다시 설정해보기
    • 오타 주의

 

AWS 프리티어는 Free가 아니므로 실습이 끝나고 필요없는 인스턴스들은 바로바로 Terminate 하여 과금을 방지하자.

728x90