2023. 8. 19. 14:41ㆍServer
Github Action 배포 사용해보기(Spring Boot, React, Ubuntu, Docker)
Github Action를 사용해 보았습니다.
많은 블로그에서는 AWS에 대해 배포하는 방법이 있는데 이번 포스팅에서는 순수하게 파일을 전송하는 방법, Docker Hub로 Push하는 방법을 포스팅하겠습니다.
자세한 코드는 아래 링크를 통해 확인해 주세요. 해당 포스팅은 코드에 대한 설명입니다.
Github Action에 적용된 부분
1. Spring Boot, React 변경이 된 부분만 반영
2. 파일을 Server로 직접 전송
2.1 파일을 Docker Hub로 push
3. Private Repository에서 테스트
feat. Oracle Cloud(Ubuntu 22.04) 배포
Github Repository 구조
├─.github
│ └─workflows
├─react-action
├─spring-action
└─README.md
# react-action에는 React(Front)가 있습니다.
# spring-action에는 Spring Boot(backend)가 있습니다.
* Spring Boot(.jar)
* JDK 17, Gradle
* React v18
# Github Action 코드에 이상이 있는지 검사하는 사이트
Github Action Checker : https://rhysd.github.io/actionlint
# Github Action Docs
https://docs.github.com/ko/actions
< 직접 전송하는 Github Action Code 보러가기>
< Docker Hub로 Push하는 Github Action Code 보러가기>
Github Action 코드 구조
jobs:
changes:
runs-on: ubuntu-latest
steps:
...
build:
runs-on: ubuntu-latest
steps:
...
deploy:
runs-on: ubuntu-latest
steps:
...
Github Action 은 job안에 여러개의 step이 존재할 수 있습니다.
job의 이름은 사용자가 정의할 수 있습니다.
on:
push:
paths:
- 'spring-action/'
- 'react-action/'
branches: [ "develop" ]
pull_request:
branches: [ "develop" ]
push 혹은 pull_request에 대한 이벤트가 일어났을 때 아래 job이 실행됩니다.
path는 프로젝트 구조가 폴더 안에 실제 코드가 있다면 위 처럼 폴더를 적어 주어야 합니다.
(추가) env 설정은 전역적으로 사용이 가능합니다.
env:
working-directory-be: ./spring-action
working-directory-fe: ./react-action
job안에 env설정은 다른 job에서는 사용할 수 없습니다.
경로같은 경우 전역적으로 사용할 수 있도록 job 밖에 빼서 선언이 가능합니다.
파일을 Server로 직접 전송 하는 방법
changes job에서는 변경을 감지합니다.
changes:
runs-on: ubuntu-latest
outputs:
backend: ${{ steps.filter.outputs.backend }}
frontend: ${{ steps.filter.outputs.frontend }}
steps:
- name: checkout
uses: actions/checkout@v3
with:
ref: develop
repository: PARKJINHOH/github-action
token: ${{ secrets.TOKEN_GITHUB }}
- name : Run Paths Filter
uses: dorny/paths-filter@v2
id: filter
with:
filters: |
backend:
- 'spring-action/**'
frontend:
- 'react-action/**'
- runs-on은 실행 환경을 지정합니다. ubuntu-20.04 , windows-2022 , macos-13 등이 있으며 고정 버전을 사용할 수 있습니다. runs-on 설명서
- actions/checkout@v3 에서는 repository를 checkout합니다. 아래 변경을 감지하기 위해 필요합니다.
- token은 해당 repository에 접근하기 위해 사용되었습니다. Private Repository에서는 필요했습니다.
- dorny/paths-filter@v2 에서는 with/filters에 위치한 경로에 변경을 감지합니다.
- outputs은 변수입니다. 아래 코드에서는 backend, frontend 2개의 변수가 선언되어 있으며 steps.filter.outputs.backend(front)에 대한 value값을 가지고 있습니다.
- dorny/paths-filter에서는 변경이 있으면 true없으면false를 반환합니다.
back Job에서는 gradle build를 담당합니다.
backend:
needs: changes
if: ${{ needs.changes.outputs.backend == 'true' }}
runs-on: ubuntu-latest
env:
working-directory: ./spring-action
steps:
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
- name: checkout
uses: actions/checkout@v3
with:
ref: develop
repository: PARKJINHOH/github-action
token: ${{ secrets.TOKEN_GITHUB }}
- name: Cache Gradle
uses: actions/cache@v3
with:
path: |
~/.gradle/caches
~/.gradle/wrapper
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
restore-keys: |
${{ runner.os }}-gradle-
- name: Gradle wrapper & build
working-directory: ${{ env.working-directory }}
run: |
chmod +x ./gradlew
./gradlew clean bootJar
ls ./build/libs
- name: pwd
run: ls -al .
- name: Upload artifact
uses: actions/upload-artifact@v3
with:
name: jar-artifact
path: ${{ env.working-directory }}/build/libs #Full Path
- if: ${{ needs.changes.outputs.backend == 'true' }} 위에서 선언했던 변수가 true라면 아래 가 실행됩니다.
- backend: - 'spring-action/**'에 변경이 없다면 해당 job의 steps는 실행되지 않습니다.
- env: working-directory: ./spring-action env설정입니다. backend의 경로를 입력했습니다.
- actions/setup-java@v3 build에 필요한 JDK를 설정합니다.
- actions/checkout@v3 에서는 repository를 checkout합니다. gradle build하기 위해 필요합니다.
- actions/cache@v3 gradle build를 매번 할 시 시간이 매우 오래 걸리기 때문에 cache를 통해 좀 더 시간과 자원을 절약할 수 있습니다.
- run에서는 script를 실행할 수 있습니다. ./gradlew clean bootJar를 통해 clean후 jar파일을 생성합니다.
- actions/upload-artifact@v3 job간에는 파일을 이동할 수 없습니다. 워크플로우내에서 생성된 파일이나 데이터를 저장하고 다른 워크플로우에서 공유하기 위해 사용됩니다. 여기서는 build된 jar파일을 다른 job에 넘겨서 원격 서버에 전송하기위해 추가되었습니다.
- path는 Full Path이며, 경로를 자세히 모르겠다면 -name pwd로 현재 경로를 확인할 수 있습니다.
- name은 중요합니다. download할 때 해당 name으로 찾아서 download합니다.
backend-upload에서는 서버로 파일을 전송합니다.
backend-upload:
needs: backend
runs-on: ubuntu-latest
steps:
- name: Download artifact
uses: actions/download-artifact@v3
with:
name: jar-artifact
#- name: pwd
# run: ls -al .
- name: copy file via ssh password
uses: appleboy/scp-action@v0.1.4
with:
host: ${{ secrets.SSH_IP }}
username: ubuntu
password: ${{ secrets.SSH_PASSWORD }}
port: 22
key: ${{ secrets.SSH_RSA }}
source: "*.jar"
target: ${{ secrets.DIST_PATH_BACKEND }}/staging
- actions/download-artifact@v3에서는 actions/upload-artifact@v3에서 업로드한 파일을 다운로드 합니다.
- 파일을 다운로드 할 때는 name으로 찾습니다. upload의 name과 동일해야 합니다.
- appleboy/scp-action은 ubuntu의 scp를 이용해 파일을 전송합니다.
- SSH_IP는 도메인 혹은 IP도 가능합니다.
- key가 필요한 server일 경우 secrets에 등록해서 사용할 수 있습니다.
- source는 전송 대상입니다. *.jar일 경우 jar파일 모두, "./**"일 경우 현재 폴더 전체 파일 입니다.
- pwd를 통해 현재 위치를 확인하세요.
- target은 서버에서 받을 경로 입니다.
(Frontend) ssh 접속
steps:
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_IP }}
username: ubuntu
password: ${{ secrets.SSH_PASSWORD }}
port: 22
key: ${{ secrets.SSH_RSA }}
script: |
cd ${{ secrets.DIST_PATH_FRONT }}
#./2.deploy.sh
※ ssh-action와 scp-action은 다릅니다. 철자에 주의해주세요.
- appleboy/ssh-action을 통해 ssh에 접속할 수 있습니다.
- script: |를 통해 서버에 있는 sh를 실행할 수도 있으며 sh를 아래 코드로 만들어 실행할 수 있습니다.
Frontend는 Backend와 구조가 비슷합니다.
파일을 Docker Hub로 push하는 방법
Docker Hub로 Push하는 방법은build 부분까지는 동일하지만 job과 step구조가 조금 다릅니다.
Docker Hub Login
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }} # https://docs.docker.com/docker-hub/access-tokens
- docker/login-action을 통해 docker에 login합니다.
- password는 token을 생성해서 사용해도 되고, 실제 password를 사용해도 됩니다.
Docker Build & Docker push
- name: web docker build and push
working-directory: ${{ env.working-directory }}
run: |
pwd
ls -al .
# The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested 에러시 아래 사용.
# docker build -t ${{ secrets.DOCKER_REPO }}/gitaction-be .
docker build --platform linux/arm64 -t ${{ secrets.DOCKER_REPO }}/gitaction-be .
docker push ${{ secrets.DOCKER_REPO }}/gitaction-be
저는 여기서 경로 때문에 조금 헷갈렸는데요.
pwd와 ls -al . 로 경로와 파일을 보면서 하면 좀 더 쉽습니다.
docker build를 하며 자신의 docker repository/이미지 이름으로 build합니다.
만약 배포할 서버가 arm64를 사용하면 --platform명령어를 사용해 build 합니다.
docker push하면 끝
[배포 서버] Docker pull
backend-docker:
needs: backend
runs-on: ubuntu-latest
env:
working-directory: ./spring-action
steps:
- name: docker pull
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SSH_IP }}
username: ubuntu
password: ${{ secrets.SSH_PASSWORD }}
port: 22
key: ${{ secrets.SSH_RSA }}
script: |
sudo docker pull ${{ secrets.DOCKER_REPO }}/gitaction-be
ssh-action으로 서버에 접속한 뒤, script를 통해 Docker hub에 push했던 image를 pull 합니다.
이후 재기동 및 배포관련 script를 작성하면 됩니다.
만약 서버에 실행하는 .sh파일이 있다면 `cd 경로` `./start.sh`를 적어주면 됩니다.
'Server' 카테고리의 다른 글
[기록] docker-compose가 여러개 있을 때 쉘 스크립트 작성 (0) | 2024.03.30 |
---|---|
Docker 미사용 이미지 모두 삭제 쉘스크립트(Tag가 None인 이미지) (0) | 2024.03.30 |
Oracle Cloud 방화벽 설정(Ubuntu 22.04) (0) | 2023.08.14 |
Ubuntu 초기 설정 (feat.Ubuntu 22.04, Oracle Cloud) (0) | 2023.08.12 |
[Docker] Window에서 Docker Desktop 설치 후 'Docker Desktop requires a newer WSL kernel version.' 문제 해결 (0) | 2023.05.06 |