๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
Project/์‹นํ‹”์›€

[์‹นํ‹”์›€] 11/05 ๊ฐœ๋ฐœ์ผ์ง€ ๋ฐฐํฌ : Github Actions ๋ฅผ ํ™œ์šฉํ•œ CI/CD ์ž๋™ํ™” WorkFlow

by ํ•œ33 2024. 11. 10.

๐ŸŒฑ CI/CD Workflow

CICD.yml

name: CI/CD

on:
  pull_request:
    branches: ["main"]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Install JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

      - name: Build with Gradle
        run: |
          chmod +x ./gradlew
          ./gradlew clean build -x test

      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build Docker Image
        run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1 .

      - name: Push Docker Image
        run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1

  deploy:
    needs: build
    runs-on: ubuntu-latest
    steps:
      - name: Deploy to Server
        uses: appleboy/ssh-action@master
        with:
          username: ubuntu
          host: ${{ secrets.SSAKTIUM_SERVER_IP }}
          key: ${{ secrets.EC2_SSH_KEY }}
          script_stop: true
          script: |
            # Pull the latest image from DockerHub
            sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
            
            # Stop and remove the existing container if it exists
            if [ "$(sudo docker ps -q -f name=daegyuhan-ssak)" ]; then
              sudo docker stop daegyuhan-ssak
            fi
            
            if [ "$(sudo docker ps -aq -f status=exited -f name=daegyuhan-ssak)" ]; then
              sudo docker rm daegyuhan-ssak
            fi
            
            # Run the new container
            sudo docker run -d --name daegyuhan-ssak -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1


on:
  pull_request:
    branches: ["main"]

 

๐Ÿ“š main ๋ธŒ๋žœ์น˜์— pull request ๊ฐ€ ์ผ์–ด๋‚  ๋•Œ๋งŒ ์‹คํ–‰


jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3

      - name: Install JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'

 

๐Ÿ“š ubuntu ์ตœ์‹  ๋ฒ„์ „์—์„œ ์‹คํ–‰์‹œํ‚ค๊ณ , JDK 17 ๋ฒ„์ „์œผ๋กœ ์‹คํ–‰ํ•˜๊ฒ ๋‹ค๋Š” ๋ง์ด๋‹ค.

์›ฌ๋งŒํ•˜๋ฉด ๋ฒ„์ „์€ ๋ณธ์ธ์˜ ํ”„๋กœ์ ํŠธ ์‹คํ–‰ ํ™˜๊ฒฝ๊ณผ ๋™์ผํ•˜๊ฒŒ ๊ฐ€์ฃผ๋Š” ๊ฒŒ ์ข‹๋‹ค.


- name: Build with Gradle
  run: |
    chmod +x ./gradlew
    ./gradlew clean build -x test

 

๐Ÿ“š Gradle ํ™˜๊ฒฝ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋˜‘๊ฐ™์ด ๋งž์ถฐ์คฌ๋‹ค.

clean ์„ ํ•œ ๋ฒˆ ํ•˜๊ณ  build ๋ฅผ ํ•ด์„œ ์‹น ๊ฐˆ์•„์ฃผ๊ณ , -x test ์˜ต์…˜์„ ์จ์„œ ์šฐ์„  test ๋ฅผ ๋Œ๋ฆฌ๋Š” ๊ณผ์ •์„ ์ƒ๋žตํ–ˆ๋‹ค.

: ํ”„๋กœ์ ํŠธ ์ง„ํ–‰ ์†๋„๋ฅผ ์œ„ํ•ด์„œ ์šฐ์„  ์ด๋ ‡๊ฒŒ ์ง„ํ–‰


- name: Login to DockerHub
  uses: docker/login-action@v1
  with:
    username: ${{ secrets.DOCKERHUB_USERNAME }}
    password: ${{ secrets.DOCKERHUB_TOKEN }}

- name: Build Docker Image
  run: docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1 .

- name: Push Docker Image
  run: docker push ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1

 

๐Ÿ“š ๋‚ด ํ”„๋กœ์ ํŠธ์˜ jar ํŒŒ์ผ์„ Docker ์ด๋ฏธ์ง€๋กœ ๋งŒ๋“ค์–ด์„œ Docker Hub ์— ์˜ฌ๋ ค๋†“๊ธฐ ์œ„ํ•œ ์ฝ”๋“œ์ด๋‹ค.

Docker Hub ์— ๋กœ๊ทธ์ธ์„ ํ•œ๋‹ค์Œ์— ๊ธฐ์กด์— ์ƒ์„ฑ๋˜์–ด์žˆ๋Š” Repository ์— ๋“ฑ๋ก๋˜์–ด์žˆ๋Š” ์ด๋ฏธ์ง€์™€ ๋ฒ„์ „์— ๋งž์ถฐ์„œ Build, Push ๋ฅผ ์ง„ํ–‰ํ•œ๋‹ค.

DOCKERHUB_TOKEN ์€ Docker Hub ์— ์ ‘์†ํ•ด์„œ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

 

Dockerfile

๋”๋ณด๊ธฐ
FROM amazoncorretto:17-alpine-jdk
EXPOSE 8080
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

 


deploy:
  needs: build
  runs-on: ubuntu-latest
  steps:
    - name: Deploy to Server
      uses: appleboy/ssh-action@master
      with:
        username: ubuntu
        host: ${{ secrets.SSAKTIUM_SERVER_IP }}
        key: ${{ secrets.EC2_SSH_KEY }}
        script_stop: true

 

๐Ÿ“š deploy ๊ณผ์ •์ด๋‹ค. ๋˜‘๊ฐ™์ด ํ™˜๊ฒฝ์€ ubuntu ์ตœ์‹  ๋ฒ„์ „์œผ๋กœ ํ•ด์คฌ๊ณ , ๋‚ด ์ธ์Šคํ„ด์Šค์˜ ์„œ๋ฒ„ IP ์™€ SSH_KEY ๋ฅผ ์ž…๋ ฅํ•จ์œผ๋กœ์จ, ๋‚ด ์ธ์Šคํ„ด์Šค SSH ์— ์ ‘์†์„ ์‹œ์ผฐ๋‹ค.


script: |
  # Pull the latest image from DockerHub
  sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1
  
  # Stop and remove the existing container if it exists
  if [ "$(sudo docker ps -q -f name=daegyuhan-ssak)" ]; then
    sudo docker stop daegyuhan-ssak
  fi
  
  if [ "$(sudo docker ps -aq -f status=exited -f name=daegyuhan-ssak)" ]; then
    sudo docker rm daegyuhan-ssak
  fi
  
  # Run the new container
  sudo docker run -d --name daegyuhan-ssak -p 8080:8080 ${{ secrets.DOCKERHUB_USERNAME }}/ssak:v1

 

๐Ÿ“š ๋งจ ์œ„์—์„œ build ๋‹จ๊ณ„์—์„œ push ํ–ˆ๋˜ ๋‚ด Docker Hub ์˜ ์ด๋ฏธ์ง€๋ฅผ Pull ๋กœ ๋‹น๊ฒจ์˜จ๋‹ค.

 

๐Ÿ“š ๊ธฐ์กด์— ์‹คํ–‰๋˜๊ณ  ์žˆ๋Š” ์ปจํ…Œ์ด๋„ˆ๋ฅผ stop ํ•˜๊ณ , remove ํ•œ๋‹ค.

 

๐Ÿ“š Pull ๋กœ ๋‹น๊ฒจ์˜จ ์ƒˆ ์ด๋ฏธ์ง€๋ฅผ 8080 ํฌํŠธ๋กœ ์ƒˆ๋กœ ์‹คํ–‰์‹œํ‚จ๋‹ค.


์œ„์—์„œ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์„ค์ •์€ github ํŽ˜์ด์ง€์— Secrets and variables ํƒญ์˜ Actions ํƒญ์— ๋“ค์–ด๊ฐ€๋ณด๋ฉด

 

์ด๋ ‡๊ฒŒ ์ถ”๊ฐ€๋ฅผ ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.