Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
7ea18b4
feat: github secrets 관련 script 파일 생성
zhy2on Jan 22, 2025
15ac9b3
chore: gitignore 추가
zhy2on Jan 22, 2025
09588f9
feat: docker 관련 파일 추가
zhy2on Jan 22, 2025
be79b3e
feat: github actions 설정
zhy2on Jan 22, 2025
13c48cf
fix: ssh key 유형 변경
zhy2on Jan 22, 2025
9bac21a
refactor: docker pruning 단계 개선
zhy2on Jan 22, 2025
2fae401
chore: 도커 환경에 맞게 데이터베이스 URL 수정
zhy2on Jan 22, 2025
4213ea7
fix: ssh key 유형 변경
zhy2on Jan 22, 2025
0135c3b
feat: 서브모듈의 develop 브랜치 자동 체크아웃 설정 추가
zhy2on Jan 22, 2025
c48da51
fix: 서브모듈 경로 수정
zhy2on Jan 22, 2025
610a97b
fix: 서브모듈 develop 브랜치 체크아웃 오류 수정
zhy2on Jan 22, 2025
4febbc8
fix: 서브모듈 develop 브랜치 체크아웃 방식 수정
zhy2on Jan 22, 2025
0b79732
chore: 불필요한 매크로 이미지 파일 삭제
zhy2on Jan 23, 2025
6e8ec8d
refactor: 백엔드 DB 설정 환경변수화
zhy2on Jan 23, 2025
d22d245
fix: MariaDB 컨테이너 연결 문제 해결
zhy2on Jan 23, 2025
684d32e
feat: dev용 sql 추가
zhy2on Jan 23, 2025
a62105a
feat: config의 dev sql을 복사하도록 설정
zhy2on Jan 23, 2025
46fc0a0
chore: 배포 속도 개선을 위한 GitHub Actions 최적화
zhy2on Jan 23, 2025
7412c3d
refactor: 운영 환경에 맞춘 docker-compose 설정 최적화
zhy2on Jan 23, 2025
312ceeb
fix: GitHub Container Registry 권한 문제 해결을 위한 permissions 추가
zhy2on Jan 23, 2025
451a460
refactor: Docker Compose 설정 파일 분리
zhy2on Jan 23, 2025
e1ccd64
fix: GitHub Actions 토큰 설정 변경
zhy2on Jan 23, 2025
19bf1fe
fix: GitHub Actions Container Registry 인증 설정 변경
zhy2on Jan 23, 2025
eb8fce1
fix: 서버의 Container Registry 인증 추가
zhy2on Jan 23, 2025
7cabde3
fix: 백엔드 이미지 멀티 플랫폼 지원 추가
zhy2on Jan 23, 2025
ede14b7
fix: Github Actions workflow에 project name 옵션 추가
zhy2on Jan 23, 2025
c826c15
fix: docker-compose 파일 통합
zhy2on Jan 23, 2025
f140f44
chore: dev-data.sql 업데이트
zhy2on Jan 23, 2025
bfa9807
fix: 서비스 시작 순서를 위한 컨테이너 의존성 설정 추가
zhy2on Jan 23, 2025
2ddd314
chore: docker-compose 파일 잘못 적혀있던 것 수정
zhy2on Jan 23, 2025
35434bb
chore: unused import문 제거 & 배포 정상 작동 테스트
zhy2on Jan 23, 2025
f649f19
Merge branch 'docker-server' of https://github.com/tutorial-sejong/cr…
zhy2on Jan 23, 2025
9bd810f
feat: Docker 빌드 최적화를 위한 .dockerignore 추가
zhy2on Jan 23, 2025
8b98a40
feat: GitHub Actions 배포 워크플로우 최적화
zhy2on Jan 23, 2025
128d3ce
fix: GitHub Actions 빌드 오류 수정
zhy2on Jan 23, 2025
0baa77b
chore: github actions 성능 개선 테스트
zhy2on Jan 23, 2025
303e3f3
fix: 불필요한 Docker 멀티플랫폼 빌드 제거
zhy2on Jan 23, 2025
068ee99
chore: 배포 테스트용 수정
zhy2on Jan 23, 2025
a53d33c
Merge branch 'docker-server' of https://github.com/tutorial-sejong/cr…
zhy2on Jan 23, 2025
d06f84b
chore: 마지막 github actions 테스트
zhy2on Jan 23, 2025
f714474
chore: ssh key 알고리즘 변경
zhy2on Jan 25, 2025
cbe2f4a
chore: GitHub Actions 대상 브랜치를 develop으로 변경
zhy2on Jan 25, 2025
99b2e2a
Merge branch 'develop' of https://github.com/tutorial-sejong/cr-backe…
zhy2on Jan 25, 2025
fbc6dac
fix: JWT 토큰 검증 시 무한 재귀 제거
zhy2on Jan 25, 2025
31c720e
fix: 백엔드 배포 시 이미지 재빌드 옵션 추가
zhy2on Jan 25, 2025
bb6f620
Merge branch 'TS-59/feat/docker-server-setup' of https://github.com/t…
zhy2on Jan 25, 2025
547ca7f
refactor: ARM64 아키텍처 지원을 위한 이미지 변경
zhy2on Jan 25, 2025
ead6157
fix: 컨테이너 배포 파이프라인 최적화
zhy2on Jan 25, 2025
986f44b
chore: github actions 테스트
zhy2on Jan 25, 2025
b57be0d
fix: cleanup 로직 수정
zhy2on Jan 25, 2025
66ccceb
Merge branch 'TS-59/feat/docker-server-setup' of https://github.com/t…
zhy2on Jan 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
146 changes: 95 additions & 51 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -1,70 +1,114 @@
name: Deploy Spring Boot Project
name: Deploy to Development Server

on:
push:
branches: [develop]
pull_request:
branches:
- main
branches: [develop]

jobs:
build-and-deploy:
permissions:
contents: read
packages: write
runs-on: ubuntu-latest
environment: development

steps:
- name: Checkout repository
uses: actions/checkout@v2
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.GH_TOKEN }}

- name: Set up JDK 17
uses: actions/setup-java@v2
with:
distribution: 'adopt'
java-version: '17'

- name: Cache Gradle packages
uses: actions/cache@v2
token: ${{ secrets.GH_PAT }}

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

- name: Grant execute permission for gradlew
run: chmod +x gradlew

# --- (1) build 시 테스트 무시: -x test ---
- name: Build with Gradle
run: ./gradlew build -x test

- name: Install sshpass
run: sudo apt-get install -y sshpass
restore-keys: ${{ runner.os }}-gradle-

# 빌드 산출물(JAR 파일)을 원격 서버로 복사
- name: Copy build artifacts
# 서브모듈 설정
- name: Setup submodule
run: |
JAR_FILE=$(ls build/libs/*.jar | sort -r | head -n 1)
echo "JAR_FILE=$JAR_FILE" >> $GITHUB_ENV
sshpass -p ${{ secrets.SSH_PASSWORD }} scp -o StrictHostKeyChecking=no -r "$JAR_FILE" ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/home/anhye0n/web/tutorial_sejong/backend/
cd src/main/resources/config
git fetch origin develop:develop
git checkout develop
cp data-dev.sql ../data-dev.sql
cd ../../../../

# --- (2) systemd daemon-reload 추가 후 서비스 재시작 ---
- name: Restart backend service
run: |
sshpass -p ${{ secrets.SSH_PASSWORD }} ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << EOF
cd /home/anhye0n/web/tutorial_sejong/backend/
git submodule update --init --recursive
# GitHub Container Registry 로그인
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GH_PAT }}

# 도커 빌더 설정
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

# Backend 이미지 빌드 및 푸시
- name: Build and push Backend image
uses: docker/build-push-action@v5
with:
context: .
file: docker-files/backend/Dockerfile
push: true
tags: ${{ secrets.BACKEND_IMAGE }}
platforms: linux/arm64
cache-from: type=gha
cache-to: type=gha,mode=max

CURRENT_PID=\$(lsof -t -i:8080)
if [ -n "\$CURRENT_PID" ]; then
echo "Stopping process using port 8080 with PID \$CURRENT_PID"
echo ${{ secrets.SSH_PASSWORD }} | sudo -S kill -9 \$CURRENT_PID
fi
# 필요한 파일만 서버로 전송
- name: Copy deployment files
uses: appleboy/scp-action@v0.1.7
with:
host: ${{ secrets.HOST }}
port: ${{ secrets.PORT }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
source: "docker-compose.yml,docker-files/nginx/"
target: "${{ secrets.DEPLOY_PATH }}"
strip_components: 0

# systemd 설정 변경/추가 후 재로딩
echo ${{ secrets.SSH_PASSWORD }} | sudo -S systemctl daemon-reload
echo ${{ secrets.SSH_PASSWORD }} | sudo -S systemctl restart tutorial_sejong_backend
echo ${{ secrets.SSH_PASSWORD }} | sudo -S systemctl status tutorial_sejong_backend
# 백엔드 배포
- name: Deploy backend
uses: appleboy/ssh-action@v1.0.3
with:
host: ${{ secrets.HOST }}
port: ${{ secrets.PORT }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd ${{ secrets.DEPLOY_PATH }}

# DB 스크립트 실행 (15초 대기 후)
sleep 15
mysql -u ${{ secrets.MARIADB_ID }} -p${{ secrets.MARIADB_PASSWORD }} < /home/anhye0n/web/tutorial_sejong/backend/tutorial_sejong.sql
EOF
# GitHub Container Registry 로그인 추가
echo ${{ secrets.GH_PAT }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin

# 환경 변수 파일 생성
cat > .env << EOL
DB_ROOT_PASSWORD=${{ secrets.DB_ROOT_PASSWORD }}
DB_NAME=${{ secrets.DB_NAME }}
DB_USER=${{ secrets.DB_USER }}
DB_PASSWORD=${{ secrets.DB_PASSWORD }}
DOMAIN_NAME=${{ secrets.DOMAIN_NAME }}
BACKEND_PORT=${{ secrets.BACKEND_PORT }}
NGINX_PORT=${{ secrets.NGINX_PORT }}
DB_PORT=${{ secrets.DB_PORT }}
BACKEND_IMAGE=${{ secrets.BACKEND_IMAGE }}
EOL

# 백엔드만 재배포
docker-compose pull backend
docker-compose up -d --no-deps backend

# 상태 확인
docker-compose ps

# 미사용 이미지 정리
docker image prune -f --filter "until=168h"
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,5 @@ out/
application*.properties
src/main/resources/config

logs/*
logs/*
.env
60 changes: 60 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
services:
nginx:
image: nginx:alpine@arm64
container_name: cr-nginx
depends_on:
backend:
condition: service_started
ports:
- "${NGINX_PORT}:80"
volumes:
- ./docker-files/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- app-network
restart: unless-stopped

mariadb:
image: mariadb:latest@arm64
container_name: cr-mariadb
healthcheck:
test: ["CMD", "mariadb", "-h", "localhost", "-u${DB_USER}", "-p${DB_PASSWORD}", "-e", "SELECT 1"]
start_period: 30s
interval: 10s
timeout: 5s
retries: 5
Comment on lines +19 to +24
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

healthcheck라는 부분을 이번에 처음 알았습니다!
감사합니다.

environment:
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
MARIADB_DATABASE: ${DB_NAME}
MARIADB_USER: ${DB_USER}
MARIADB_PASSWORD: ${DB_PASSWORD}
ports:
- "${DB_PORT}:3306"
volumes:
- mariadb-data:/var/lib/mysql
networks:
- app-network
restart: unless-stopped

backend:
image: ${BACKEND_IMAGE}
platform: linux/arm64
container_name: cr-backend
depends_on:
mariadb:
condition: service_healthy
environment:
- DB_NAME=${DB_NAME}
- DB_USER=${DB_USER}
- DB_PASSWORD=${DB_PASSWORD}
ports:
- "${BACKEND_PORT}:8080"
networks:
- app-network
restart: unless-stopped

networks:
app-network:
driver: bridge

volumes:
mariadb-data:
8 changes: 8 additions & 0 deletions docker-files/backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.git
.gradle
.idea
build
!build/libs/*.jar
*.md
*.log
**/test/
23 changes: 23 additions & 0 deletions docker-files/backend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 빌드 스테이지
FROM amazoncorretto:17-alpine as build

WORKDIR /workspace/app

COPY gradle gradle
COPY build.gradle settings.gradle gradlew ./
COPY src src

RUN chmod +x ./gradlew
RUN ./gradlew bootJar
RUN mkdir -p build/libs

# 실행 스테이지
FROM amazoncorretto:17-alpine

VOLUME /tmp

COPY --from=build /workspace/app/build/libs/*.jar app.jar

EXPOSE 8080

ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=dev", "/app.jar"]
12 changes: 12 additions & 0 deletions docker-files/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
server {
listen 80;
server_name ${DOMAIN_NAME};

location / {
proxy_pass http://backend:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
40 changes: 40 additions & 0 deletions scripts/set-github-secrets.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/bin/bash

# ANSI 색상 코드
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m' # No Color

# 사용법 체크
if [ -z "$1" ]; then
echo "${RED}Usage: ./set-github-env-secrets.sh <environment_name>${NC}"
echo "${YELLOW}Example: ./set-github-env-secrets.sh development${NC}"
exit 1
fi

ENVIRONMENT=$1

# Environment secrets 설정
echo "⚙️ ${GREEN}GitHub ${ENVIRONMENT} environment secrets 설정을 시작합니다...${NC}"

# .env 파일이 존재하는지 확인
if [ ! -f .env ]; then
echo "${RED}Error: .env 파일을 찾을 수 없습니다.${NC}"
exit 1
fi

# .env 파일을 읽어서 secrets 설정
while IFS='=' read -r key value
do
if [ ! -z "$key" ] && [ ! -z "$value" ]; then
gh secret set "$key" -b"$value" --env $ENVIRONMENT || exit 1
fi
done < .env

# SSH key 설정 (선택적)
if [ -f ~/.ssh/id_ed25519 ]; then
gh secret set SSH_PRIVATE_KEY -b"$(cat ~/.ssh/id_ed25519)" --env $ENVIRONMENT || exit 1
fi

echo "✅ ${GREEN}GitHub ${ENVIRONMENT} environment secrets 설정이 완료되었습니다!${NC}"
61 changes: 61 additions & 0 deletions scripts/setup-ssh-key.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
#!/bin/bash

# ANSI 색상 코드
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
NC='\033[0m'

# SSH 디렉토리 및 파일 확인
echo "SSH 설정을 확인합니다..."

# .ssh 디렉토리가 없으면 생성
if [ ! -d ~/.ssh ]; then
echo ".ssh 디렉토리를 생성합니다..."
mkdir -p ~/.ssh
chmod 700 ~/.ssh
fi

# id_ed25519 파일이 이미 존재하는지 확인
if [ -f ~/.ssh/id_ed25519 ]; then
echo "${YELLOW}SSH 키가 이미 존재합니다.${NC}"
echo "기존 키를 사용하시겠습니까? (y/n)"
read -r response
if [ "$response" = "y" ]; then
echo "${GREEN}기존 SSH 키를 사용합니다.${NC}"
else
echo "새로운 키로 대체하시겠습니까? 이 작업은 되돌릴 수 없습니다. (y/n)"
read -r replace
if [ "$replace" = "y" ]; then
echo "${RED}Warning: 필요한 경우 기존 키를 먼저 백업하는 것을 추천합니다.${NC}"
echo "계속하시겠습니까? (y/n)"
read -r confirm
if [ "$confirm" = "y" ]; then
echo "새로운 SSH 키를 생성합니다..."
echo "이메일 주소를 입력해주세요:"
read -r email
rm ~/.ssh/id_ed25519*
ssh-keygen -t ed25519 -b 4096 -C "$email"
else
echo "${RED}스크립트를 종료합니다.${NC}"
exit 1
fi
else
echo "${RED}스크립트를 종료합니다.${NC}"
exit 1
fi
fi
else
# SSH 키 생성
echo "새로운 SSH 키를 생성합니다..."
echo "이메일 주소를 입력해주세요:"
read -r email
ssh-keygen -t ed25519 -b 4096 -C "$email"
fi

# authorized_keys 설정
echo "authorized_keys 파일을 설정합니다..."
cat ~/.ssh/id_ed25519.pub >> ~/.ssh/authorized_keys
chmod 600 ~/.ssh/authorized_keys

echo "${GREEN}SSH 키 설정이 완료되었습니다!${NC}"
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,4 @@ public class TutorialSejongApplication {
public static void main(String[] args) {
SpringApplication.run(TutorialSejongApplication.class, args);
}

}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.tutorialsejong.courseregistration.common.exception;

import com.tutorialsejong.courseregistration.domain.auth.controller.AuthController;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Getter
public class BusinessException extends RuntimeException {
Expand Down
Loading
Loading