-
Notifications
You must be signed in to change notification settings - Fork 2
[EPIC] 개발-배포-운영 파이프라인 안정성 강화 #259
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
c6412b0
refactor(test) : 사용하지 않는 테스트 임시 주석처리
jsoonworld 19db26e
refactor(user) : 초기화 구분 워닝 메시지 개선하고, 와일드 카드 제거
jsoonworld 4aeef2c
test: 테스트 환경 구축 및 설정 분리
jsoonworld fd3198c
refactor: 환경 변수를 사용하도록 yml 설정 구조 개선
jsoonworld ca23c8d
test: 테스트 환경 구축 및 설정 분리
jsoonworld 993e318
ci: 환경 변수 기반의 배포 파이프라인으로 개편
jsoonworld 4b981eb
chore(db) : 호환성 문제 임시 해결
jsoonworld File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,132 @@ | ||
| name: DOCKER-CD-PRODUCTION | ||
|
|
||
| on: | ||
| push: | ||
| branches: [ "main" ] | ||
|
|
||
| jobs: | ||
| ci: | ||
| runs-on: ubuntu-24.04 | ||
|
|
||
| steps: | ||
| - name: Checkout | ||
| uses: actions/checkout@v3 | ||
|
|
||
| - name: Set up JDK 21 | ||
| uses: actions/setup-java@v3 | ||
| with: | ||
| distribution: 'temurin' | ||
| java-version: '21' | ||
|
|
||
| - name: Gradle Caching | ||
| 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: Build and Test with Gradle | ||
| run: | | ||
| chmod +x gradlew | ||
| ./gradlew build | ||
| shell: bash | ||
|
|
||
| - name: Login to Docker Hub | ||
| uses: docker/login-action@v2.2.0 | ||
| with: | ||
| username: ${{ secrets.DOCKER_LOGIN_USERNAME }} | ||
| password: ${{ secrets.DOCKER_LOGIN_ACCESSTOKEN }} | ||
|
|
||
| - name: Build and push Docker image for Production | ||
| run: | | ||
| docker build --platform linux/amd64 -t terningpoint/terning2025 . | ||
| docker push terningpoint/terning2025 | ||
|
|
||
| cd: | ||
| needs: ci | ||
| runs-on: ubuntu-24.04 | ||
| environment: production | ||
|
|
||
| steps: | ||
| - name: Deploy to Production Server | ||
| uses: appleboy/ssh-action@master | ||
| with: | ||
| host: ${{ secrets.SERVER_IP }} | ||
| username: ${{ secrets.SERVER_USER }} | ||
| key: ${{ secrets.SERVER_KEY }} | ||
| script: | | ||
| # -- 변수 설정 -- | ||
| APP_NAME="terning2025-prod" | ||
| IMAGE_NAME="terningpoint/terning2025" | ||
| NGINX_CONFIG_PATH="/etc/nginx" | ||
| SERVICE_URL_INC_PATH="${NGINX_CONFIG_PATH}/conf.d/service-url.inc" | ||
|
|
||
| echo "### 1. 최신 Docker 이미지를 pull합니다." | ||
| docker pull ${IMAGE_NAME}:latest | ||
|
|
||
| echo "### 2. 현재 실행 중인 포트(Blue)와 새로 실행할 포트(Green)를 결정합니다." | ||
| RUNNING_PORT=$(docker ps --filter "name=${APP_NAME}" --format "{{.Ports}}" | grep -o '[0-9]\{4\}->8080' | awk -F'->' '{print $1}') | ||
|
|
||
| if [ "${RUNNING_PORT}" == "8080" ]; then | ||
| NEW_PORT=8081 | ||
| else | ||
| NEW_PORT=8080 | ||
| fi | ||
|
|
||
| echo " > 현재 서비스 포트(Blue): ${RUNNING_PORT:-없음}" | ||
| echo " > 새로 실행할 포트(Green): ${NEW_PORT}" | ||
|
|
||
| echo "### 3. 새로운 버전의 애플리케이션(Green)을 실행합니다." | ||
| docker run -d --name ${APP_NAME}-${NEW_PORT} --restart always \ | ||
| -p ${NEW_PORT}:8080 \ | ||
| -e SPRING_PROFILES_ACTIVE=prod \ | ||
| -e SPRING_DATASOURCE_URL='${{ secrets.DB_URL }}' \ | ||
| -e SPRING_DATASOURCE_USERNAME=${{ secrets.DB_USERNAME }} \ | ||
| -e SPRING_DATASOURCE_PASSWORD=${{ secrets.DB_PASSWORD }} \ | ||
| -e SPRING_JPA_DEFAULT_SCHEMA=${{ secrets.SPRING_JPA_DEFAULT_SCHEMA }} \ | ||
| -e JWT_SECRET_KEY='${{ secrets.JWT_SECRET_KEY }}' \ | ||
| -e JWT_ACCESS_TOKEN_EXPIRED=${{ secrets.JWT_ACCESS_TOKEN_EXPIRED }} \ | ||
| -e JWT_REFRESH_TOKEN_EXPIRED=${{ secrets.JWT_REFRESH_TOKEN_EXPIRED }} \ | ||
| -e OPERATION_BASE_URL='${{ secrets.OPERATION_BASE_URL }}' \ | ||
| -e DISCORD_WEBHOOK_URL='${{ secrets.DISCORD_WEBHOOK_URL }}' \ | ||
| -e FIREBASE_SERVICE_KEY_JSON='${{ secrets.FIREBASE_SERVICE_KEY_JSON }}' \ | ||
| -e LOGGING_LOCATION=${{ secrets.LOGGING_LOCATION }} \ | ||
| -e TZ=Asia/Seoul \ | ||
| -v /home/ubuntu:/home/ubuntu/prod-logs \ | ||
| ${IMAGE_NAME}:latest | ||
|
|
||
| echo "### 4. 헬스 체크를 시작합니다." | ||
| sleep 10 | ||
| for retry_count in {1..10}; do | ||
| echo " > [${retry_count}/10] 서버 상태 체크 중..." | ||
| response=$(curl -s http://localhost:${NEW_PORT}/actuator/health) | ||
| up_count=$(echo "$response" | grep -c 'UP') | ||
|
|
||
| if [ $up_count -ge 1 ]; then | ||
| echo " > ✅ 서버 실행 성공 (포트: ${NEW_PORT})" | ||
| break | ||
| fi | ||
| if [ $retry_count -eq 10 ]; then | ||
| echo " > ❌ 서버 헬스체크 실패. 배포를 중단하고 새 컨테이너를 종료합니다." | ||
| docker rm -f ${APP_NAME}-${NEW_PORT} | ||
| exit 1 | ||
| fi | ||
| sleep 5 | ||
| done | ||
|
|
||
| echo "### 5. Nginx 설정을 변경하여 트래픽을 새 포트(Green)로 전환합니다." | ||
| echo "set \$service_url http://127.0.0.1:${NEW_PORT};" | sudo tee ${SERVICE_URL_INC_PATH} | ||
| sudo nginx -s reload | ||
|
|
||
| echo "### 6. 이전 버전의 컨테이너(Blue)를 종료 및 삭제합니다." | ||
| if [ -n "${RUNNING_PORT}" ]; then | ||
| docker rm -f ${APP_NAME}-${RUNNING_PORT} | ||
| fi | ||
|
|
||
| echo "### 7. 사용하지 않는 Docker 이미지를 정리합니다." | ||
| docker image prune -af | ||
|
|
||
| echo "✅ Production 배포가 성공적으로 완료되었습니다. 현재 서비스 포트: ${NEW_PORT}" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
현재 스크립트가 긴데, 중간에 하나의 명령어가 실패하더라도 다음 명령어를 계속 실행할 수 있는 상태라 set -e를 스크립트 상단에 추가하는 것은 어떨까요? 명령어가 하나라도 실패하면 스크립트 전체를 중단시키도록 설정하는게 좋을 것 같아서 제안드려봅니다 ㅎㅎ
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
꼼꼼하게 리뷰해주셔서 감사합니다! 👍
말씀해주신 대로 set -e 옵션을 추가해서 스크립트의 안정성을 높이는 것, 정말 좋은 제안이라고 생각합니다. 중간에 명령어가 실패했을 때 즉시 파이프라인을 중단시키는 것이 더 안전한 방법이겠네요.
다만 현재 PR에서는 핵심 기능 구현에 더 집중하고 싶습니다. 제안해주신 내용은 파이프라인 안정성 강화라는 좋은 개선 과제이니, 별도 이슈로 등록해서 다음 단계에서 꼭 반영하도록 하겠습니다.
다시 한번 좋은 의견 감사드립니다! 😊