From 1ae2d1f76c17d9077d49c06ea97b37d2a7ef61f9 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 18:16:26 +0900 Subject: [PATCH 01/20] =?UTF-8?q?[docs]=20application-dev.yml=EC=9D=84=20g?= =?UTF-8?q?itignore=EC=97=90=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 64cff529..385f2b4d 100644 --- a/.gitignore +++ b/.gitignore @@ -43,6 +43,7 @@ application.properties application-aws.properties application-dev.properties application-prod.properties +application-dev.yml application-prod.yml FirebaseAdminKey.json From 5dae573cf2ef4a828abbef872e00b910ac24ab6d Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 18:33:07 +0900 Subject: [PATCH 02/20] =?UTF-8?q?[feat]=20=EA=B0=9C=EB=B0=9C=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=20CI/CD=20workflow=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 154 +++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 .github/workflows/deploy-dev.yml diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml new file mode 100644 index 00000000..ecfd8feb --- /dev/null +++ b/.github/workflows/deploy-dev.yml @@ -0,0 +1,154 @@ +name: Deploy to Development Server (Mac Mini) + +on: + push: + branches: ["develop"] # develop 브랜치에 푸시될 때 개발 배포 + workflow_dispatch: # 수동 실행 가능 + +permissions: + contents: read + +jobs: + build-and-deploy-dev: + runs-on: self-hosted # Mac Mini의 Self-hosted Runner 사용 + + steps: + # 1. 코드 체크아웃 + - name: Checkout code + uses: actions/checkout@v4 + + # 2. JDK 17 설정 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: 'gradle' + + # 3. application-dev.yml 생성 (개발 환경 설정) + - name: Create application-dev.yml + run: | + mkdir -p ./src/main/resources + cat > ./src/main/resources/application-dev.yml << 'EOF' + ${{ secrets.APPLICATION_DEV }} + EOF + shell: bash + + # 4. Firebase Admin Key 생성 + - name: Create FirebaseAdminKey.json + run: | + rm -rf ./FirebaseAdminKey.json + cat > ./FirebaseAdminKey.json << 'EOF' + ${{ secrets.FIREBASE_ADMIN_KEY }} + EOF + shell: bash + + # 5. Gradle 빌드 권한 부여 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + shell: bash + + # 6. Gradle 빌드 (테스트 제외) + - name: Build with Gradle + run: ./gradlew clean build -x test + shell: bash + + # 7. Docker 이미지 빌드 (DEVELOPMENT 태그) + - name: Build Docker image + run: | + docker build -t ${{ secrets.DOCKER_USERNAME }}/ono:dev-latest . + docker tag ${{ secrets.DOCKER_USERNAME }}/ono:dev-latest ${{ secrets.DOCKER_USERNAME }}/ono:dev-${{ github.sha }} + shell: bash + + # 8. Docker Hub에 푸시 + - name: Push to Docker Hub + run: | + echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin + docker push ${{ secrets.DOCKER_USERNAME }}/ono:dev-latest + docker push ${{ secrets.DOCKER_USERNAME }}/ono:dev-${{ github.sha }} + shell: bash + + # 9. .env 파일 생성 (DEVELOPMENT) + - name: Create .env file + run: | + cat > .env.dev << EOF + DOCKER_USERNAME=${{ secrets.DOCKER_USERNAME }} + MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }} + SPRING_CRYPTO_SECRET_KEY=${{ secrets.SPRING_CRYPTO_SECRET_KEY }} + JWT_ACCESS_TOKEN_SECRET=${{ secrets.JWT_ACCESS_TOKEN_SECRET }} + JWT_ACCESS_TOKEN_EXPIRATION=1800000 + JWT_REFRESH_TOKEN_SECRET=${{ secrets.JWT_REFRESH_TOKEN_SECRET }} + JWT_REFRESH_TOKEN_EXPIRATION=604800000 + CLOUD_AWS_S3_BUCKET=${{ secrets.CLOUD_AWS_S3_BUCKET }} + CLOUD_AWS_CREDENTIALS_ACCESS_KEY=${{ secrets.CLOUD_AWS_CREDENTIALS_ACCESS_KEY }} + CLOUD_AWS_CREDENTIALS_SECRET_KEY=${{ secrets.CLOUD_AWS_CREDENTIALS_SECRET_KEY }} + DISCORD_WEBHOOK_URL_DEV=${{ secrets.DISCORD_WEBHOOK_URL_DEV }} + OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} + SENTRY_DSN_DEV=${{ secrets.SENTRY_DSN_DEV }} + ADMIN_IDENTIFIER=${{ secrets.ADMIN_IDENTIFIER }} + ADMIN_PASSWORD=${{ secrets.ADMIN_PASSWORD }} + EOF + shell: bash + + # 10. Docker Compose로 배포 (DEVELOPMENT) + - name: Deploy with Docker Compose + run: | + # MySQL과 Redis 시작 (개발 환경 전용) + docker-compose -f docker-compose.dev.yml up -d mysql-dev redis-dev + + # Spring Boot 개발 앱만 재시작 + docker-compose -f docker-compose.dev.yml stop app-dev || true + docker-compose -f docker-compose.dev.yml rm -f app-dev || true + docker-compose -f docker-compose.dev.yml --env-file .env.dev up -d app-dev + + # 헬스체크 대기 (최대 2분) + echo "Waiting for development application to be healthy..." + timeout=120 + elapsed=0 + while [ $elapsed -lt $timeout ]; do + if docker-compose -f docker-compose.dev.yml ps app-dev | grep -q "healthy"; then + echo "Development application is healthy!" + break + fi + echo "Waiting... ($elapsed seconds)" + sleep 5 + elapsed=$((elapsed + 5)) + done + + # 컨테이너 상태 확인 + docker-compose -f docker-compose.dev.yml ps + + # 로그 출력 (마지막 50줄) + echo "=== Development Application Logs ===" + docker-compose -f docker-compose.dev.yml logs --tail=50 app-dev + shell: bash + + # 12. 오래된 Docker 이미지 정리 + - name: Clean up old Docker images + run: | + docker image prune -f --filter "until=24h" + shell: bash + continue-on-error: true + + # 13. Discord 배포 알림 + - name: Send deployment notification + if: always() + run: | + STATUS="${{ job.status }}" + COLOR="3066993" # 파란색 (성공) + if [ "$STATUS" != "success" ]; then + COLOR="15158332" # 빨간색 (실패) + fi + + curl -X POST "${{ secrets.DISCORD_WEBHOOK_URL_DEV }}" \ + -H "Content-Type: application/json" \ + -d "{ + \"embeds\": [{ + \"title\": \"🔧 Development Deployment $STATUS\", + \"description\": \"Environment: **DEVELOPMENT**\nURL: https://ono-dev.seungminki.shop\nBranch: \`${{ github.ref_name }}\`\nCommit: \`${{ github.sha }}\`\nAuthor: ${{ github.actor }}\", + \"color\": $COLOR, + \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)\" + }] + }" + shell: bash + continue-on-error: true \ No newline at end of file From 6258a0f8b4683a149c1c5c72030a953b050f7a10 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 18:33:12 +0900 Subject: [PATCH 03/20] =?UTF-8?q?[feat]=20=ED=94=84=EB=A1=9C=EB=8D=95?= =?UTF-8?q?=EC=85=98=20=ED=99=98=EA=B2=BD=20CI/CD=20workflow=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yml | 154 ++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 .github/workflows/deploy-prod.yml diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml new file mode 100644 index 00000000..8c362a3e --- /dev/null +++ b/.github/workflows/deploy-prod.yml @@ -0,0 +1,154 @@ +name: Deploy to Production Server (Mac Mini) + +on: + push: + branches: ["main"] # main 브랜치에 푸시될 때 운영 배포 + workflow_dispatch: # 수동 실행 가능 + +permissions: + contents: read + +jobs: + build-and-deploy-prod: + runs-on: self-hosted # Mac Mini의 Self-hosted Runner 사용 + + steps: + # 1. 코드 체크아웃 + - name: Checkout code + uses: actions/checkout@v4 + + # 2. JDK 17 설정 + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + cache: 'gradle' + + # 3. application-prod.yml 생성 + - name: Create application-prod.yml + run: | + mkdir -p ./src/main/resources + cat > ./src/main/resources/application-prod.yml << 'EOF' + ${{ secrets.APPLICATION_PROD }} + EOF + shell: bash + + # 4. Firebase Admin Key 생성 + - name: Create FirebaseAdminKey.json + run: | + rm -rf ./FirebaseAdminKey.json + cat > ./FirebaseAdminKey.json << 'EOF' + ${{ secrets.FIREBASE_ADMIN_KEY }} + EOF + shell: bash + + # 5. Gradle 빌드 권한 부여 + - name: Grant execute permission for gradlew + run: chmod +x gradlew + shell: bash + + # 6. Gradle 빌드 (테스트 제외) + - name: Build with Gradle + run: ./gradlew clean build -x test + shell: bash + + # 7. Docker 이미지 빌드 (PRODUCTION 태그) + - name: Build Docker image + run: | + docker build -t ${{ secrets.DOCKER_USERNAME }}/ono:prod-latest . + docker tag ${{ secrets.DOCKER_USERNAME }}/ono:prod-latest ${{ secrets.DOCKER_USERNAME }}/ono:prod-${{ github.sha }} + shell: bash + + # 8. Docker Hub에 푸시 + - name: Push to Docker Hub + run: | + echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin + docker push ${{ secrets.DOCKER_USERNAME }}/ono:prod-latest + docker push ${{ secrets.DOCKER_USERNAME }}/ono:prod-${{ github.sha }} + shell: bash + + # 9. .env 파일 생성 (PRODUCTION) + - name: Create .env file + run: | + cat > .env.prod << EOF + DOCKER_USERNAME=${{ secrets.DOCKER_USERNAME }} + MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }} + SPRING_CRYPTO_SECRET_KEY=${{ secrets.SPRING_CRYPTO_SECRET_KEY }} + JWT_ACCESS_TOKEN_SECRET=${{ secrets.JWT_ACCESS_TOKEN_SECRET }} + JWT_ACCESS_TOKEN_EXPIRATION=1800000 + JWT_REFRESH_TOKEN_SECRET=${{ secrets.JWT_REFRESH_TOKEN_SECRET }} + JWT_REFRESH_TOKEN_EXPIRATION=604800000 + CLOUD_AWS_S3_BUCKET=${{ secrets.CLOUD_AWS_S3_BUCKET }} + CLOUD_AWS_CREDENTIALS_ACCESS_KEY=${{ secrets.CLOUD_AWS_CREDENTIALS_ACCESS_KEY }} + CLOUD_AWS_CREDENTIALS_SECRET_KEY=${{ secrets.CLOUD_AWS_CREDENTIALS_SECRET_KEY }} + DISCORD_WEBHOOK_URL=${{ secrets.DISCORD_WEBHOOK_URL }} + OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} + SENTRY_DSN=${{ secrets.SENTRY_DSN }} + ADMIN_IDENTIFIER=${{ secrets.ADMIN_IDENTIFIER }} + ADMIN_PASSWORD=${{ secrets.ADMIN_PASSWORD }} + EOF + shell: bash + + # 10. Docker Compose로 배포 (PRODUCTION) + - name: Deploy with Docker Compose + run: | + # MySQL과 Redis 시작 (이미 실행 중이면 스킵) + docker-compose -f docker-compose.prod.yml up -d mysql-prod redis-prod + + # Spring Boot 운영 앱만 재시작 + docker-compose -f docker-compose.prod.yml stop app-prod || true + docker-compose -f docker-compose.prod.yml rm -f app-prod || true + docker-compose -f docker-compose.prod.yml --env-file .env.prod up -d app-prod + + # 헬스체크 대기 (최대 2분) + echo "Waiting for production application to be healthy..." + timeout=120 + elapsed=0 + while [ $elapsed -lt $timeout ]; do + if docker-compose -f docker-compose.prod.yml ps app-prod | grep -q "healthy"; then + echo "Production application is healthy!" + break + fi + echo "Waiting... ($elapsed seconds)" + sleep 5 + elapsed=$((elapsed + 5)) + done + + # 컨테이너 상태 확인 + docker-compose -f docker-compose.prod.yml ps + + # 로그 출력 (마지막 50줄) + echo "=== Production Application Logs ===" + docker-compose -f docker-compose.prod.yml logs --tail=50 app-prod + shell: bash + + # 12. 오래된 Docker 이미지 정리 + - name: Clean up old Docker images + run: | + docker image prune -f --filter "until=24h" + shell: bash + continue-on-error: true + + # 13. Discord 배포 알림 + - name: Send deployment notification + if: always() + run: | + STATUS="${{ job.status }}" + COLOR="3066993" # 파란색 (성공) + if [ "$STATUS" != "success" ]; then + COLOR="15158332" # 빨간색 (실패) + fi + + curl -X POST "${{ secrets.DISCORD_WEBHOOK_URL }}" \ + -H "Content-Type: application/json" \ + -d "{ + \"embeds\": [{ + \"title\": \"🚀 Production Deployment $STATUS\", + \"description\": \"Environment: **PRODUCTION**\nURL: https://ono-prod.seungminki.shop\nBranch: \`${{ github.ref_name }}\`\nCommit: \`${{ github.sha }}\`\nAuthor: ${{ github.actor }}\", + \"color\": $COLOR, + \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)\" + }] + }" + shell: bash + continue-on-error: true \ No newline at end of file From 82d3497c90bda65aafa823d2756d96fdbe16a9ef Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 18:33:26 +0900 Subject: [PATCH 04/20] =?UTF-8?q?[feat]=20=EA=B0=9C=EB=B0=9C=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=20docker-compose=20=ED=8C=8C=EC=9D=BC=20=EC=9E=91?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.dev.yml | 102 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 docker-compose.dev.yml diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 00000000..77bae335 --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,102 @@ +version: '3.8' + +services: + # MySQL Database - DEVELOPMENT + mysql-dev: + image: mysql:8.0 + container_name: ono-mysql-dev + restart: unless-stopped + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_DATABASE: ono_db_dev + TZ: Asia/Seoul + ports: + - "3307:3306" # 외부 포트 3307로 노출 (prod와 충돌 방지) + volumes: + - mysql_dev_data:/var/lib/mysql + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --default-time-zone=+09:00 + networks: + - ono-network + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] + interval: 10s + timeout: 5s + retries: 5 + + # Redis Cache - DEVELOPMENT (리소스 제한 적용) + redis-dev: + image: redis:7.2-alpine + container_name: ono-redis-dev + restart: unless-stopped + ports: + - "6380:6379" # 외부 포트 6380으로 노출 (prod와 충돌 방지) + volumes: + - redis_dev_data:/data + networks: + - ono-network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + # 개발 환경 Redis는 메모리 제한을 더 작게 설정 + command: redis-server --appendonly yes --maxmemory 128mb --maxmemory-policy allkeys-lru + + # Spring Boot Application - DEVELOPMENT + app-dev: + image: ${DOCKER_USERNAME}/ono:dev-latest + container_name: ono-app-dev + restart: unless-stopped + ports: + - "8082:8080" # 개발 서버는 8082 포트로 외부 노출 + environment: + SPRING_PROFILES_ACTIVE: dev + SPRING_DATASOURCE_URL: jdbc:mysql://mysql-dev:3306/ono_db_dev?serverTimezone=Asia/Seoul&characterEncoding=UTF-8 + SPRING_DATASOURCE_USERNAME: root + SPRING_DATASOURCE_PASSWORD: ${MYSQL_ROOT_PASSWORD} + SPRING_DATA_REDIS_HOST: redis-dev + SPRING_DATA_REDIS_PORT: 6379 + # 환경 변수 + SPRING_CRYPTO_SECRET_KEY: ${SPRING_CRYPTO_SECRET_KEY} + JWT_ACCESS_TOKEN_SECRET: ${JWT_ACCESS_TOKEN_SECRET} + JWT_ACCESS_TOKEN_EXPIRATION: ${JWT_ACCESS_TOKEN_EXPIRATION} + JWT_REFRESH_TOKEN_SECRET: ${JWT_REFRESH_TOKEN_SECRET} + JWT_REFRESH_TOKEN_EXPIRATION: ${JWT_REFRESH_TOKEN_EXPIRATION} + CLOUD_AWS_S3_BUCKET: ${CLOUD_AWS_S3_BUCKET} + CLOUD_AWS_CREDENTIALS_ACCESS_KEY: ${CLOUD_AWS_CREDENTIALS_ACCESS_KEY} + CLOUD_AWS_CREDENTIALS_SECRET_KEY: ${CLOUD_AWS_CREDENTIALS_SECRET_KEY} + DISCORD_WEBHOOK_URL: ${DISCORD_WEBHOOK_URL} + OPENAI_API_KEY: ${OPENAI_API_KEY} + SENTRY_DSN: ${SENTRY_DSN} + ADMIN_IDENTIFIER: ${ADMIN_IDENTIFIER} + ADMIN_PASSWORD: ${ADMIN_PASSWORD} + volumes: + - app_dev_logs:/app/logs + depends_on: + mysql-dev: + condition: service_healthy + redis-dev: + condition: service_healthy + networks: + - ono-network + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/actuator/health || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s + +networks: + ono-network: + external: true # prod에서 생성된 네트워크 사용 + +volumes: + mysql_dev_data: + driver: local + redis_dev_data: + driver: local + app_dev_logs: + driver: local \ No newline at end of file From 85605948fcfa56e2890ad1d230af87c5793ecc98 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 18:33:31 +0900 Subject: [PATCH 05/20] =?UTF-8?q?[feat]=20=ED=94=84=EB=A1=9C=EB=8D=95?= =?UTF-8?q?=EC=85=98=20=ED=99=98=EA=B2=BD=20docker-compose=20=ED=8C=8C?= =?UTF-8?q?=EC=9D=BC=20=EC=9E=91=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.prod.yml | 101 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docker-compose.prod.yml diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 00000000..ec6538a8 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,101 @@ +version: '3.8' + +services: + # MySQL Database - PRODUCTION + mysql-prod: + image: mysql:8.0 + container_name: ono-mysql-prod + restart: unless-stopped + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + MYSQL_DATABASE: ono_db_prod + TZ: Asia/Seoul + ports: + - "3306:3306" + volumes: + - mysql_prod_data:/var/lib/mysql + command: + - --character-set-server=utf8mb4 + - --collation-server=utf8mb4_unicode_ci + - --default-time-zone=+09:00 + networks: + - ono-network + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"] + interval: 10s + timeout: 5s + retries: 5 + + # Redis Cache - PRODUCTION + redis-prod: + image: redis:7.2-alpine + container_name: ono-redis-prod + restart: unless-stopped + ports: + - "6379:6379" + volumes: + - redis_prod_data:/data + networks: + - ono-network + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 5s + retries: 5 + command: redis-server --appendonly yes --maxmemory 512mb --maxmemory-policy allkeys-lru + + # Spring Boot Application - PRODUCTION + app-prod: + image: ${DOCKER_USERNAME}/ono:prod-latest + container_name: ono-app-prod + restart: unless-stopped + ports: + - "8080:8080" # 운영 서버 포트 + environment: + SPRING_PROFILES_ACTIVE: prod + SPRING_DATASOURCE_URL: jdbc:mysql://mysql-prod:3306/ono_db_prod?serverTimezone=Asia/Seoul&characterEncoding=UTF-8 + SPRING_DATASOURCE_USERNAME: root + SPRING_DATASOURCE_PASSWORD: ${MYSQL_ROOT_PASSWORD} + SPRING_DATA_REDIS_HOST: redis-prod + SPRING_DATA_REDIS_PORT: 6379 + # 환경 변수 + SPRING_CRYPTO_SECRET_KEY: ${SPRING_CRYPTO_SECRET_KEY} + JWT_ACCESS_TOKEN_SECRET: ${JWT_ACCESS_TOKEN_SECRET} + JWT_ACCESS_TOKEN_EXPIRATION: ${JWT_ACCESS_TOKEN_EXPIRATION} + JWT_REFRESH_TOKEN_SECRET: ${JWT_REFRESH_TOKEN_SECRET} + JWT_REFRESH_TOKEN_EXPIRATION: ${JWT_REFRESH_TOKEN_EXPIRATION} + CLOUD_AWS_S3_BUCKET: ${CLOUD_AWS_S3_BUCKET} + CLOUD_AWS_CREDENTIALS_ACCESS_KEY: ${CLOUD_AWS_CREDENTIALS_ACCESS_KEY} + CLOUD_AWS_CREDENTIALS_SECRET_KEY: ${CLOUD_AWS_CREDENTIALS_SECRET_KEY} + DISCORD_WEBHOOK_URL: ${DISCORD_WEBHOOK_URL} + OPENAI_API_KEY: ${OPENAI_API_KEY} + SENTRY_DSN: ${SENTRY_DSN} + ADMIN_IDENTIFIER: ${ADMIN_IDENTIFIER} + ADMIN_PASSWORD: ${ADMIN_PASSWORD} + volumes: + - app_prod_logs:/app/logs + depends_on: + mysql-prod: + condition: service_healthy + redis-prod: + condition: service_healthy + networks: + - ono-network + healthcheck: + test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/actuator/health || exit 1"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s + +networks: + ono-network: + driver: bridge + +volumes: + mysql_prod_data: + driver: local + redis_prod_data: + driver: local + app_prod_logs: + driver: local \ No newline at end of file From 7f7f23c88fa9f5cfe92c7e32a77c8390ffbfa14f Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 18:34:23 +0900 Subject: [PATCH 06/20] =?UTF-8?q?[test]=20test=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=B4=20workflow=20=EB=B8=8C=EB=9E=9C=EC=B9=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 2 +- .github/workflows/deploy-prod.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index ecfd8feb..6a04d29c 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -2,7 +2,7 @@ name: Deploy to Development Server (Mac Mini) on: push: - branches: ["develop"] # develop 브랜치에 푸시될 때 개발 배포 + branches: ["deploy-develop-test"] # develop 브랜치에 푸시될 때 개발 배포 workflow_dispatch: # 수동 실행 가능 permissions: diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 8c362a3e..c180a7b2 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -2,7 +2,7 @@ name: Deploy to Production Server (Mac Mini) on: push: - branches: ["main"] # main 브랜치에 푸시될 때 운영 배포 + branches: ["deploy-prod-test"] # main 브랜치에 푸시될 때 운영 배포 workflow_dispatch: # 수동 실행 가능 permissions: From 9dd213427a8a3fd8e48b4423f8d6a9918c861c93 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 18:43:42 +0900 Subject: [PATCH 07/20] =?UTF-8?q?[fix]=20=ED=99=98=EA=B2=BD=EB=B3=80?= =?UTF-8?q?=EC=88=98=EB=AA=85=EC=9D=B4=20=EC=9E=98=EB=AA=BB=20=EC=84=A4?= =?UTF-8?q?=EC=A0=95=EB=90=98=EC=96=B4=20=EC=9E=88=EB=8A=94=20=EB=AC=B8?= =?UTF-8?q?=EC=A0=9C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 4 ++-- docker-compose.dev.yml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 6a04d29c..849961eb 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -82,9 +82,9 @@ jobs: CLOUD_AWS_S3_BUCKET=${{ secrets.CLOUD_AWS_S3_BUCKET }} CLOUD_AWS_CREDENTIALS_ACCESS_KEY=${{ secrets.CLOUD_AWS_CREDENTIALS_ACCESS_KEY }} CLOUD_AWS_CREDENTIALS_SECRET_KEY=${{ secrets.CLOUD_AWS_CREDENTIALS_SECRET_KEY }} - DISCORD_WEBHOOK_URL_DEV=${{ secrets.DISCORD_WEBHOOK_URL_DEV }} + DISCORD_WEBHOOK_URL_DEV=${{ secrets.DISCORD_WEBHOOK_URL }} OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} - SENTRY_DSN_DEV=${{ secrets.SENTRY_DSN_DEV }} + SENTRY_DSN_DEV=${{ secrets.SENTRY_DSN }} ADMIN_IDENTIFIER=${{ secrets.ADMIN_IDENTIFIER }} ADMIN_PASSWORD=${{ secrets.ADMIN_PASSWORD }} EOF diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 77bae335..9f7202a2 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -91,7 +91,8 @@ services: networks: ono-network: - external: true # prod에서 생성된 네트워크 사용 + driver: bridge + name: ono-network # prod와 같은 네트워크 이름 사용 volumes: mysql_dev_data: From b227679c316c6d836aff4405f47a55cb351a4e14 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 18:54:18 +0900 Subject: [PATCH 08/20] =?UTF-8?q?[fix]=20=ED=99=98=EA=B2=BD=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 849961eb..4fd7de2d 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -140,7 +140,7 @@ jobs: COLOR="15158332" # 빨간색 (실패) fi - curl -X POST "${{ secrets.DISCORD_WEBHOOK_URL_DEV }}" \ + curl -X POST "${{ secrets.DISCORD_WEBHOOK_URL }}" \ -H "Content-Type: application/json" \ -d "{ \"embeds\": [{ From e46ab1db5a5b1f9eed993b880981d0acaa5547d8 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 19:02:26 +0900 Subject: [PATCH 09/20] =?UTF-8?q?[fix]=20=ED=99=98=EA=B2=BD=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=ED=8C=8C=EC=9D=BC=EC=9D=B4=20=EB=A1=9C=EB=93=9C?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 6 +++--- .github/workflows/deploy-prod.yml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 4fd7de2d..25140272 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -94,11 +94,11 @@ jobs: - name: Deploy with Docker Compose run: | # MySQL과 Redis 시작 (개발 환경 전용) - docker-compose -f docker-compose.dev.yml up -d mysql-dev redis-dev + docker-compose -f docker-compose.dev.yml --env-file .env.dev up -d mysql-dev redis-dev # Spring Boot 개발 앱만 재시작 - docker-compose -f docker-compose.dev.yml stop app-dev || true - docker-compose -f docker-compose.dev.yml rm -f app-dev || true + docker-compose -f docker-compose.dev.yml --env-file .env.dev stop app-dev || true + docker-compose -f docker-compose.dev.yml --env-file .env.dev rm -f app-dev || true docker-compose -f docker-compose.dev.yml --env-file .env.dev up -d app-dev # 헬스체크 대기 (최대 2분) diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index c180a7b2..7a650e78 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -94,11 +94,11 @@ jobs: - name: Deploy with Docker Compose run: | # MySQL과 Redis 시작 (이미 실행 중이면 스킵) - docker-compose -f docker-compose.prod.yml up -d mysql-prod redis-prod + docker-compose -f docker-compose.prod.yml --env-file .env.prod up -d mysql-prod redis-prod # Spring Boot 운영 앱만 재시작 - docker-compose -f docker-compose.prod.yml stop app-prod || true - docker-compose -f docker-compose.prod.yml rm -f app-prod || true + docker-compose -f docker-compose.prod.yml --env-file .env.prod stop app-prod || true + docker-compose -f docker-compose.prod.yml --env-file .env.prod rm -f app-prod || true docker-compose -f docker-compose.prod.yml --env-file .env.prod up -d app-prod # 헬스체크 대기 (최대 2분) From 33ca9c2a8a960603b2885bcc3366d43e6f25f981 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 19:13:33 +0900 Subject: [PATCH 10/20] =?UTF-8?q?[fix]=20=ED=99=98=EA=B2=BD=EB=B3=80?= =?UTF-8?q?=EC=88=98=20=ED=8C=8C=EC=9D=BC=EC=9D=B4=20=EB=A1=9C=EB=93=9C?= =?UTF-8?q?=EB=90=98=EC=A7=80=20=EC=95=8A=EB=8D=98=20=EB=AC=B8=EC=A0=9C=20?= =?UTF-8?q?=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 25140272..6540bbd2 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -106,7 +106,7 @@ jobs: timeout=120 elapsed=0 while [ $elapsed -lt $timeout ]; do - if docker-compose -f docker-compose.dev.yml ps app-dev | grep -q "healthy"; then + if docker-compose -f docker-compose.dev.yml --env-file .env.dev ps app-dev | grep -q "healthy"; then echo "Development application is healthy!" break fi @@ -116,11 +116,11 @@ jobs: done # 컨테이너 상태 확인 - docker-compose -f docker-compose.dev.yml ps + docker-compose -f docker-compose.dev.yml --env-file .env.dev ps # 로그 출력 (마지막 50줄) echo "=== Development Application Logs ===" - docker-compose -f docker-compose.dev.yml logs --tail=50 app-dev + docker-compose -f docker-compose.dev.yml --env-file .env.dev logs --tail=50 app-dev shell: bash # 12. 오래된 Docker 이미지 정리 From 0a2a823a50bc3c4b7b5baf7f184fd7f3a4aa0eae Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 20:19:22 +0900 Subject: [PATCH 11/20] =?UTF-8?q?[fix]=20application.yml=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EC=8A=A4=ED=81=AC=EB=A6=BD=ED=8A=B8=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 6540bbd2..7e09ec4a 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -29,9 +29,7 @@ jobs: - name: Create application-dev.yml run: | mkdir -p ./src/main/resources - cat > ./src/main/resources/application-dev.yml << 'EOF' - ${{ secrets.APPLICATION_DEV }} - EOF + echo "${{ secrets.APPLICATION_DEV }}" > ./src/main/resources/application.yml shell: bash # 4. Firebase Admin Key 생성 From 5c33b1ae0706749460fbdbc4cdfcd58ae4de668a Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 20:29:41 +0900 Subject: [PATCH 12/20] =?UTF-8?q?[fix]=20SecurityConfig=EC=9D=98=20?= =?UTF-8?q?=EB=B6=88=ED=95=84=EC=9A=94=ED=95=9C=20=ED=95=84=EB=93=9C=20?= =?UTF-8?q?=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/aisip/OnO/backend/auth/config/SecurityConfig.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/com/aisip/OnO/backend/auth/config/SecurityConfig.java b/src/main/java/com/aisip/OnO/backend/auth/config/SecurityConfig.java index f2014754..09ba1ecc 100644 --- a/src/main/java/com/aisip/OnO/backend/auth/config/SecurityConfig.java +++ b/src/main/java/com/aisip/OnO/backend/auth/config/SecurityConfig.java @@ -33,10 +33,7 @@ @RequiredArgsConstructor public class SecurityConfig { - @Value("${spring.jwt.secret}") - private String secret; - - @Value("${spring.site.url}") // 애플리케이션의 HTTPS 기본 URL을 환경 변수로 받아옴 + @Value("${spring.site.url}") private String siteUrl; public final JwtTokenFilter jwtTokenFilter; From a0c631174b2c53c42138c2f3355beff03ac8e202 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 20:43:04 +0900 Subject: [PATCH 13/20] =?UTF-8?q?[chore]=20CI/CD=20=EC=8B=9C=20Health=20ch?= =?UTF-8?q?eck=20=EC=8B=9C=EA=B0=84=EC=9D=84=202=EB=B6=84=20->=201?= =?UTF-8?q?=EB=B6=84=EC=9C=BC=EB=A1=9C=20=EB=8B=A8=EC=B6=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 7e09ec4a..83fc96bb 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -29,7 +29,7 @@ jobs: - name: Create application-dev.yml run: | mkdir -p ./src/main/resources - echo "${{ secrets.APPLICATION_DEV }}" > ./src/main/resources/application.yml + echo "${{ secrets.APPLICATION_DEV }}" > ./src/main/resources/application-dev.yml shell: bash # 4. Firebase Admin Key 생성 @@ -101,7 +101,7 @@ jobs: # 헬스체크 대기 (최대 2분) echo "Waiting for development application to be healthy..." - timeout=120 + timeout=60 elapsed=0 while [ $elapsed -lt $timeout ]; do if docker-compose -f docker-compose.dev.yml --env-file .env.dev ps app-dev | grep -q "healthy"; then From b3a6e0ff16ef2051969bb170a22e6f0500f24aac Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 20:46:36 +0900 Subject: [PATCH 14/20] =?UTF-8?q?[test]=20=ED=94=84=EB=A1=9C=EB=8D=95?= =?UTF-8?q?=EC=85=98=20=ED=85=8C=EC=8A=A4=ED=8A=B8=EB=A5=BC=20=EC=9C=84?= =?UTF-8?q?=ED=95=9C=20workflow=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 7a650e78..5b7620e2 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -29,8 +29,7 @@ jobs: - name: Create application-prod.yml run: | mkdir -p ./src/main/resources - cat > ./src/main/resources/application-prod.yml << 'EOF' - ${{ secrets.APPLICATION_PROD }} + echo "${{ secrets.APPLICATION_PROD }}" > ./src/main/resources/application-prod.yml EOF shell: bash @@ -101,9 +100,9 @@ jobs: docker-compose -f docker-compose.prod.yml --env-file .env.prod rm -f app-prod || true docker-compose -f docker-compose.prod.yml --env-file .env.prod up -d app-prod - # 헬스체크 대기 (최대 2분) + # 헬스체크 대기 (최대 1분) echo "Waiting for production application to be healthy..." - timeout=120 + timeout=60 elapsed=0 while [ $elapsed -lt $timeout ]; do if docker-compose -f docker-compose.prod.yml ps app-prod | grep -q "healthy"; then From a0a55c95ef4f8a4e07724bc0174aaf61af109e70 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 20:55:41 +0900 Subject: [PATCH 15/20] =?UTF-8?q?[docs]=20yml=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 2 +- .github/workflows/deploy-prod.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 83fc96bb..83b5d02d 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -29,7 +29,7 @@ jobs: - name: Create application-dev.yml run: | mkdir -p ./src/main/resources - echo "${{ secrets.APPLICATION_DEV }}" > ./src/main/resources/application-dev.yml + echo "${{ secrets.APPLICATION_DEV }}" > ./src/main/resources/application.yml shell: bash # 4. Firebase Admin Key 생성 diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 5b7620e2..3544c86e 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -29,7 +29,7 @@ jobs: - name: Create application-prod.yml run: | mkdir -p ./src/main/resources - echo "${{ secrets.APPLICATION_PROD }}" > ./src/main/resources/application-prod.yml + echo "${{ secrets.APPLICATION_PROD }}" > ./src/main/resources/application.yml EOF shell: bash From db0727880e86eb462b12f27f14aa188b9bc01083 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 20:56:47 +0900 Subject: [PATCH 16/20] =?UTF-8?q?[docs]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20EOF=20=EB=AC=B8=EA=B5=AC=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-prod.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 3544c86e..148df313 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -30,7 +30,6 @@ jobs: run: | mkdir -p ./src/main/resources echo "${{ secrets.APPLICATION_PROD }}" > ./src/main/resources/application.yml - EOF shell: bash # 4. Firebase Admin Key 생성 From c813d249b8f53f76794b6a99546a30ab8d5412f3 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 21:24:17 +0900 Subject: [PATCH 17/20] =?UTF-8?q?[test]=20=EA=B0=9C=EB=B0=9C=ED=99=98?= =?UTF-8?q?=EA=B2=BD=20=EB=B0=B0=ED=8F=AC=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index 83b5d02d..d3687f38 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -149,4 +149,4 @@ jobs: }] }" shell: bash - continue-on-error: true \ No newline at end of file + continue-on-error: true From a52d0c4519d0bfe6bab41366598d5d78d70ffd58 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 23:26:00 +0900 Subject: [PATCH 18/20] =?UTF-8?q?[chore]=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EB=A1=9C=EA=B7=B8=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-compose.dev.yml | 2 +- docker-compose.prod.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 9f7202a2..9592915a 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -83,7 +83,7 @@ services: networks: - ono-network healthcheck: - test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/actuator/health || exit 1"] + test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:8080/actuator/health || exit 1"] interval: 30s timeout: 10s retries: 3 diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index ec6538a8..e67e8a77 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -82,7 +82,7 @@ services: networks: - ono-network healthcheck: - test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:8080/actuator/health || exit 1"] + test: ["CMD-SHELL", "wget --quiet --tries=1 --spider http://localhost:8080/actuator/health || exit 1"] interval: 30s timeout: 10s retries: 3 From 36518e1e22285d3b024891b19045673fa80aa605 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 23:38:14 +0900 Subject: [PATCH 19/20] =?UTF-8?q?[chore]=20=EC=82=AC=EC=9A=A9=ED=95=98?= =?UTF-8?q?=EC=A7=80=20=EC=95=8A=EB=8A=94=20workflow=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-home-server.yml | 157 ----------------------- .github/workflows/prod_docker_gradle.yml | 76 ----------- 2 files changed, 233 deletions(-) delete mode 100644 .github/workflows/deploy-home-server.yml delete mode 100644 .github/workflows/prod_docker_gradle.yml diff --git a/.github/workflows/deploy-home-server.yml b/.github/workflows/deploy-home-server.yml deleted file mode 100644 index 8557c325..00000000 --- a/.github/workflows/deploy-home-server.yml +++ /dev/null @@ -1,157 +0,0 @@ -name: Deploy to Home Server (Mac Mini) - -on: - push: - branches: ["main"] # main 브랜치에 푸시될 때 워크플로우 실행 - workflow_dispatch: # 수동 실행 가능 - -permissions: - contents: read - -jobs: - build-and-deploy: - runs-on: self-hosted # Mac Mini의 Self-hosted Runner 사용 - - steps: - # 1. 코드 체크아웃 - - name: Checkout code - uses: actions/checkout@v4 - - # 2. JDK 17 설정 - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' - cache: 'gradle' # Gradle 캐시 활성화 - - # 3. application-prod.yml 생성 (GitHub Secrets에서 주입) - - name: Create application-prod.yml - run: | - mkdir -p ./src/main/resources - echo "${{ secrets.APPLICATION_PROD }}" > ./src/main/resources/application-prod.yml - shell: bash - - # 4. Firebase Admin Key 생성 (GitHub Secrets에서 주입) - - name: Create FirebaseAdminKey.json - run: | - rm -rf ./FirebaseAdminKey.json # 기존 파일/디렉토리 삭제 - cat > ./FirebaseAdminKey.json << 'EOF' - ${{ secrets.FIREBASE_ADMIN_KEY }} - EOF - shell: bash - - # 5. Gradle 빌드 권한 부여 - - name: Grant execute permission for gradlew - run: chmod +x gradlew - shell: bash - - # 6. Gradle 빌드 (테스트 제외) - - name: Build with Gradle - run: ./gradlew clean build -x test - shell: bash - - # 7. Docker 이미지 빌드 - - name: Build Docker image - run: | - docker build -t ${{ secrets.DOCKER_USERNAME }}/ono:latest . - docker tag ${{ secrets.DOCKER_USERNAME }}/ono:latest ${{ secrets.DOCKER_USERNAME }}/ono:${{ github.sha }} - shell: bash - - # 8. Docker Hub에 로그인 및 푸시 (선택사항: 다른 서버에도 배포하려면) - - name: Push to Docker Hub - run: | - echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin - docker push ${{ secrets.DOCKER_USERNAME }}/ono:latest - docker push ${{ secrets.DOCKER_USERNAME }}/ono:${{ github.sha }} - shell: bash - - # 9. .env 파일 생성 - - name: Create .env file - run: | - cat > .env << EOF - DOCKER_USERNAME=${{ secrets.DOCKER_USERNAME }} - MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }} - SPRING_CRYPTO_SECRET_KEY=${{ secrets.SPRING_CRYPTO_SECRET_KEY }} - JWT_ACCESS_TOKEN_SECRET=${{ secrets.JWT_ACCESS_TOKEN_SECRET }} - JWT_ACCESS_TOKEN_EXPIRATION=1800000 - JWT_REFRESH_TOKEN_SECRET=${{ secrets.JWT_REFRESH_TOKEN_SECRET }} - JWT_REFRESH_TOKEN_EXPIRATION=604800000 - CLOUD_AWS_S3_BUCKET=${{ secrets.CLOUD_AWS_S3_BUCKET }} - CLOUD_AWS_CREDENTIALS_ACCESS_KEY=${{ secrets.CLOUD_AWS_CREDENTIALS_ACCESS_KEY }} - CLOUD_AWS_CREDENTIALS_SECRET_KEY=${{ secrets.CLOUD_AWS_CREDENTIALS_SECRET_KEY }} - EXTERNAL_API_FAST_API_URL=${{ secrets.EXTERNAL_API_FAST_API_URL }} - DISCORD_WEBHOOK_URL=${{ secrets.DISCORD_WEBHOOK_URL }} - OPENAI_API_KEY=${{ secrets.OPENAI_API_KEY }} - SENTRY_DSN=${{ secrets.SENTRY_DSN }} - ADMIN_IDENTIFIER=${{ secrets.ADMIN_IDENTIFIER }} - ADMIN_PASSWORD=${{ secrets.ADMIN_PASSWORD }} - EOF - shell: bash - - # 10. Docker Compose로 배포 - - name: Deploy with Docker Compose - run: | - # MySQL과 Redis가 없으면 시작 (최초 배포 시) - docker-compose up -d mysql redis - - # Spring Boot 앱만 재시작 (기존 컨테이너 중지 후 새로 시작) - docker-compose stop app || true - docker-compose rm -f app || true - docker-compose up -d app - - # 헬스체크 대기 (최대 2분) - echo "Waiting for application to be healthy..." - timeout=120 - elapsed=0 - while [ $elapsed -lt $timeout ]; do - if docker-compose ps app | grep -q "healthy"; then - echo "Application is healthy!" - break - fi - echo "Waiting... ($elapsed seconds)" - sleep 5 - elapsed=$((elapsed + 5)) - done - - # 컨테이너 상태 확인 - docker-compose ps - - # 로그 출력 (마지막 50줄) - echo "=== Application Logs ===" - docker-compose logs --tail=50 app - shell: bash - - # 11. 오래된 Docker 이미지 정리 - - name: Clean up old Docker images - run: | - # 24시간 이상 된 dangling 이미지 삭제 - docker image prune -f --filter "until=24h" - - # 사용하지 않는 볼륨 정리 (선택사항) - # docker volume prune -f - shell: bash - continue-on-error: true # 정리 실패해도 워크플로우는 성공으로 처리 - - # 12. Slack/Discord 알림 (선택사항) - - name: Send deployment notification - if: always() # 성공/실패 관계없이 항상 실행 - run: | - STATUS="${{ job.status }}" - COLOR="3066993" # 파란색 (성공) - if [ "$STATUS" != "success" ]; then - COLOR="15158332" # 빨간색 (실패) - fi - - curl -X POST "${{ secrets.DISCORD_WEBHOOK_URL }}" \ - -H "Content-Type: application/json" \ - -d "{ - \"embeds\": [{ - \"title\": \"🚀 Deployment $STATUS\", - \"description\": \"Branch: \`${{ github.ref_name }}\`\nCommit: \`${{ github.sha }}\`\nAuthor: ${{ github.actor }}\", - \"color\": $COLOR, - \"timestamp\": \"$(date -u +%Y-%m-%dT%H:%M:%S.000Z)\" - }] - }" - shell: bash - continue-on-error: true \ No newline at end of file diff --git a/.github/workflows/prod_docker_gradle.yml b/.github/workflows/prod_docker_gradle.yml deleted file mode 100644 index 9887d64b..00000000 --- a/.github/workflows/prod_docker_gradle.yml +++ /dev/null @@ -1,76 +0,0 @@ -#name: DOCKER CI IN PRODUCTION SERVER # 워크플로우의 이름 설정 -# -#on: -# push: -# branches: ["main"] # main 브랜치에 푸시될 때 워크플로우 실행 -# -#permissions: -# contents: read # 워크플로우의 권한 설정 (read-only) -# -#jobs: -# build: -# -# runs-on: ubuntu-latest # 워크플로우가 실행될 환경 설정 (Ubuntu 최신 버전) -# -# steps: -# # 코드 체크아웃: GitHub Actions가 현재 리포지토리의 코드를 가져옵니다. -# - uses: actions/checkout@v3 -# -# # JDK 17 설정: Java 17 버전을 사용하기 위해 JDK를 설치합니다. -# - name: Set up JDK 17 -# uses: actions/setup-java@v3 -# with: -# java-version: '17' # JDK 버전 17 설정 -# distribution: 'temurin' # Temurin JDK 배포판 사용 -# -# # application.properties 파일 생성: dev 환경의 설정 파일을 생성하고 secrets에서 값을 가져와 입력합니다. -# - name: make application.properties -# run: | -# cd ./src/main/resources # resources 디렉토리로 이동 -# touch ./application.yml # application.properties 파일 생성 -# echo "${{ secrets.APPLICATION_PROD }}" > ./application.yml # GitHub Secrets에서 설정값을 가져와 파일에 저장 -# -# # Gradle Wrapper 실행 권한 부여: gradlew에 실행 권한을 부여합니다. -# - name: Grant execute permission for gradlew -# run: chmod +x gradlew -# -# # Gradle 빌드: Gradle을 사용해 프로젝트를 빌드하되, 테스트는 생략합니다. -# - name: Build with Gradle -# run: ./gradlew build -x test # 테스트는 실행하지 않고 빌드만 수행 -# -# # Docker 이미지 빌드 및 푸시 -# - name: Docker build -# run: | -# docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} # Docker Hub에 로그인 -# docker build -t app . # Docker 이미지를 'app'이라는 이름으로 빌드 -# docker tag app ${{ secrets.DOCKER_USERNAME }}/ono:latest # 이미지를 Docker Hub 저장소로 태깅 -# docker push ${{ secrets.DOCKER_USERNAME }}/ono:latest # 이미지를 Docker Hub에 푸시 -# -# # Bastion 서버를 통해 스프링 서버로 배포 -# - name: Deploy via Bastion Server -# uses: appleboy/ssh-action@master -# with: -# host: ${{ secrets.PROD_BASTION_HOST }} # Bastion 서버의 퍼블릭 IP 또는 DNS 주소 -# username: ubuntu # Bastion 서버의 사용자 이름 -# key: ${{ secrets.PROD_BASTION_PRIVATE_KEY }} # Bastion 서버의 SSH 개인 키 (GitHub Secrets에서 가져옴) -# port: 22 # SSH 연결에 사용할 포트 (기본값 22) -# script: | -# sudo usermod -aG docker ubuntu -# sudo chmod 666 /var/run/docker.sock -# # Bastion 서버에서 스프링 서버로 SSH 연결 및 도커 작업 수행 -# ssh -o StrictHostKeyChecking=no -i /home/ubuntu/dev-an2-ono-test-spring-key.pem ubuntu@${{ secrets.PROD_SPRING_SERVER_IP }} << "EOSSH" -# # 스프링 서버에서 Docker Hub에 로그인 -# docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }} -# # 최신 Docker 이미지를 Docker Hub에서 Pull -# docker pull ${{ secrets.DOCKER_USERNAME }}/ono:latest -# # 실행 중인 모든 컨테이너를 중지 (실행 중인 컨테이너가 없을 경우 오류 무시) -# docker stop $(docker ps -a -q) || true -# # 중지된 모든 컨테이너를 제거 (없을 경우 오류 무시) -# docker rm $(docker ps -a -q) || true -# # 새로 받은 이미지를 기반으로 컨테이너 실행 (8080 포트 사용) -# docker run -d --restart unless-stopped --log-driver=syslog -p 8080:8080 ${{ secrets.DOCKER_USERNAME }}/ono:latest -# # 24시간 동안 사용되지 않은 모든 Docker 이미지를 삭제하여 공간 확보 -# docker image prune -a -f --filter "until=24h" -# EOSSH -#TODO -#FirebaseAdminKey.json 파일 생성하기 \ No newline at end of file From e816359737af3edb633a9552b390cddbd9f38f90 Mon Sep 17 00:00:00 2001 From: KiSeungMin Date: Tue, 23 Dec 2025 23:38:51 +0900 Subject: [PATCH 20/20] =?UTF-8?q?[chore]=20workflow=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=99=84=EB=A3=8C.=20=EB=B8=8C=EB=9E=9C=EC=B9=98?= =?UTF-8?q?=EB=AA=85=20=EC=9B=90=EC=83=81=EB=B3=B5=EA=B5=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/deploy-dev.yml | 2 +- .github/workflows/deploy-prod.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/deploy-dev.yml b/.github/workflows/deploy-dev.yml index d3687f38..1e2b1372 100644 --- a/.github/workflows/deploy-dev.yml +++ b/.github/workflows/deploy-dev.yml @@ -2,7 +2,7 @@ name: Deploy to Development Server (Mac Mini) on: push: - branches: ["deploy-develop-test"] # develop 브랜치에 푸시될 때 개발 배포 + branches: ["develop"] # develop 브랜치에 푸시될 때 개발 배포 workflow_dispatch: # 수동 실행 가능 permissions: diff --git a/.github/workflows/deploy-prod.yml b/.github/workflows/deploy-prod.yml index 148df313..3b967fd3 100644 --- a/.github/workflows/deploy-prod.yml +++ b/.github/workflows/deploy-prod.yml @@ -2,7 +2,7 @@ name: Deploy to Production Server (Mac Mini) on: push: - branches: ["deploy-prod-test"] # main 브랜치에 푸시될 때 운영 배포 + branches: ["main"] # main 브랜치에 푸시될 때 운영 배포 workflow_dispatch: # 수동 실행 가능 permissions: