diff --git a/.github/ISSUE_TEMPLATE/ci.md b/.github/ISSUE_TEMPLATE/ci.md new file mode 100644 index 0000000..c0bcaa9 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/ci.md @@ -0,0 +1,20 @@ +--- +name: "CI/CD" +about: 배포 작업 템플릿입니다. +title: "ci/cd: " +labels: ci +assignees: '' + +--- + +# Title + +- title + +# TODO + +- [ ] write what to do + +# etc + +- nothing diff --git a/.github/ISSUE_TEMPLATE/docs.md b/.github/ISSUE_TEMPLATE/docs.md new file mode 100644 index 0000000..e907a29 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/docs.md @@ -0,0 +1,20 @@ +--- +name: "DOCS" +about: 문서 작업 템플릿입니다. +title: "docs: " +labels: docs +assignees: '' + +--- + +# Title + +- title + +# TODO + +- [ ] write what to do + +# etc + +- nothing diff --git a/.github/ISSUE_TEMPLATE/feat.md b/.github/ISSUE_TEMPLATE/feat.md new file mode 100644 index 0000000..0a5101f --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feat.md @@ -0,0 +1,20 @@ +--- +name: "FEAT" +about: 기능 개발 템플릿입니다. +title: "feat: " +labels: feat +assignees: '' + +--- + +# Title + +- title + +# TODO + +- [ ] write what to do + +# etc + +- nothing diff --git a/.github/ISSUE_TEMPLATE/fix.md b/.github/ISSUE_TEMPLATE/fix.md new file mode 100644 index 0000000..cbe7685 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/fix.md @@ -0,0 +1,20 @@ +--- +name: "FIX" +about: 버그 수정 템플릿입니다. +title: "fix: " +labels: fix +assignees: '' + +--- + +# Title + +- title + +# TODO + +- [ ] write what to do + +# etc + +- nothing diff --git a/.github/ISSUE_TEMPLATE/refactor.md b/.github/ISSUE_TEMPLATE/refactor.md new file mode 100644 index 0000000..a720cb6 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/refactor.md @@ -0,0 +1,20 @@ +--- +name: "REFACTOR" +about: 리팩토링 템플릿입니다. +title: "️refactor: " +labels: refactor +assignees: '' + +--- + +# Title + +- title + +# TODO + +- [ ] write what to do + +# etc + +- nothing diff --git a/.github/ISSUE_TEMPLATE/test.md b/.github/ISSUE_TEMPLATE/test.md new file mode 100644 index 0000000..36a32bf --- /dev/null +++ b/.github/ISSUE_TEMPLATE/test.md @@ -0,0 +1,20 @@ +--- +name: "TEST" +about: 테스트 작업 템플릿입니다. +title: "test: " +labels: test +assignees: '' + +--- + +# Title + +- title + +# TODO + +- [ ] write what to do + +# etc + +- nothing diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml new file mode 100644 index 0000000..7631faf --- /dev/null +++ b/.github/workflows/deploy.yml @@ -0,0 +1,97 @@ +name: CI/CD with Git Actions & Docker Hub test + +on: + pull_request: + branches: + - master + - develop + +jobs: + build: + runs-on: ubuntu-latest + + env: + SPRING_PROFILE: ${{ github.base_ref == 'master' && 'prod' || 'dev' }} + PRIVATE_IP: ${{ github.base_ref == 'master' && secrets.PRIVATE_IP || secrets.DEV_PRIVATE_IP }} + REPOSITORY: ${{ github.base_ref == 'master' && secrets.DOCKERHUB_REPOSITORY || secrets.DEV_DOCKERHUB_REPOSITORY }} + APPLICATION_YML: ${{ github.base_ref == 'master' && secrets.APPLICATION_YML_PROD || secrets.APPLICATION_YML_DEV }} + + steps: + - name: Checkout source code + uses: actions/checkout@v3 + + - name: Set up JDK 21 + uses: actions/setup-java@v3 + with: + java-version: '21' + distribution: 'temurin' + + - name: Grant execute permission to gradlew + run: chmod +x ./gradlew + + - name: Create application-{profile}.yml + run: | + mkdir -p src/main/resources + echo "${{ env.APPLICATION_YML }}" > src/main/resources/application-${{ env.SPRING_PROFILE }}.yml + + - name: Build with Gradle + run: ./gradlew clean :bootJar + + - name: Login to Docker Hub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Build and push Docker image + run: | + docker build \ + --build-arg SPRING_PROFILE=${{ env.SPRING_PROFILE }} \ + -t ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:${{ secrets.DOCKERHUB_TAG }} \ + --platform linux/amd64 . + + docker push ${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:${{ secrets.DOCKERHUB_TAG }} + + - name: Deploy at EC2 instance through Bastion Host + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.BASTION_SSH_HOST }} # Bastion Host 퍼블릭 IP + username: ubuntu + key: ${{ secrets.BASTION_SSH_KEY }} + port: ${{ secrets.BASTION_SSH_PORT }} + script: | + echo "✅ Bastion Host 접속 완료" + + # Private EC2에 SSH 접속 후 배포 수행 + ssh -i "${{secrets.DIRECTORY_PEM}}" ubuntu@${{ env.PRIVATE_IP }} << 'EOF' + echo "✅ Private EC2 접속 완료" + + IMAGE_NAME="${{ secrets.DOCKERHUB_USERNAME }}/${{ env.REPOSITORY }}:${{ secrets.DOCKERHUB_TAG }}" + CONTAINER_NAME="${{ secrets.DOCKERHUB_TAG }}" + + echo "🔹 Docker 로그인" + docker login -u "${{ secrets.DOCKERHUB_USERNAME }}" -p "${{ secrets.DOCKERHUB_TOKEN }}" + + echo "🔹 기존 컨테이너($CONTAINER_NAME) 중지 및 삭제" + if [ "$(sudo docker ps -q -f name=$CONTAINER_NAME)" ]; then + sudo docker stop "$CONTAINER_NAME" + sudo docker rm "$CONTAINER_NAME" + else + echo "ℹ️ $CONTAINER_NAME 컨테이너가 실행 중이지 않음" + fi + + echo "🔹 기존 이미지($IMAGE_NAME) 삭제" + if [ "$(sudo docker images -q $IMAGE_NAME)" ]; then + sudo docker rmi "$IMAGE_NAME" + else + echo "ℹ️ 삭제할 이미지 없음: $IMAGE_NAME" + fi + + echo "🔹 새로운 Docker 이미지 Pull" + sudo docker pull "$IMAGE_NAME" + + echo "🔹 컨테이너 실행" + sudo docker run -d --name "$CONTAINER_NAME" --network=drinkly -p 8888:8888 --restart unless-stopped "$IMAGE_NAME" + + echo "🚀 배포 완료" + EOF diff --git a/.gitignore b/.gitignore index b3db3e2..071ba39 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ out/ .vscode/ application.yml +/src/main/resources/application-*.yml diff --git a/Dockerfile b/Dockerfile index d05511c..93f6c9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,9 @@ FROM openjdk:21 -# JAR 복사 -COPY ./build/libs/config-server.jar config-server.jar - -# 기본 ENV 설정 (선택) -ENV SPRING_PROFILE=prod +ARG SPRING_PROFILE=prod +ENV SPRING_PROFILE=$SPRING_PROFILE ENV TZ=Asia/Seoul -# ENTRYPOINT에서 외부 환경 변수를 기반으로 실행 -ENTRYPOINT ["sh", "-c", "java -Dspring.profiles.active=${SPRING_PROFILE} -Duser.timezone=${TZ} -jar config-server.jar"] +COPY ./build/libs/config-server.jar config-server.jar + +ENTRYPOINT ["sh", "-c", "java -Dspring.profiles.active=${SPRING_PROFILE} -Duser.timezone=${TZ} -jar config-server.jar"] \ No newline at end of file diff --git a/src/main/resources/application-dev.yml b/src/main/resources/application-dev.yml deleted file mode 100644 index 5d6d9bd..0000000 --- a/src/main/resources/application-dev.yml +++ /dev/null @@ -1,49 +0,0 @@ -server: - port: 8888 # Config Server 포트 - -eureka: - client: - region: ap-northeast-2 - service-url: - defaultZone: http://eureka-server:8761/eureka/ # Eureka 서버 주소 - register-with-eureka: true # Eureka에 등록 - fetch-registry: true # 다른 서비스 목록 가져오기 - -spring: - application: - name: config-server # 서비스 이름 - - cloud: - config: - server: - git: - uri: https://github.com/JuseungL/Config-Server-Test.git - username: JuseungL - password: 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 - clone-on-start: true - search-paths: - - member-service - - store-service - - coupon-service - - gateway - - payment-service - default-label: main - - rabbitmq: - host: rabbitmq - port: 5672 - username: guest - password: guest - - -management: - endpoints: - web: - base-path: /api/v1/config # 기본 엔드포인트 경로 변경 - exposure: - include: refresh, health, beans, httptrace, busrefresh - endpoint: - health: - show-details: always - bus-refresh: - enabled: true diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml deleted file mode 100644 index 1171257..0000000 --- a/src/main/resources/application-local.yml +++ /dev/null @@ -1,49 +0,0 @@ -server: - port: 8888 # Config Server 포트 - -eureka: - client: - region: ap-northeast-2 - service-url: - defaultZone: http://localhost:8761/eureka/ # Eureka 서버 주소 - register-with-eureka: true # Eureka에 등록 - fetch-registry: true # 다른 서비스 목록 가져오기 - -spring: - application: - name: config-server # 서비스 이름 - - cloud: - config: - server: - git: - uri: https://github.com/JuseungL/Config-Server-Test.git - username: JuseungL - password: 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 - clone-on-start: true - search-paths: - - member-service - - store-service - - coupon-service - - gateway - - payment-service - default-label: main - - rabbitmq: - host: rabbitmq - port: 5672 - username: guest - password: guest - - -management: - endpoints: - web: - base-path: /api/v1/config # 기본 엔드포인트 경로 변경 - exposure: - include: refresh, health, beans, httptrace, busrefresh - endpoint: - health: - show-details: always - bus-refresh: - enabled: true diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml deleted file mode 100644 index 5d6d9bd..0000000 --- a/src/main/resources/application-prod.yml +++ /dev/null @@ -1,49 +0,0 @@ -server: - port: 8888 # Config Server 포트 - -eureka: - client: - region: ap-northeast-2 - service-url: - defaultZone: http://eureka-server:8761/eureka/ # Eureka 서버 주소 - register-with-eureka: true # Eureka에 등록 - fetch-registry: true # 다른 서비스 목록 가져오기 - -spring: - application: - name: config-server # 서비스 이름 - - cloud: - config: - server: - git: - uri: https://github.com/JuseungL/Config-Server-Test.git - username: JuseungL - password: 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 - clone-on-start: true - search-paths: - - member-service - - store-service - - coupon-service - - gateway - - payment-service - default-label: main - - rabbitmq: - host: rabbitmq - port: 5672 - username: guest - password: guest - - -management: - endpoints: - web: - base-path: /api/v1/config # 기본 엔드포인트 경로 변경 - exposure: - include: refresh, health, beans, httptrace, busrefresh - endpoint: - health: - show-details: always - bus-refresh: - enabled: true