본문 바로가기

[배포]

[GitHub Actions] GitHub Actions 명령어

GitHub Actions의 YAML 파일에서 자주 사용되는 기본적인 명령어

명령어 설명
name: GitHub Actions의 워크플로우 이름 설정
on: 워크플로우 실행 조건 설정 (ex: push, pull_request, schedule 등)
jobs: 실행할 작업을 정의
runs-on: 실행 환경 지정 (ex: ubuntu-latest)
steps: 실행할 단계 정의
uses: GitHub Marketplace의 액션을 사용
run: 직접 명령어 실행 (ex: ./gradlew build)
env: 환경 변수 설정
with: 액션에 전달할 인자 설정
secrets: GitHub Secrets에서 보안 정보 가져오기

 

1. Checkout 코드 가져오기(GitHub 리포지토리의 코드를 가져오는 액션)

- name: Checkout repository
  uses: actions/checkout@v4
  • GitHub Actions에서 CI/CD를 수행하려면 먼저 저장소의 코드를 가져와야 한다.
  • GitHub Actions 실행 시 기본적으로 코드가 포함되지 않기 때문에 필요함.
  • actions/checkout를 사용하면 GitHub 저장소를 로컬 환경에 복제할 수 있다.

2. JDK 설정(Java 버전을 설정하고 Gradle/Maven을 실행할 수 있도록 환경을 구성하는 액션)

- name: Set up JDK 17
  uses: actions/setup-java@v3
  with:
    distribution: 'temurin'  # OpenJDK 배포판 (AdoptOpenJDK 기반)
    java-version: '17'       # JDK 버전
  • 스프링 부트 프로젝트는 JDK 환경이 필요하므로, actions/setup-java를 사용해 JDK를 설정할 수 있다.
  • CI/CD에서 JDK 버전 설정이 중요함!

📌 Java 배포판 종류

  1. temurin (Adoptium): 가장 많이 사용됨
  2. zulu (Azul)
  3. corretto (AWS)
3. Gradle 빌드 & 테스트
- name: Setup Gradle
  uses: gradle/gradle-build-action@v2

- name: Build with Gradle
  run: ./gradlew build

✅ 테스트 실행까지 포함
- name: Run tests
  run: ./gradlew test
  • 스프링 부트 프로젝트는 Gradle로 빌드할 때, gradle/gradle-build-action을 활용하면 빌드 캐싱을 최적화할 수 있다.
  • Gradle을 사용하여 빌드 및 테스트 실행

📌 --no-daemon 옵션을 추가하여 CI/CD에서 불필요한 Gradle 데몬 실행 방지

- name: Build with Gradle
  run: ./gradlew build --no-daemon

 

📌 Gradle 캐싱을 활용하면 속도를 높일 수 있음

- name: Cache Gradle packages
  uses: actions/cache@v3
  with:
    path: ~/.gradle/caches
    key: gradle-${{ runner.os }}-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
    restore-keys: |
      gradle-${{ runner.os }}-

 

4. Docker 빌드 & 푸시

- name: Build and push Docker image
  uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: my-docker-repo/my-app:latest
  • Docker를 사용해서 컨테이너화된 환경을 배포할 계획이라면 docker/build-push-action를 활용할 수 있다.

5. AWS Credentials 설정

- name: Configure AWS credentials
  uses: aws-actions/configure-aws-credentials@v2
  with:
    aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
    aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    aws-region: ap-northeast-2
  • AWS 서비스 (EC2, S3, CodeDeploy, Lambda 등)와 연동하려면 AWS 인증 정보가 필요함.

6. 애플리케이션 배포 (✅ EC2로 배포하는 경우)

- name: Deploy to EC2
  uses: appleboy/scp-action@v0.1.7
  with:
    host: ${{ secrets.EC2_HOST }}
    username: ${{ secrets.EC2_USER }}
    key: ${{ secrets.EC2_SSH_KEY }}
    source: "build/libs/myapp.jar"
    target: "/home/ubuntu/myapp/"
  • AWS EC2에 배포하려면 scp이나 GitHub Actions의 rsync를 사용해서 애플리케이션을 전송할 수 있다.

7. S3에 JAR 파일 업로드

- name: Upload to S3
  run: aws s3 cp build/libs/my-app.jar s3://my-bucket-name/
  • 빌드된 JAR 파일을 AWS S3에 업로드하여 CodeDeploy에서 사용할 수 있도록 설정

🤔 S3에 저장하는 이유?

  • 배포 파일 (JAR, ZIP 등) 저장:
    • 스프링 부트 프로젝트를 빌드하면 JAR 파일이 생성되는데, 이걸 EC2로 직접 보내는 대신 S3에 저장할 수 있다.
  • CI/CD에서 안정적인 파일 저장소 역할:
    • 여러 서버에서 동일한 배포 파일을 가져가야 할 때 유용.
  • 백업 및 이력 관리:
    • 최신 버전의 애플리케이션 파일을 관리하기 쉬움.

8. AWS CodeDeploy 배포

- name: Deploy to EC2 via CodeDeploy
  run: aws deploy create-deployment \
    --application-name my-app \
    --deployment-group-name my-deployment-group \
    --s3-location bucket=my-bucket-name,key=my-app.jar,bundleType=zip
  • S3에 업로드한 JAR 파일을 EC2에 배포하는 과정

9. Slack 알림 보내기

- name: Send Slack Notification
  uses: rtCamp/action-slack-notify@v2
  with:
    webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
    channel: '#ci-cd'
    color: 'good'
    message: '배포 완료 ✅'
  • CI/CD의 빌드 성공/실패를 Slack으로 알림 보낼 수 있음.

✅ AWS S3, EC2, CodeDeploy, Secrets Manager를 활용한 Spring Boot 배포 예제

 

📌 배포 흐름

  1. 개발자가 GitHub에 코드를 푸시 (git push)
  2. GitHub Actions가 실행됨 (CI/CD)
  3. Gradle로 빌드하고 실행 가능한 JAR 파일 생성
  4. S3에 JAR 파일을 업로드
  5. AWS CodeDeploy가 EC2에 배포
  6. EC2에서 Spring Boot 애플리케이션 실행

📌 GitHub Actions 스크립트 (.github/workflows/deploy.yml)

name: Deploy Spring Boot to AWS

on:
  push:
    branches:
      - main  # main 브랜치에 push될 때 실행

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      # 1️⃣ GitHub에서 코드 가져오기
      - name: Checkout Repository
        uses: actions/checkout@v4

      # 2️⃣ Java 17 환경 설정
      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          distribution: 'temurin'
          java-version: '17'

      # 3️⃣ Gradle 빌드 (JAR 파일 생성)
      - name: Build with Gradle
        run: ./gradlew build --no-daemon

      # 4️⃣ AWS CLI 설정 (S3, CodeDeploy 사용을 위해 필요)
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-2  # 서울 리전

      # 5️⃣ S3에 JAR 파일 업로드
      - name: Upload to S3
        run: |
          aws s3 cp build/libs/my-app-0.0.1-SNAPSHOT.jar s3://my-deploy-bucket/my-app.jar

      # 6️⃣ CodeDeploy 트리거 (배포 시작)
      - name: Deploy to EC2 via CodeDeploy
        run: |
          aws deploy create-deployment \
            --application-name my-app \
            --deployment-group-name my-deploy-group \
            --s3-location bucket=my-deploy-bucket,key=my-app.jar,bundleType=zip

 

📌 appspec.yml (EC2에 배포될 때 실행할 스크립트)

version: 0.0
os: linux
files:
  - source: /
    destination: /home/ubuntu/app  # EC2에서 JAR 파일이 저장될 위치
hooks:
  ApplicationStart:
    - location: scripts/start.sh
      timeout: 60
      runas: ubuntu
  • CodeDeploy는 appspec.yml 파일을 읽고 배포 과정에서 실행할 명령어를 지정할 수 있다.
  • 이 파일을 프로젝트 루트에 추가하고, S3에 업로드한 후 EC2에 배포할 때 사용

📌 start.sh (EC2에서 Spring Boot 실행)

#!/bin/bash

# 기존 프로세스 종료
echo "Stopping existing application..."
pkill -f 'java -jar' || true

# AWS Secrets Manager에서 환경 변수 로드
export $(aws secretsmanager get-secret-value --secret-id my-secret | jq -r '.SecretString | fromjson | to_entries | map("\(.key)=\(.value)") | .[]')

# Spring Boot 애플리케이션 실행
echo "Starting application..."
nohup java -jar /home/ubuntu/app/my-app.jar > /home/ubuntu/app/app.log 2>&1 &
  • 이제 EC2에서 Spring Boot 애플리케이션을 실행하는 스크립트를 만들어야 한다.
  • 이 파일은 scripts/start.sh 위치에 저장한다.

설명

  • 기존 실행 중인 애플리케이션을 종료하고 새로운 버전을 실행
  • AWS Secrets Manager에서 환경 변수 로드
  • 백그라운드에서 my-app.jar 실행

Spring Boot application.yml에 적용

spring:
  datasource:
    url: jdbc:mysql://my-db-instance.amazonaws.com:3306/mydb
    username: admin
    password: ${DB_PASSWORD}  # AWS Secrets Manager에서 가져온 값
  jwt:
    secret: ${JWT_SECRET_KEY}
  • Secrets Manager에서 불러온 값을 Spring Boot에서 사용할 수 있도록 설정해야 한다.

✔️ Secrets Manager에서 데이터 저장

aws secretsmanager create-secret --name my-secret --secret-string '{"DB_PASSWORD":"my-db-password"}'
  • Secrets Manager를 사용하면 데이터베이스 비밀번호, API 키 등 민감한 정보를 보호할 수 있다.
  • 위 start.sh에서는 Secrets Manager에서 환경 변수를 불러와 사용한다.

📌 이 명령어는 AWS CLI에서 직접 실행해야 함!

  • 한 번만 실행하면 됨 (배포할 때마다 실행할 필요 없음)
  • AWS 웹 콘솔에서도 Secrets Manager > 새 보안 값 생성에서 직접 입력 가능
  • 보통 로컬 개발 환경에서 실행하거나, EC2에서 한 번만 실행

✔️ Secrets Manager에서 값 불러오기

aws secretsmanager get-secret-value --secret-id my-secret

 

📌이 명령어는 start.sh에 추가해야 함!

  • EC2에서 실행될 때마다 Secrets Manager에서 값을 가져와 환경 변수로 설정
  • Spring Boot가 실행될 때 DB 비밀번호나 JWT 키를 환경 변수에서 읽도록 함
  • JSON 형식으로 저장된 Secrets 값을 DB_PASSWORD=xxx 형식으로 변환해서 로드