From 8e0d17a77fa506723898f30fd092d0d2cbcc6187 Mon Sep 17 00:00:00 2001 From: Sejeong Kim <64718002+clean2001@users.noreply.github.com> Date: Tue, 12 Nov 2024 20:43:42 +0900 Subject: [PATCH] =?UTF-8?q?chore:=20=EC=84=9C=EB=B2=84=20ncp=20->=20aws?= =?UTF-8?q?=EB=A1=9C=20=EC=9D=B4=EC=A0=84=20(#257)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * chore: test * chore: test * chore: StoredCredential 삭제 * chore: Dockerfile 수정 * chore: aws-cicd yml 수정 * chore: docker compose 변경(Docker-dev, prod 분리) * chore: docker compose 변경(Docker-dev, prod 분리) * chore: build 부분 수정 * chore: docker build 부분 수정 * chore: docker build 부분 수정 * chore: docker build 부분 수정 * chore: cicd-prod.ym ldocker build 부분 수정 * chore: cicd-prod.yml 오타 수정 * chore: prod > deploy.sh 작성 * chore: prod > blue,green 추가 * chore: prod > blue,green 추가 * chore: prod > blue,green 추가 * chore: docker-compose depends_on 수정 * chore: deploy 수정 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: docker-compse 테스트 * chore: dev test * chore: dev test * chore: prod test * chore: prod nginx conf 변경 * chore: prod nginx conf 변경 * chore: github actionsa 파일 브랜치 명 변경 * chore: batch db 엔드포인트 변경 * chore: 포트번호 변경 * chore: depends on 변경 * chore: 포트 변경 * chore: 포트 변경 * chore: blue green sh 수정 * chore: blue green sh 수정 * chore: docker compose 수정 * chore: sh 수정 * chore: 포트 수정 * chore: 포트 수정 * chore: dns 수정 * chore: localhost로 수정 * chore: 배치 로그 추가 * chore: Dockefile 수정 * chore: 크론 임시 변경 * chore: 도커 파일 변경 * chore: 도커 파일 이름 지정 * chore: batch yml 추가 * chore: no-cache 추가 * chore: Dockerfile 이름 변경 * chore: deploy.sh 변경 * chore: 2분마다로 변경 테스트 * chore: now 로그 추가 * chore: 스케줄러 1시간 단위로 변경 --- .github/workflows/aws-cicd-dev.yml | 164 ++++++++++++++++ .github/workflows/aws-cicd-prod.yml | 179 ++++++++++++++++++ .github/workflows/k3s-dev.yaml | 2 +- .github/workflows/k3s-prod.yaml | 2 +- .gitignore | 2 + layer-api/{Dockerfile => Dockerfile-dev} | 8 +- layer-api/Dockerfile-prod | 4 + .../infra/development/docker-compose.yaml | 20 +- layer-api/infra/production/application.yml | 66 +++++++ layer-api/infra/production/deploy.sh | 66 +++++++ .../infra/production/docker-compose-blue.yaml | 33 ++++ .../production/docker-compose-green.yaml | 33 ++++ .../infra/production/docker-compose.yaml | 41 ---- layer-api/infra/production/nginx.blue.conf | 19 ++ layer-api/infra/production/nginx.green.conf | 19 ++ .../java/org/layer/config/SecurityConfig.java | 1 + .../org/layer/domain/etc/TempController.java | 13 ++ .../src/main/resources/application-dev.yml | 13 +- .../src/main/resources/application-local.yml | 5 +- .../src/main/resources/application-prod.yml | 24 ++- layer-api/src/main/resources/tokens/.gitkeep | 0 layer-batch/{Dockerfile => Dockerfile-batch} | 2 +- .../batch/scheduler/RetrospectScheduler.java | 2 + .../src/main/resources/application.yml | 6 +- .../main/resources/tokens/StoredCredential | Bin 0 -> 1130 bytes tokens/StoredCredential | Bin 0 -> 1130 bytes 26 files changed, 652 insertions(+), 72 deletions(-) create mode 100644 .github/workflows/aws-cicd-dev.yml create mode 100644 .github/workflows/aws-cicd-prod.yml rename layer-api/{Dockerfile => Dockerfile-dev} (55%) create mode 100644 layer-api/Dockerfile-prod create mode 100644 layer-api/infra/production/application.yml create mode 100644 layer-api/infra/production/deploy.sh create mode 100644 layer-api/infra/production/docker-compose-blue.yaml create mode 100644 layer-api/infra/production/docker-compose-green.yaml delete mode 100644 layer-api/infra/production/docker-compose.yaml create mode 100644 layer-api/infra/production/nginx.blue.conf create mode 100644 layer-api/infra/production/nginx.green.conf create mode 100644 layer-api/src/main/java/org/layer/domain/etc/TempController.java create mode 100644 layer-api/src/main/resources/tokens/.gitkeep rename layer-batch/{Dockerfile => Dockerfile-batch} (56%) create mode 100644 layer-batch/src/main/resources/tokens/StoredCredential create mode 100644 tokens/StoredCredential diff --git a/.github/workflows/aws-cicd-dev.yml b/.github/workflows/aws-cicd-dev.yml new file mode 100644 index 00000000..5f6144d7 --- /dev/null +++ b/.github/workflows/aws-cicd-dev.yml @@ -0,0 +1,164 @@ +name: deploy action + +on: + push: + branches: + - develop + +env: + REGISTRY: "docker.io" + NAMESPACE: "clean01" + IMAGE_NAME: "layer-server" + +jobs: + setup: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + outputs: + deploy_target: ${{ steps.set-env.outputs.DEPLOY_TARGET }} + steps: + - name: Setup Env + id: set-env + run: | + echo "DEPLOY_TARGET=development" >> $GITHUB_OUTPUT + + build: + name: build + needs: [ setup ] + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + env: + DEPLOY_TARGET: ${{ needs.setup.outputs.deploy_target }} + REGISTRY: "docker.io" + NAMESPACE: "clean01" + APPLICATION_SECRET_PROPERTIES: ${{ secrets.AWS_APPLICATION_SECRET_PROPERTIES }} + GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} + + steps: + - name: Setup Java + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'corretto' + + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Setup Gradle + uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 + + - name: Create application-secret.properties + run: | + echo "${APPLICATION_SECRET_PROPERTIES}" > ./layer-api/src/main/resources/application-secret.properties + echo "${APPLICATION_SECRET_PROPERTIES}" > ./layer-batch/src/main/resources/application-secret.properties + + - name: Build layer-api module + run: ./gradlew :layer-api:build + + - name: Test layer-api module + run: ./gradlew :layer-api:test + + - name: Build layer-batch module + run: ./gradlew :layer-batch:build + + - name: Test layer-batch module + run: ./gradlew :layer-batch:test + + - name: Docker Hub Login + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_EMAIL }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: | + ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}_layer-api + ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}_layer-batch + + - name: Push layer-api Docker Image + uses: docker/build-push-action@v4 + with: + context: ./layer-api + file: ./layer-api/Dockerfile-dev # Dockerfile 이름 지정 + platforms: linux/amd64 + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}_layer-api:latest + + + - name: Push layer-batch Docker Image + uses: docker/build-push-action@v4 + with: + context: ./layer-batch + platforms: linux/amd64 + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}_layer-batch:latest + + deploy: + name: Deploy + needs: [ build, setup ] + runs-on: ubuntu-latest + env: + DEPLOY_TARGET: ${{ needs.setup.outputs.deploy_target }} + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Create application-secret.properties file + run: | + echo "${{ secrets.APPLICATION_SECRET_PROPERTIES }}" > ./layer-api/infra/${{ env.DEPLOY_TARGET }}/application-secret.properties + echo "${{ secrets.APPLICATION_SECRET_PROPERTIES }}" > ./layer-batch/src/main/resources/application-secret.properties + + - name: Archive Files + run: | + tar -cvzf layer-api.tar.gz ./layer-api/infra/${{ env.DEPLOY_TARGET }}/ + + - name: Send Docker Compose + uses: appleboy/scp-action@master + with: + host: ${{ secrets.AWS_DEV_INSTANCE_HOST }} + username: ubuntu + key: ${{ secrets.AWS_INSTANCE_PEM }} + port: 22 + source: "layer-api.tar.gz" + target: "/home/ubuntu" + + - name: Extract Files on Server and Set Permissions + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_DEV_INSTANCE_HOST }} + username: ubuntu + key: ${{ secrets.AWS_INSTANCE_PEM }} + port: 22 + script: | + cd /home/ubuntu + tar -xvzf layer-api.tar.gz + sudo chmod -R 755 /home/ubuntu/layer-api/infra/${{ env.DEPLOY_TARGET }} + sudo chown -R ubuntu:ubuntu /home/ubuntu/layer-api/infra/${{ env.DEPLOY_TARGET }} + + + - name: Deploy with Docker Compose + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_DEV_INSTANCE_HOST }} + username: ubuntu + key: ${{ secrets.AWS_INSTANCE_PEM }} + port: 22 + script: | + sudo apt update + sudo apt install docker-ce + sudo apt install docker-compose + sudo docker login --username ${{ secrets.DOCKER_EMAIL }} --password ${{ secrets.DOCKER_PASSWORD }} + cd /home/ubuntu/layer-api/infra/${{ env.DEPLOY_TARGET }} + sudo docker-compose pull && sudo docker-compose up -d + sudo docker image prune -a -f diff --git a/.github/workflows/aws-cicd-prod.yml b/.github/workflows/aws-cicd-prod.yml new file mode 100644 index 00000000..6b3c8eb9 --- /dev/null +++ b/.github/workflows/aws-cicd-prod.yml @@ -0,0 +1,179 @@ +name: deploy action + +on: + push: + branches: + - main + - chore/migration + +env: + REGISTRY: "docker.io" + NAMESPACE: "clean01" + IMAGE_NAME: "layer-server" + +jobs: + setup: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + outputs: + deploy_target: ${{ steps.set-env.outputs.DEPLOY_TARGET }} + steps: + - name: Setup Env + id: set-env + run: | + echo "DEPLOY_TARGET=production" >> $GITHUB_OUTPUT + + build: + name: build + needs: [ setup ] + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + env: + DEPLOY_TARGET: ${{ needs.setup.outputs.deploy_target }} + REGISTRY: "docker.io" + NAMESPACE: "clean01" + APPLICATION_SECRET_PROPERTIES: ${{ secrets.AWS_APPLICATION_SECRET_PROPERTIES }} + GOOGLE_CREDENTIALS: ${{ secrets.GOOGLE_CREDENTIALS }} + + steps: + - name: Setup Java + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'corretto' + + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Setup Gradle + uses: gradle/gradle-build-action@bd5760595778326ba7f1441bcf7e88b49de61a25 # v2.6.0 + + - name: Create application-secret.properties + run: | + echo "${APPLICATION_SECRET_PROPERTIES}" > ./layer-api/src/main/resources/application-secret.properties + echo "${APPLICATION_SECRET_PROPERTIES}" > ./layer-batch/src/main/resources/application-secret.properties + + - name: Build layer-api module + run: ./gradlew :layer-api:build + + - name: Test layer-api module + run: ./gradlew :layer-api:test + + - name: Build layer-batch module + run: ./gradlew :layer-batch:build + + - name: Test layer-batch module + run: ./gradlew :layer-batch:test + + - name: Docker Hub Login + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_EMAIL }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Extract metadata (tags, labels) for Docker + id: meta + uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + with: + images: | + ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}_layer-api + ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}_layer-batch + + - name: Push layer-api Docker Image + uses: docker/build-push-action@v4 + with: + context: ./layer-api + file: ./layer-api/Dockerfile-prod # Dockerfile 이름 지정 + platforms: linux/amd64 + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}_layer-api:latest + no-cache: true + + - name: Push layer-batch Docker Image + uses: docker/build-push-action@v4 + with: + context: ./layer-batch + file: ./layer-batch/Dockerfile-batch # Dockerfile 이름 지정 + platforms: linux/amd64 + push: true + tags: | + ${{ env.REGISTRY }}/${{ env.NAMESPACE }}/${{ env.IMAGE_NAME }}_layer-batch:latest + no-cache: true + + deploy: + name: Deploy + needs: [ build, setup ] + runs-on: ubuntu-latest + env: + DEPLOY_TARGET: ${{ needs.setup.outputs.deploy_target }} + + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Create application-secret.properties file + run: | + echo "${{ secrets.APPLICATION_SECRET_PROPERTIES }}" > ./layer-api/infra/${{ env.DEPLOY_TARGET }}/application-secret.properties + echo "${{ secrets.APPLICATION_SECRET_PROPERTIES }}" > ./layer-batch/src/main/resources/application-secret.properties + + - name: Archive Files + run: | + tar -cvzf layer-api.tar.gz ./layer-api/infra/${{ env.DEPLOY_TARGET }}/ + + - name: Send Docker Compose + uses: appleboy/scp-action@master + with: + host: ${{ secrets.AWS_PROD_INSTANCE_HOST }} + username: ubuntu + key: ${{ secrets.AWS_INSTANCE_PEM }} + port: 22 + source: "layer-api.tar.gz" + target: "/home/ubuntu" + + - name: Extract Files on Server and Set Permissions + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_PROD_INSTANCE_HOST }} + username: ubuntu + key: ${{ secrets.AWS_INSTANCE_PEM }} + port: 22 + script: | + cd /home/ubuntu + tar -xvzf layer-api.tar.gz + sudo chmod -R 755 /home/ubuntu/layer-api/infra/${{ env.DEPLOY_TARGET }} + sudo chown -R ubuntu:ubuntu /home/ubuntu/layer-api/infra/${{ env.DEPLOY_TARGET }} + + + - name: Set Permissions on Transferred Files + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_PROD_INSTANCE_HOST }} + username: ubuntu + key: ${{ secrets.AWS_INSTANCE_PEM }} + port: 22 + script: | + sudo chmod -R 755 /home/ubuntu/layer-api/infra/${{ env.DEPLOY_TARGET }} + sudo chown -R ubuntu:ubuntu /home/ubuntu/layer-api/infra/${{ env.DEPLOY_TARGET }} + + - name: Deploy with Docker Compose + uses: appleboy/ssh-action@master + with: + host: ${{ secrets.AWS_PROD_INSTANCE_HOST }} + username: ubuntu + key: ${{ secrets.AWS_INSTANCE_PEM }} + port: 22 + script: | + sudo apt update + sudo apt install docker-ce + sudo apt install docker-compose + sudo docker login --username ${{ secrets.DOCKER_EMAIL }} --password ${{ secrets.DOCKER_PASSWORD }} + cd /home/ubuntu/layer-api/infra/${{ env.DEPLOY_TARGET }} + chmod 777 ./deploy.sh + ./deploy.sh + sudo docker image prune -a -f diff --git a/.github/workflows/k3s-dev.yaml b/.github/workflows/k3s-dev.yaml index 35a596a5..aeb1b7b5 100644 --- a/.github/workflows/k3s-dev.yaml +++ b/.github/workflows/k3s-dev.yaml @@ -3,7 +3,7 @@ name: Spring Boot Multi-module K3s Deployment on: push: branches: - - develop + - develop-test # 실행되지 않도록 브랜치 명 변경 env: REGISTRY: "ghcr.io" diff --git a/.github/workflows/k3s-prod.yaml b/.github/workflows/k3s-prod.yaml index cfbbc34a..30cb74cb 100644 --- a/.github/workflows/k3s-prod.yaml +++ b/.github/workflows/k3s-prod.yaml @@ -3,7 +3,7 @@ name: Spring Boot Multi-module K3s Deployment on: push: branches: - - main + - main-test # 실행되지 않도록 브랜치 명 변경 env: REGISTRY: "ghcr.io" diff --git a/.gitignore b/.gitignore index 074a5fa9..e0630052 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,5 @@ log/ credentials.json +layer-api/src/main/resources/tokens/StoredCredential +layer-batch/src/main/resources/application-secret.properties \ No newline at end of file diff --git a/layer-api/Dockerfile b/layer-api/Dockerfile-dev similarity index 55% rename from layer-api/Dockerfile rename to layer-api/Dockerfile-dev index 04505691..cbb49e2e 100644 --- a/layer-api/Dockerfile +++ b/layer-api/Dockerfile-dev @@ -1,10 +1,4 @@ FROM openjdk:17 - ARG JAR_FILE=./build/libs/*.jar -ARG SPRING_PROFILE - COPY ${JAR_FILE} layer-server.jar - -ENV SPRING_PROFILE=${SPRING_PROFILE} - -ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=${SPRING_PROFILE}" ,"-jar" ,"layer-server.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=dev" ,"-jar" ,"layer-server.jar"] \ No newline at end of file diff --git a/layer-api/Dockerfile-prod b/layer-api/Dockerfile-prod new file mode 100644 index 00000000..1cc729ea --- /dev/null +++ b/layer-api/Dockerfile-prod @@ -0,0 +1,4 @@ +FROM openjdk:17 +ARG JAR_FILE=./build/libs/*.jar +COPY ${JAR_FILE} layer-server.jar +ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=prod" ,"-jar" ,"layer-server.jar"] \ No newline at end of file diff --git a/layer-api/infra/development/docker-compose.yaml b/layer-api/infra/development/docker-compose.yaml index 5d664994..edd2b8c9 100644 --- a/layer-api/infra/development/docker-compose.yaml +++ b/layer-api/infra/development/docker-compose.yaml @@ -1,6 +1,6 @@ services: java-app: - image: ghcr.io/depromeet/kasukabe-server/layer-api:latest + image: docker.io/clean01/layer-server_layer-api:latest container_name: layer-api ports: - "8080:8080" @@ -14,6 +14,21 @@ services: networks: - app-network + batch-job: + image: docker.io/clean01/layer-server_layer-batch:latest # + container_name: layer-batch + environment: + - TZ=Asia/Seoul + volumes: + - ./application-secret.properties:/config/application-secret.properties + - ./log:/log + - ./tokens:/config/tokens + networks: + - app-network + depends_on: + - java-app + restart: always + nginx: image: nginx:latest container_name: nginx @@ -27,5 +42,4 @@ services: - app-network networks: - app-network: - driver: bridge + app-network: \ No newline at end of file diff --git a/layer-api/infra/production/application.yml b/layer-api/infra/production/application.yml new file mode 100644 index 00000000..bb74f7fd --- /dev/null +++ b/layer-api/infra/production/application.yml @@ -0,0 +1,66 @@ +server: + port: 8085 + +spring: + config: + import: application-secret.properties + datasource: + url: ${AWS_PROD_DB_URL} + username: ${AWS_PROD_DB_NAME} + password: ${AWS_PROD_DB_PASSWORD} + driver-class-name: com.mysql.cj.jdbc.Driver + jpa: + hibernate: + ddl-auto: update + properties: + hibernate: + format_sql: true + show_sql: true + open-in-view: false + database: mysql + +apple: + login: + issuer: ${DEV_APPLE_ISSUER} + client_id: ${DEV_APPLE_CLIENT_ID} + audience: ${DEV_APPLE_AUD} + +kakao: + login: + api_key: ${DEV_KAKAO_API_KEY} + redirect_uri: ${DEV_KAKAO_REDIRECT_URI} + uri: + base: https://kauth.kakao.com + code: /oauth/authorize + token: /oauth/token + api: + uri: + base: https://kapi.kakao.com + user: /v2/user/me + +google: + login: + client_id: ${DEV_GOOGLE_CLIENT_ID} + code_uri: ${DEV_GOOGLE_CODE_URI} + token_uri: ${DEV_GOOGLE_TOKEN_URI} + client_secret: ${DEV_GOOGLE_CLIENT_SECRET} + redirect_uri: ${DEV_GOOGLE_REDIRECT_URI} + code_redirect_uri: http://localhost:8080/api/auth/oauth2/google/code + sheet: + id: ${GOOGLE_SHEET_ID} + token_path: ${PROD_GOOGLE_TOKEN_PATH} + credential_path: ${PROD_GOOGLE_CREDENTIAL_PATH} + +ncp: + storage: + region: ${STORAGE_REGION} + bucketName: ${STORAGE_NAME} + endpoint: ${STORAGE_ENDPOINT} + accessKey: ${STORAGE_ACCESS_KEY} + secretKey: ${STORAGE_SECRET_KEY} + +openai: + systemContent: ${OPENAI_SYSTEM_CONTENT} + apiKey: ${OPENAI_API_KEY} + model: ${OPENAI_MODEL} + maxTokens: ${OPENAI_MAX_TOKENS} \ No newline at end of file diff --git a/layer-api/infra/production/deploy.sh b/layer-api/infra/production/deploy.sh new file mode 100644 index 00000000..00e8d950 --- /dev/null +++ b/layer-api/infra/production/deploy.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +IS_GREEN=$(sudo docker ps | grep layer-api-green) # 현재 실행중인 App이 blue인지 확인합니다. +DEFAULT_CONF="/etc/nginx/nginx.conf" + + +if [ -z $IS_GREEN ];then # blue라면 + + echo "### BLUE => GREEN ###" + + echo "1. get green image" + cd ./layer-api/infra/production + + echo "1.1. pull latest green image" + sudo docker-compose -f docker-compose-green.yaml pull + + echo "2. green container up" + sudo docker-compose -f docker-compose-green.yaml up -d + + while [ 1 = 1 ]; do + echo "3. green health check..." + sudo sleep 3 + + REQUEST=$(sudo curl http://127.0.0.1:8080/greeting) # green으로 request + if [ -n "$REQUEST" ]; then # 서비스 가능하면 health check 중지 + echo "health check success" + break ; + fi + done; + + echo "4. reload nginx" + sudo cp ./nginx.green.conf /etc/nginx/nginx.conf + sudo nginx -s reload + + echo "5. blue container down" + sudo sudo docker-compose -f docker-compose-blue.yaml down +else + echo "### GREEN => BLUE ###" + echo "1. get blue image" + cd ./layer-api/infra/production + + echo "1.1. pull latest blue image" + sudo docker-compose -f docker-compose-blue.yaml pull + + echo "2. blue container up" + sudo docker-compose -f docker-compose-blue.yaml up -d + + + while [ 1 = 1 ]; do + echo "3. blue health check..." + sleep 3 + REQUEST=$(curl http://127.0.0.1:8081/greeting) # blue로 request + + if [ -n "$REQUEST" ]; then # 서비스 가능하면 health check 중지 + echo "health check success" + break ; + fi + done; + + echo "4. reload nginx" + sudo cp ./nginx.blue.conf /etc/nginx/nginx.conf + sudo nginx -s reload + + echo "5. green container down" + sudo sudo docker-compose -f docker-compose-green.yaml down +fi \ No newline at end of file diff --git a/layer-api/infra/production/docker-compose-blue.yaml b/layer-api/infra/production/docker-compose-blue.yaml new file mode 100644 index 00000000..82d57859 --- /dev/null +++ b/layer-api/infra/production/docker-compose-blue.yaml @@ -0,0 +1,33 @@ +services: + layer-api-blue: + image: docker.io/clean01/layer-server_layer-api:latest + container_name: layer-api-blue + ports: + - "8081:8080" + environment: + - TZ=Asia/Seoul + - SPRING_PROFILES_ACTIVE=prod + volumes: + - ./application-secret.properties:/config/application-secret.properties + - ./log:/log + - ./tokens:/config/tokens + networks: + - app-network + + batch-job-blue: + image: docker.io/clean01/layer-server_layer-batch:latest + container_name: layer-batch-blue + environment: + - TZ=Asia/Seoul + volumes: + - ./application-secret.properties:/config/application-secret.properties + - ./log:/log + - ./tokens:/config/tokens + networks: + - app-network + depends_on: + - layer-api-blue + restart: always + +networks: + app-network: \ No newline at end of file diff --git a/layer-api/infra/production/docker-compose-green.yaml b/layer-api/infra/production/docker-compose-green.yaml new file mode 100644 index 00000000..bf36a0b6 --- /dev/null +++ b/layer-api/infra/production/docker-compose-green.yaml @@ -0,0 +1,33 @@ +services: + layer-api-green: + image: docker.io/clean01/layer-server_layer-api:latest + container_name: layer-api-green + ports: + - "8080:8080" + environment: + - TZ=Asia/Seoul + - SPRING_PROFILES_ACTIVE=prod + volumes: + - ./application-secret.properties:/config/application-secret.properties + - ./log:/log + - ./tokens:/config/tokens + networks: + - app-network + + batch-job-green: + image: docker.io/clean01/layer-server_layer-batch:latest + container_name: layer-batch-green + environment: + - TZ=Asia/Seoul + volumes: + - ./application-secret.properties:/config/application-secret.properties + - ./log:/log + - ./tokens:/config/tokens + networks: + - app-network + depends_on: + - layer-api-green + restart: always + +networks: + app-network: \ No newline at end of file diff --git a/layer-api/infra/production/docker-compose.yaml b/layer-api/infra/production/docker-compose.yaml deleted file mode 100644 index 954d959f..00000000 --- a/layer-api/infra/production/docker-compose.yaml +++ /dev/null @@ -1,41 +0,0 @@ -services: - redis: - image: redis:latest - container_name: redis - ports: - - "6379:6379" - networks: - - app-network - - java-app: - image: ghcr.io/depromeet/kasukabe-server/layer-api:latest - container_name: layer-api - depends_on: - - redis - ports: - - "8080:8080" - environment: - - TZ=Asia/Seoul - - SPRING_PROFILES_ACTIVE=prod - volumes: - - type: bind - source: ./config/application.yaml - target: ./application.yaml - networks: - - app-network - - nginx: - image: nginx:latest - container_name: nginx - depends_on: - - java-app - ports: - - "80:80" - volumes: - - ./nginx.conf:/etc/nginx/nginx.conf - networks: - - app-network - -networks: - app-network: - driver: bridge diff --git a/layer-api/infra/production/nginx.blue.conf b/layer-api/infra/production/nginx.blue.conf new file mode 100644 index 00000000..326ea474 --- /dev/null +++ b/layer-api/infra/production/nginx.blue.conf @@ -0,0 +1,19 @@ +events { } + +http { + upstream layer-api { + server localhost:8081; + } + + server { + listen 80; + + location / { + proxy_pass http://layer-api; + 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; + } + } +} \ No newline at end of file diff --git a/layer-api/infra/production/nginx.green.conf b/layer-api/infra/production/nginx.green.conf new file mode 100644 index 00000000..a7f4110b --- /dev/null +++ b/layer-api/infra/production/nginx.green.conf @@ -0,0 +1,19 @@ +events { } + +http { + upstream layer-api { + server localhost:8080; + } + + server { + listen 80; + + location / { + proxy_pass http://layer-api; + 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; + } + } +} \ No newline at end of file diff --git a/layer-api/src/main/java/org/layer/config/SecurityConfig.java b/layer-api/src/main/java/org/layer/config/SecurityConfig.java index ce833a59..266ed332 100644 --- a/layer-api/src/main/java/org/layer/config/SecurityConfig.java +++ b/layer-api/src/main/java/org/layer/config/SecurityConfig.java @@ -59,6 +59,7 @@ private void setHttp(HttpSecurity http) throws Exception { .requestMatchers(new AntPathRequestMatcher("/api/auth/oauth2/apple")).permitAll() .requestMatchers(new AntPathRequestMatcher("/api/auth/create-token")).permitAll() .requestMatchers(new AntPathRequestMatcher("/admin/**")).permitAll() + .requestMatchers(new AntPathRequestMatcher("/greeting")).permitAll() .anyRequest().authenticated() ) .headers(headers -> headers diff --git a/layer-api/src/main/java/org/layer/domain/etc/TempController.java b/layer-api/src/main/java/org/layer/domain/etc/TempController.java new file mode 100644 index 00000000..aef6a6d7 --- /dev/null +++ b/layer-api/src/main/java/org/layer/domain/etc/TempController.java @@ -0,0 +1,13 @@ +package org.layer.domain.etc; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +public class TempController { + @GetMapping("/greeting") + public String greeting(@Value("${greeting.message}") String greeting) { + return greeting; + } +} diff --git a/layer-api/src/main/resources/application-dev.yml b/layer-api/src/main/resources/application-dev.yml index 06aa6b02..9a0b49b0 100644 --- a/layer-api/src/main/resources/application-dev.yml +++ b/layer-api/src/main/resources/application-dev.yml @@ -1,10 +1,10 @@ spring: config: - import: optional:file:/config/application-secret.properties + import: application-secret.properties datasource: - url: ${DEV_DB_URL} - username: ${DEV_DB_NAME} - password: ${DEV_DB_PASSWORD} + url: ${AWS_DEV_DB_URL} + username: ${AWS_PROD_DB_NAME} + password: ${AWS_PROD_DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: @@ -80,4 +80,7 @@ openai: maxTokens: ${OPENAI_MAX_TOKENS} admin: - password: ${ADMIN_PASSWORD} \ No newline at end of file + password: ${ADMIN_PASSWORD} + +greeting: + message: this is dev \ No newline at end of file diff --git a/layer-api/src/main/resources/application-local.yml b/layer-api/src/main/resources/application-local.yml index c8fe1029..4e6ac6d3 100644 --- a/layer-api/src/main/resources/application-local.yml +++ b/layer-api/src/main/resources/application-local.yml @@ -85,4 +85,7 @@ openai: maxTokens: ${OPENAI_MAX_TOKENS} admin: - password: ${ADMIN_PASSWORD} \ No newline at end of file + password: ${ADMIN_PASSWORD} + +greeting: + message: this is local \ No newline at end of file diff --git a/layer-api/src/main/resources/application-prod.yml b/layer-api/src/main/resources/application-prod.yml index bb726150..dbfedc7a 100644 --- a/layer-api/src/main/resources/application-prod.yml +++ b/layer-api/src/main/resources/application-prod.yml @@ -1,10 +1,10 @@ spring: config: - import: optional:file:/config/application-secret.properties + import: application-secret.properties datasource: - url: ${PROD_DB_URL} - username: ${PROD_DB_NAME} - password: ${PROD_DB_PASSWORD} + url: ${AWS_PROD_DB_URL} + username: ${AWS_PROD_DB_NAME} + password: ${AWS_PROD_DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: @@ -18,12 +18,12 @@ spring: data: redis: - host: ${PROD_REDIS_HOST} - port: ${PROD_REDIS_PORT} - password: ${PROD_REDIS_PASSWORD} + host: ${DEV_REDIS_HOST} + port: ${DEV_REDIS_PORT} + password: ${DEV_REDIS_PASSWORD} jwt: - secret: ${PROD_JWT_SECRET} + secret: ${DEV_JWT_SECRET} kakao: login: @@ -41,8 +41,11 @@ kakao: google: login: client_id: ${DEV_GOOGLE_CLIENT_ID} + code_uri: ${DEV_GOOGLE_CODE_URI} + token_uri: ${DEV_GOOGLE_TOKEN_URI} client_secret: ${DEV_GOOGLE_CLIENT_SECRET} redirect_uri: ${DEV_GOOGLE_REDIRECT_URI} + code_redirect_uri: http://localhost:8080/api/auth/oauth2/google/code sheet: id: ${GOOGLE_SHEET_ID} token_path: ${PROD_GOOGLE_TOKEN_PATH} @@ -77,4 +80,7 @@ openai: maxTokens: ${OPENAI_MAX_TOKENS} admin: - password: ${ADMIN_PASSWORD} \ No newline at end of file + password: ${ADMIN_PASSWORD} + +greeting: + message: this is prod \ No newline at end of file diff --git a/layer-api/src/main/resources/tokens/.gitkeep b/layer-api/src/main/resources/tokens/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/layer-batch/Dockerfile b/layer-batch/Dockerfile-batch similarity index 56% rename from layer-batch/Dockerfile rename to layer-batch/Dockerfile-batch index ea09a3c3..1176e233 100644 --- a/layer-batch/Dockerfile +++ b/layer-batch/Dockerfile-batch @@ -7,4 +7,4 @@ COPY ${JAR_FILE} layer-batch.jar ENV SPRING_PROFILE=${SPRING_PROFILE} -ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul","-Dspring.profiles.active=prod" ,"-jar" ,"layer-batch.jar"] \ No newline at end of file +ENTRYPOINT ["java", "-Duser.timezone=Asia/Seoul" ,"-jar" ,"layer-batch.jar"] \ No newline at end of file diff --git a/layer-batch/src/main/java/org/layer/batch/scheduler/RetrospectScheduler.java b/layer-batch/src/main/java/org/layer/batch/scheduler/RetrospectScheduler.java index 9280f083..40f70f53 100644 --- a/layer-batch/src/main/java/org/layer/batch/scheduler/RetrospectScheduler.java +++ b/layer-batch/src/main/java/org/layer/batch/scheduler/RetrospectScheduler.java @@ -40,6 +40,8 @@ public void updateRetrospectStatusToDone() { List retrospects = retrospectRepository.findAllByDeadlineBeforeAndRetrospectStatus( now, RetrospectStatus.PROCEEDING); + + Map retrospectMap = retrospects.stream() .collect(Collectors.toMap(Retrospect::getId, retrospect -> retrospect)); diff --git a/layer-batch/src/main/resources/application.yml b/layer-batch/src/main/resources/application.yml index 326c8e7c..75718ee9 100644 --- a/layer-batch/src/main/resources/application.yml +++ b/layer-batch/src/main/resources/application.yml @@ -5,9 +5,9 @@ spring: config: import: application-secret.properties datasource: - url: ${PROD_DB_URL} - username: ${PROD_DB_NAME} - password: ${PROD_DB_PASSWORD} + url: ${AWS_PROD_DB_URL} + username: ${AWS_PROD_DB_NAME} + password: ${AWS_PROD_DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver jpa: hibernate: diff --git a/layer-batch/src/main/resources/tokens/StoredCredential b/layer-batch/src/main/resources/tokens/StoredCredential new file mode 100644 index 0000000000000000000000000000000000000000..63b1c6c17b9026d421421e9725d098cde63b28b2 GIT binary patch literal 1130 zcma)5L66%+6rN;vp>!*>Z~zGjq^dn|sGZo`>=N}*yh)vSv7Jqvgv}xW6MO88V|$YE zOq>M7v8vQVi&XvqCqRq1!U-WR9Jp}hKr4ZSs)`dA)KkaVN?R_~jx_J`-uJ%uzWL_( zAFz>9@Ja}0Q05FraucQ_3r;p({Qak&U;FsCHBi*S`G`PIhb|-3057o-Md^q{-h6WX zU67v(**Oun#4Rwe&QnA=1;r2cj{klAzZcGR9~1$YPXJhZe0)Nux+InZLV^g%aDrtw z!YE-fk)Cs3|u_Pv z>kAb5xdJQtDfkQ&<`V|~SU|NZ!?NaDJBpe)i!>ct4ZXv7Fx20Vc-Qu~r@D?QuTFc? z_O9L1=uy9}br!XyPI^map+vFTt#wB?+P#6*$e5<}m!ThHR38t!3ki=?hZ}<~VG6F= z^_^B6WKPEolPq+$tyz6GHJW&24LVev#P&hiqmtq_ss?4?{1wlIVx zw1#%ou`^vVs|KwdE%u%CqoAY1UNQ}(YCl}KjrQ13!!*>Z~zGjq^dn|sGZo`>=N}*yh)vSv7Jqvgv}xW6MO88V|$YE zOq>M7v8vQVi&XvqCqRq1!U-WR9Jp}hKr4ZSs)`dA)KkaVN?R_~jx_J`-uJ%uzWL_( zAFz>9@Ja}0Q05FraucQ_3r;p({Qak&U;FsCHBi*S`G`PIhb|-3057o-Md^q{-h6WX zU67v(**Oun#4Rwe&QnA=1;r2cj{klAzZcGR9~1$YPXJhZe0)Nux+InZLV^g%aDrtw z!YE-fk)Cs3|u_Pv z>kAb5xdJQtDfkQ&<`V|~SU|NZ!?NaDJBpe)i!>ct4ZXv7Fx20Vc-Qu~r@D?QuTFc? z_O9L1=uy9}br!XyPI^map+vFTt#wB?+P#6*$e5<}m!ThHR38t!3ki=?hZ}<~VG6F= z^_^B6WKPEolPq+$tyz6GHJW&24LVev#P&hiqmtq_ss?4?{1wlIVx zw1#%ou`^vVs|KwdE%u%CqoAY1UNQ}(YCl}KjrQ13!