Post

[CI_CD] (Github Actions) 서버 밖에서 빌드를 수행하고 빌드된 파일만 전달받는 CI/CD 구축 방법

🗿 일반 프로젝트에서 많이 쓰는 CI/CD 구축 방법

🗿 Github Actions 안에서 빌드와 테스트를 진행하고 빌드된 파일을 전달한다

AWS EC2에서 빌드하는 것아 아닌 Github Actions에서 빌드함으로써
서버 (EC2) 의 성능에 영향을 거의 주지 않는다.

다만, 무중단 배포 구현이나 여러 EC2 인스턴스에 배포해야하는 상황에서는
Github Actions에서 스크립트를 작성하는 게 꽤 복잡하다.

🎯 현업에서 초기 서비스를 구축할 때 많이 활용 (오버 엔지니어링 x)

🍜 EC2 內 필요한 작업
해당 방식으로 구축하려면 EC2 내에 JDK만 설치하면 된다.
sudo apt update
sudo apt install openjdk-11-jdk -y
java -version

⚔️ Github Actions 內 사용할 라이브러리

⚔️ Repository에 올린 파일 불러오기, JDK 설치, 파일 전송하기, ssh로 원격 접속
🎮 actions/checkout@v4
Github Repository에 올린 파일들을 불러올 때 사용
1
2
3
4
5
steps:
  - name: Repository에 올린 파일 불러오기
    uses: actions/checkout@v4
    with: # (선택) 원하는 폴더만 불러오고 싶은 경우 사용
      sparse-checkout: "backend" # 정확한 폴더 경로 지정, 와일드카드 사용 금지
🎮 actions/setup-java@v4
JDK 설치 시 사용
1
2
3
4
5
6
steps:
  - name: JDK 설치
    uses: actions/setup-java@v4
    with:
      distribution: temurin # 브랜드 선택
      java-version: 11 # 버전 명시
🎮 appleboy/scp-action@v0.1.7
SCP(Secure Copy)는 ssh 기반으로 파일을 전송 시 사용 (Github Actions에서 빌드된 파일 -> EC2)
1
2
3
4
5
6
7
8
9
steps:
  - name: SCP로 EC2에 빌드된 파일 전송
    uses: appleboy/scp-action@v0.1.7
    with:
      host: $
      username: $
      key: $
      source: project.jar
      target: /home/ubuntu/test-server/tobe # EC2의 어떤 폴더에 전송된 파일을 저장할 것인가
🎮 appleboy/ssh-action@v1.0.3
ssh를 통해 원격접속 시 사용 (EC2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
steps:
  - name: ssh로 EC2에 원격 접속
    uses: appleboy/ssh-action@v1.0.3
    with:
      host: $
      username: $
      key: $
      script_stop: true
      script: | # 원격 접속해서 사용할 명령어
        rm -rf /home/ubuntu/test-server/current
        mkdir /home/ubuntu/test-server/current
        mv /home/ubuntu/test-server/tobe/project.jar /home/ubuntu/test-server/current/project.jar
        cd /home/ubuntu/test-server/current
        sudo fuser -k -n tcp 8080 || true
        nohup java -jar project.jar > ./output.log 2>&1 &
        rm -rf /home/ubuntu/test-server/tobe

🔌 실습: deploy.yml

🔌 📂.github > 📂workflows > deploy.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
name: Deploy Application To EC2

on:
  push:
    branches:
      - main

jobs:
  Deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Github Repository에 업로드한 파일 불러오기
        uses: actions/checkout@v4
        with:
          sparse-checkout: "backend"

      - name: 불러온 파일 확인 및 위치 파악
        run: |
          ls
          pwd

      - name: JDK 11 ver. 설치
        uses: actions/setup-java@v4
        with:
          distribution: temurin
          java-version: 11

      - name: 설치한 Java ver. 확인
        run: java -version

      - name: application.yml 파일 생성
        run: |
          cd backend/src/main
          mkdir resources
          cd resources
          pwd
          echo "${{ secrets.APPLICATION_PROPERTIES_AWS }}" > application-aws.yml
          echo "${{ secrets.APPLICATION_PROPERTIES_JWT }}" > application-jwt.yml
          echo "${{ secrets.APPLICATION_PROPERTIES }}" > application.yml

      - name: 테스트 및 빌드
        run: |
          cd backend
          chmod +x gradlew
          ./gradlew clean build

      - name: 빌드된 파일명 변경
        run: |
          cd backend
          mv ./build/libs/*SNAPSHOT.jar ./project.jar

      - name: SCP로 EC2에 빌드된 파일 전송
        uses: appleboy/scp-action@v0.1.7
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_PRIVATE_KEY }}
          source: backend/project.jar
          target: /home/ubuntu/test-server/tobe

      - name: ssh로 EC2에 접속
        uses: appleboy/ssh-action@v1.0.3
        with:
          host: ${{ secrets.EC2_HOST }}
          username: ${{ secrets.EC2_USERNAME }}
          key: ${{ secrets.EC2_PRIVATE_KEY }}
          script_stop: true
          script: |
            rm -rf /home/ubuntu/test-server/current
            mkdir /home/ubuntu/test-server/current
            mv /home/ubuntu/test-server/tobe/backend/project.jar /home/ubuntu/test-server/current/project.jar
            cd /home/ubuntu/test-server/current
            sudo fuser -k -n tcp 8010 || true
            nohup java -jar project.jar > ./output.log 2>&1 &
            rm -rf /home/ubuntu/test-server/tobe

🐃 내가 헤맨 부분

🐃 내가 헤맨 부분 - 워크플로우 파일 위치
Github Repository에 올린 파일이 다음과 같이 폴더로 하나의 depth가 더 있다.
📂 frontend
📂 backend
이 내부에 관련 소스들이 올라가 있는데, 이를 간과하고 .github > workflows > deploy.yml 파일을
backend 폴더 內 루트에 생성했는데, 이러면 Github Actions가 인식을 못한다.

📂 frontend
📂 backend
📂 .github
이런 식으로 Repository Root에 워크플로우 파일을 경로에 맞게 작성해줘야 Github Actions에서 인식한다.
🐃 내가 헤맨 부분 - 각 step마다 독립된 셸 세션에서 수행
워크플로우 파일에서 sparse-checkout으로 원하는 폴더만 불러왔을 때(ex. backend)
해당 폴더 내부로 이동해준 뒤 작업해야 한다.
' 불러온 파일 확인 및 위치 파악 '하는 cd backend 명령어로 이동해주면
후속 stepbackend 폴더 내부에서 작업이 진행될 줄 알았으나
step은 독립된 셸 세션에서 수행되므로, 서로 영향을 받지 않기 때문에step에서 폴더 내부로 이동하는 명령어가 필요하다.
🐃 내가 헤맨 부분 - 워크플로우 파일와 EC2 內 JDK 설치
워크플로우 파일 內 step에서 JDK를 설치하는 것은 Github 內 임시 가상 서버에서 빌드하기 위해서이고,
EC2 內 명령어로 JDK를 설치하는 이유는 전달받은 빌드된 파일을 실행시키기 위해서이다.
처음에는 워크플로우 파일에서 설치한 JDK를 왜 EC2에 또 설치하는지 헷갈렸는데, 일단은 JDK를 설치하는 컴퓨터가 다르고
각 컴퓨터 (Github 內 임시 가상 서버, EC2) 에서 JDK가 필요하기 때문이다.
This post is licensed under CC BY 4.0 by the author.