Merge remote-tracking branch 'origin/main' into deploy #3
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
| # =================================================================== | |
| # Python FastAPI 전용 CI/CD 배포 워크플로우 | |
| # =================================================================== | |
| name: PROJECT-PYTHON-CICD | |
| # =================================================================== | |
| # 📋 필수 GitHub Secrets 설정 가이드 | |
| # =================================================================== | |
| # | |
| # ⚠️ 사용하기 전에 반드시 다음 GitHub Secrets를 설정하세요! | |
| # (저장소 Settings > Secrets and variables > Actions에서 설정) | |
| # | |
| # 🔧 필수 Secrets: | |
| # ┌─────────────────────────────┬────────────────────────────────────┐ | |
| # │ Secret 이름 │ 설명 │ | |
| # ├─────────────────────────────┼────────────────────────────────────┤ | |
| # │ DOCKERHUB_USERNAME │ DockerHub 사용자명 │ | |
| # │ DOCKERHUB_TOKEN │ DockerHub 액세스 토큰 │ | |
| # │ SERVER_HOST │ 배포 대상 서버 IP/도메인 │ | |
| # │ SERVER_USER │ 서버 SSH 접속 사용자명 │ | |
| # │ SERVER_PASSWORD │ 서버 SSH 접속 비밀번호 │ | |
| # │ ENV │ .env 파일 전체 내용 │ | |
| # └─────────────────────────────┴────────────────────────────────────┘ | |
| # | |
| # 🧪 선택적 Secrets (test 브랜치 사용시에만): | |
| # ┌─────────────────────────────┬────────────────────────────────────┐ | |
| # │ PYTHON_TEST_PORT │ test 브랜치 배포 포트 (기본: 8001) │ | |
| # └─────────────────────────────┴────────────────────────────────────┘ | |
| # | |
| # =================================================================== | |
| # =================================================================== | |
| # 트리거 설정 | |
| # =================================================================== | |
| on: | |
| push: | |
| branches: | |
| - deploy # 프로덕션 배포 (필수) | |
| - test # 테스트 환경 배포 (선택사항) | |
| workflow_dispatch: # 수동 실행 허용 | |
| # =================================================================== | |
| # 환경 변수 설정 | |
| # =================================================================== | |
| env: | |
| # 🔧 프로젝트 설정 | |
| PROJECT_NAME: "mapsee-ai" | |
| PROJECT_MAIN_PORT: "8092" | |
| # 🐍 Python 설정 | |
| PYTHON_VERSION: "3.13" | |
| jobs: | |
| # =================================================================== | |
| # 빌드 작업 | |
| # =================================================================== | |
| build: | |
| name: Python FastAPI 애플리케이션 빌드 | |
| runs-on: ubuntu-latest | |
| steps: | |
| # 1. 소스코드 체크아웃 | |
| - name: 코드 체크아웃 | |
| uses: actions/checkout@v4 | |
| # 2. 디스크 공간 확보 | |
| - name: 디스크 공간 확보 | |
| run: | | |
| echo "📊 빌드 전 디스크 사용량:" | |
| df -h | |
| echo "🧹 불필요한 파일 정리 중..." | |
| sudo rm -rf /usr/share/dotnet || true | |
| sudo rm -rf /opt/ghc || true | |
| sudo rm -rf /usr/local/share/boost || true | |
| sudo rm -rf "$AGENT_TOOLSDIRECTORY" || true | |
| echo "🐳 Docker 시스템 정리 중..." | |
| docker system prune -af --volumes || true | |
| echo "📊 정리 후 디스크 사용량:" | |
| df -h | |
| # 3. .env 파일 생성 | |
| - name: .env 파일 생성 | |
| run: | | |
| cat > .env << 'EOF' | |
| ${{ secrets.ENV }} | |
| EOF | |
| echo "✅ .env 파일이 생성되었습니다" | |
| # 4. Docker 빌드 환경 설정 | |
| - name: Docker 빌드환경 설정 | |
| uses: docker/setup-buildx-action@v3 | |
| # 5. DockerHub 로그인 | |
| - name: DockerHub 로그인 | |
| uses: docker/login-action@v3 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| # 6. Docker 이미지 빌드 및 푸시 | |
| - name: Docker 이미지 빌드 및 푸시 | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./Dockerfile | |
| push: true | |
| tags: ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.PROJECT_NAME }}:${{ github.ref_name }} | |
| # GitHub Actions 캐시 사용 (로컬 디스크 공간 절약) | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| # 7. 빌드 후 정리 | |
| - name: 빌드 후 정리 | |
| if: always() | |
| run: | | |
| echo "🧹 빌드 후 정리 중..." | |
| docker system prune -f || true | |
| echo "📊 최종 디스크 사용량:" | |
| df -h | |
| # =================================================================== | |
| # 배포 작업 | |
| # =================================================================== | |
| deploy: | |
| name: 원격 서버 배포 | |
| needs: build | |
| runs-on: ubuntu-latest | |
| steps: | |
| # SSH를 통한 원격 서버 배포 실행 | |
| - name: Deploy | |
| uses: appleboy/ssh-action@v1.0.3 | |
| with: | |
| host: ${{ secrets.SERVER_HOST }} | |
| username: ${{ secrets.SERVER_USER }} | |
| password: ${{ secrets.SERVER_PASSWORD }} | |
| port: 2022 | |
| command_timeout: 600s # 명령 실행 타임아웃 10분 | |
| timeout: 60s # SSH 연결 타임아웃 60초 | |
| script: | | |
| set -e | |
| # ============================================================ | |
| # 배포 환경 변수 설정 | |
| # ============================================================ | |
| echo "🔧 환경변수 설정.." | |
| export PATH=$PATH:/usr/local/bin | |
| export PW=${{ secrets.SERVER_PASSWORD }} | |
| # GitHub에서 전달받은 브랜치명 | |
| BRANCH=${{ github.ref_name }} | |
| # 프로젝트 설정 | |
| PROJECT_NAME="${{ env.PROJECT_NAME }}" | |
| # ============================================================ | |
| # 브랜치별 포트 및 컨테이너명 설정 | |
| # ============================================================ | |
| # 기본값 설정 | |
| PORT=8000 | |
| CONTAINER_NAME="${PROJECT_NAME}" | |
| # 브랜치에 따른 환경별 설정 | |
| if [ "$BRANCH" == "main" ] || [ "$BRANCH" == "deploy" ]; then | |
| # 🏭 프로덕션 환경 (main/deploy 브랜치) | |
| PORT=${{ env.PROJECT_MAIN_PORT }} | |
| CONTAINER_NAME="${PROJECT_NAME}" | |
| echo "🏭 프로덕션 환경으로 배포합니다" | |
| elif [ "$BRANCH" == "test" ]; then | |
| # 🧪 테스트 환경 (test 브랜치) | |
| PORT=${{ secrets.PYTHON_TEST_PORT}} | |
| CONTAINER_NAME="${PROJECT_NAME}-test" | |
| echo "🧪 테스트 환경으로 배포합니다" | |
| else | |
| # ⚠️ 기타 브랜치 | |
| echo "⚠️ 지원하지 않는 브랜치입니다: $BRANCH" | |
| exit 1 | |
| fi | |
| # 설정 정보 출력 | |
| echo "📋 배포 설정 정보:" | |
| echo " - 브랜치: $BRANCH" | |
| echo " - 프로젝트: $PROJECT_NAME" | |
| echo " - 컨테이너 이름: $CONTAINER_NAME" | |
| echo " - 포트: $PORT" | |
| echo " - Docker 이미지: ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:${BRANCH}" | |
| # ============================================================ | |
| # Docker 이미지 풀 (Pull) | |
| # ============================================================ | |
| echo "⬇️ Docker 이미지 풀: ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:${BRANCH}" | |
| echo $PW | sudo -S docker pull ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:${BRANCH} | |
| # ============================================================ | |
| # 기존 컨테이너 정리 | |
| # ============================================================ | |
| echo "🧹 컨테이너 $CONTAINER_NAME 존재 여부 확인 중..." | |
| # 동일한 이름의 컨테이너가 존재하는지 확인 | |
| if echo $PW | sudo -S docker ps -a --format '{{.Names}}' | grep -Eq "^${CONTAINER_NAME}\$"; then | |
| echo "⚠️ 컨테이너 $CONTAINER_NAME 이(가) 존재합니다. 중지 및 삭제 중..." | |
| echo $PW | sudo -S docker rm -f $CONTAINER_NAME | |
| echo "✅ 컨테이너 $CONTAINER_NAME 이(가) 삭제되었습니다." | |
| else | |
| echo "ℹ️ 존재하는 컨테이너 $CONTAINER_NAME 이(가) 없습니다." | |
| fi | |
| # ============================================================ | |
| # 새 컨테이너 실행 | |
| # ============================================================ | |
| echo "🚀 새로운 컨테이너 $CONTAINER_NAME 실행 중..." | |
| # Docker 컨테이너 실행 | |
| # - 포트 매핑: ${PORT}:8000 (외부포트:내부포트) | |
| # - 시간대: Asia/Seoul | |
| # - 볼륨 마운트: 로컬 시간 동기화 및 프로젝트 데이터 | |
| # ⚠️ .env 파일은 이미 Docker 이미지에 포함되어 있습니다 | |
| echo $PW | sudo -S docker run -d \ | |
| -p ${PORT}:8000 \ | |
| --name $CONTAINER_NAME \ | |
| -e TZ=Asia/Seoul \ | |
| -v /etc/localtime:/etc/localtime:ro \ | |
| -v /volume1/projects/mapsee/ai:/mnt/mapsee \ | |
| ${{ secrets.DOCKERHUB_USERNAME }}/${PROJECT_NAME}:${BRANCH} | |
| # ============================================================ | |
| # 컨테이너 헬스체크 | |
| # ============================================================ | |
| echo "⏳ 컨테이너 초기화 대기 중... (10초)" | |
| sleep 10 | |
| echo "🏥 컨테이너 헬스체크 중..." | |
| if echo $PW | sudo -S docker ps --format '{{.Names}}' | grep -Eq "^${CONTAINER_NAME}\$"; then | |
| echo "✅ 컨테이너 $CONTAINER_NAME 이(가) 정상적으로 실행 중입니다" | |
| else | |
| echo "❌ 컨테이너 $CONTAINER_NAME 실행 실패" | |
| echo "📋 컨테이너 로그:" | |
| echo $PW | sudo -S docker logs $CONTAINER_NAME || true | |
| exit 1 | |
| fi | |
| # ============================================================ | |
| # 배포 완료 확인 | |
| # ============================================================ | |
| echo "✅ 배포가 성공적으로 완료되었습니다!" | |
| echo "" | |
| echo "📋 배포 결과 요약:" | |
| echo " 🎯 프로젝트: $PROJECT_NAME" | |
| echo " 🌿 브랜치: $BRANCH" | |
| echo " 🐳 컨테이너: $CONTAINER_NAME" | |
| echo " 🌐 포트: $PORT" | |
| echo " ⏰ 배포 시간: $(date '+%Y-%m-%d %H:%M:%S')" | |
| echo "" | |
| echo "🔗 접속 URL: http://${{ secrets.SERVER_HOST }}:${PORT}/docs" |