From 98b7c03ba0b93fe0a40fd9ed0baa8f6e44969b1b Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Wed, 5 Nov 2025 01:43:49 +0900 Subject: [PATCH 01/15] =?UTF-8?q?fix:=20deprecated=EB=90=9C=20base=20image?= =?UTF-8?q?=EB=A5=BC=20eclipse-temurin:17-jdk=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 4 ++-- src/main/resources/secret | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 773d1ba16..8a067cefc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,5 +1,5 @@ # JDK 버전 설정 -FROM openjdk:17-jdk +FROM eclipse-temurin:17-jdk # JAR_FILE 변수 정의 ARG JAR_FILE=./build/libs/solid-connection-0.0.1-SNAPSHOT.jar @@ -11,4 +11,4 @@ COPY ${JAR_FILE} app.jar ENTRYPOINT ["java", "-jar", "/app.jar"] # 볼륨 설정 -VOLUME /tmp +VOLUME /tmp \ No newline at end of file diff --git a/src/main/resources/secret b/src/main/resources/secret index ae3e90ef7..b2fb51671 160000 --- a/src/main/resources/secret +++ b/src/main/resources/secret @@ -1 +1 @@ -Subproject commit ae3e90ef74f56e93be1ede280bbc5f330ca8e297 +Subproject commit b2fb5167196dd5f36703a8541eca03fcc3ea33a1 From 83d611f1ad8a5b92256638ed429726783d643983 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Wed, 5 Nov 2025 01:44:56 +0900 Subject: [PATCH 02/15] =?UTF-8?q?refactor:=20scp=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=A0=84=EC=86=A1=ED=95=98=EB=8A=94=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=97=90=EC=84=9C=20GHCR=EB=A1=9C=20push/pull=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 153 ++++++++++++++++++++++------------- docker-compose.dev.yml | 6 +- 2 files changed, 99 insertions(+), 60 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index f0d6d3cb0..82828ef80 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -10,6 +10,7 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + packages: write steps: - name: Checkout the code @@ -18,81 +19,121 @@ jobs: token: ${{ secrets.SUBMODULE_ACCESS_TOKEN }} submodules: true + # --- Java, Gradle 설정 --- - name: Set up JDK 17 uses: actions/setup-java@v4 with: java-version: '17' distribution: 'temurin' - - # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. - # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 - + uses: gradle/actions/setup-gradle@v3 - name: Grant execute permission for Gradle wrapper(gradlew) run: chmod +x ./gradlew - - name: Build with Gradle run: ./gradlew bootJar - - name: Copy jar file to remote - uses: appleboy/scp-action@master + # --- Docker 설정 --- + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 with: - host: ${{ secrets.DEV_HOST }} - username: ${{ secrets.DEV_USERNAME }} - key: ${{ secrets.DEV_PRIVATE_KEY }} - source: "./build/libs/*.jar" - target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/" - - - name: Copy docker file to remote - uses: appleboy/scp-action@master + platforms: linux/arm64 + - name: Log in to GitHub Container Registry (GHCR) + uses: docker/login-action@v3 with: - host: ${{ secrets.DEV_HOST }} - username: ${{ secrets.DEV_USERNAME }} - key: ${{ secrets.DEV_PRIVATE_KEY }} - source: "./Dockerfile" - target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/" + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Copy docker compose file to remote - uses: appleboy/scp-action@master - with: - host: ${{ secrets.DEV_HOST }} - username: ${{ secrets.DEV_USERNAME }} - key: ${{ secrets.DEV_PRIVATE_KEY }} - source: "./docker-compose.dev.yml" - target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/" + # --- 2. 이미지 메타데이터(이름, 태그) 정의 --- + # 빌드/푸시 단계와 SSH 단계에서 공통으로 사용할 변수를 미리 정의합니다. + - name: Define image name and tag + id: image_meta + run: | + OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + IMAGE_TAG=$(date +'%Y%m%d-%H%M%S') + echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev" >> $GITHUB_OUTPUT + echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT - - name: Copy alloy config file to remote - uses: appleboy/scp-action@master + # --- 3. Docker 이미지 빌드, 푸시, 캐시 --- + # 'docker/build-push-action'을 사용하여 캐시 옵션을 적용합니다. + - name: Build, push, and cache Docker image + uses: docker/build-push-action@v5 with: - host: ${{ secrets.DEV_HOST }} - username: ${{ secrets.DEV_USERNAME }} - key: ${{ secrets.DEV_PRIVATE_KEY }} - source: "./docs/infra-config/config.alloy" - target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/" + context: . + platforms: linux/arm64 + push: true + tags: ${{ format('{0}:{1}', steps.image_meta.outputs.image_name, steps.image_meta.outputs.image_tag) }} + cache-from: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache + cache-to: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max - - name: Copy nginx config to remote - uses: appleboy/scp-action@master - with: - host: ${{ secrets.DEV_HOST }} - username: ${{ secrets.DEV_USERNAME }} - key: ${{ secrets.DEV_PRIVATE_KEY }} - source: "./docs/infra-config/nginx.dev.conf" - target: "/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/nginx" - rename: "default.conf" + # --- 4. 설정 파일들만 scp로 전송 --- + - name: Copy config files to remote + run: | + echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key.pem + chmod 600 deploy_key.pem + + scp -i deploy_key.pem \ + -o StrictHostKeyChecking=no \ + ./docker-compose.dev.yml \ + ./docs/infra-config/config.alloy \ + ./docs/infra-config/nginx.dev.conf \ + ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }}:/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/ + # --- 5. 서버에서 'docker pull' 및 서비스 재시작 --- - name: Run docker compose and apply nginx config - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.DEV_HOST }} - username: ${{ secrets.DEV_USERNAME }} - key: ${{ secrets.DEV_PRIVATE_KEY }} - script_stop: true - script: | - sudo cp /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/nginx/default.conf /etc/nginx/conf.d/default.conf + run: | + echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key_ssh.pem + chmod 600 deploy_key_ssh.pem + + ssh -i deploy_key_ssh.pem \ + -o StrictHostKeyChecking=no \ + ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }} \ + ' + set -e + + # [수정] 1. 변수를 'image_meta' 단계의 출력값에서 가져옴 + export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + export IMAGE_TAG_ONLY=${{ steps.image_meta.outputs.image_tag }} + export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG_ONLY}" + + # 2. 서버가 GHCR에 로그인 (pull 받기 위해) + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + + # 3. docker pull (전체 이미지 이름 사용) + echo "Pulling new image layer from GHCR..." + docker pull $FULL_IMAGE_NAME + + # 4. 작업 디렉토리로 이동 및 Nginx 설정 이동 + cd /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev + mkdir -p ./nginx + mv ./nginx.dev.conf ./nginx/default.conf + + # 5. Nginx 재시작 + sudo cp ./nginx/default.conf /etc/nginx/conf.d/default.conf sudo nginx -t sudo nginx -s reload - - cd /home/${{ secrets.DEV_USERNAME }}/solid-connection-dev + + # 6. Docker Compose 재시작 + echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY" docker compose -f docker-compose.dev.yml down - docker compose -f docker-compose.dev.yml up -d --build + OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d + + # 7. 이미지 정리 + echo "Pruning dangling docker images..." + docker image prune -f + + echo "Deploy and Docker Compose restart finished." + ' + + # --- 6. 이미지 정리 --- + - name: Clean up old image versions from GHCR + if: success() + uses: snok/container-retention-policy@v2 + with: + token: ${{ secrets.GHCR_DELETE_TOKEN }} + image-names: solid-connection + delete-untagged: true + keep-n-tags: 5 + account-type: org + org-name: ${{ github.repository_owner }} + cut-off: '7 days ago UTC' \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index e20302c4b..cb0ef325c 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -18,9 +18,7 @@ services: - redis solid-connection-dev: - build: - context: . - dockerfile: Dockerfile + image: ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG:-latest} container_name: solid-connection-dev ports: - "8080:8080" @@ -43,4 +41,4 @@ services: - ./logs:/var/log/spring - ./docs/infra-config/config.alloy:/etc/alloy/config.alloy:ro environment: - - ALLOY_ENV=dev + - ALLOY_ENV=dev \ No newline at end of file From 216e83a34551e394fb3575ec9c018b8c2db69414 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Wed, 5 Nov 2025 01:56:49 +0900 Subject: [PATCH 03/15] =?UTF-8?q?fix:=20GHCR=20image=20=EC=A0=9C=EA=B1=B0?= =?UTF-8?q?=EC=8B=9C=20Org=EC=9D=98=20GITHUB=5FTOKEN=20=EC=82=AC=EC=9A=A9?= =?UTF-8?q?=ED=95=98=EB=8F=84=EB=A1=9D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 82828ef80..ebcf8079c 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -130,7 +130,7 @@ jobs: if: success() uses: snok/container-retention-policy@v2 with: - token: ${{ secrets.GHCR_DELETE_TOKEN }} + token: ${{ secrets.GITHUB_TOKEN }} image-names: solid-connection delete-untagged: true keep-n-tags: 5 From 898d594f40332ef6f69698dd5710084f6f301e64 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Wed, 5 Nov 2025 01:59:51 +0900 Subject: [PATCH 04/15] =?UTF-8?q?refactor=20:=20scp=20=ED=8C=8C=EC=9D=BC?= =?UTF-8?q?=20=EC=A0=84=EC=86=A1=ED=95=98=EB=8A=94=20=EB=B0=A9=EC=8B=9D?= =?UTF-8?q?=EC=97=90=EC=84=9C=20GHCR=EB=A1=9C=20push/pull=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20prod-cd.yml=EA=B3=BC=20docker-compose.prod?= =?UTF-8?q?.yml=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-cd.yml | 201 +++++++++++++++++++++------------- docker-compose.prod.yml | 4 +- 2 files changed, 124 insertions(+), 81 deletions(-) diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index d52c524c9..9e0a71953 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -10,89 +10,134 @@ jobs: runs-on: ubuntu-latest permissions: contents: read + packages: write steps: - - name: Checkout the code - uses: actions/checkout@v4 - with: - token: ${{ secrets.SUBMODULE_ACCESS_TOKEN }} - submodules: true + - name: Checkout the code + uses: actions/checkout@v4 + with: + token: ${{ secrets.SUBMODULE_ACCESS_TOKEN }} + submodules: true - - name: Set up JDK 17 - uses: actions/setup-java@v4 - with: - java-version: '17' - distribution: 'temurin' + # --- Java, Gradle 설정 (dev와 동일하게 버전 통일) --- + - name: Set up JDK 17 + uses: actions/setup-java@v4 + with: + java-version: '17' + distribution: 'temurin' + - name: Setup Gradle + uses: gradle/actions/setup-gradle@v3 + - name: Grant execute permission for Gradle wrapper(gradlew) + run: chmod +x ./gradlew + - name: Build with Gradle + run: ./gradlew bootJar - # Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies. - # See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md - - name: Setup Gradle - uses: gradle/actions/setup-gradle@417ae3ccd767c252f5661f1ace9f835f9654f2b5 # v3.1.0 + # --- 1. Docker 설정 --- + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + with: + platforms: linux/arm64 + - name: Log in to GitHub Container Registry (GHCR) + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} - - name: Grant execute permission for Gradle wrapper(gradlew) - run: chmod +x ./gradlew + # --- 2. 이미지 메타데이터(이름, 태그) 정의 --- + - name: Define image name and tag + id: image_meta + run: | + OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + IMAGE_TAG=$(date +'%Y%m%d-%H%M%S') + echo "image_name=ghcr.io/${OWNER_LOWERCASE}/solid-connection-server" >> $GITHUB_OUTPUT + echo "image_tag=${IMAGE_TAG}" >> $GITHUB_OUTPUT - - name: Build with Gradle - run: ./gradlew bootJar + # --- 3. Docker 이미지 빌드, 푸시, 캐시 --- + - name: Build, push, and cache Docker image + uses: docker/build-push-action@v5 + with: + context: . + platforms: linux/arm64 + push: true + tags: ${{ format('{0}:{1}', steps.image_meta.outputs.image_name, steps.image_meta.outputs.image_tag) }} + cache-from: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache + cache-to: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max + + # --- 4. 설정 파일들만 scp로 전송 --- + - name: Copy config files to remote + run: | + echo "${{ secrets.PRIVATE_KEY }}" > deploy_key.pem + chmod 600 deploy_key.pem - - name: Copy jar file to remote - uses: appleboy/scp-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.PRIVATE_KEY }} - source: "./build/libs/*.jar" - target: "/home/${{ secrets.USERNAME }}/solid-connect-server/" - - - name: Copy docker file to remote - uses: appleboy/scp-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.PRIVATE_KEY }} - source: "./Dockerfile" - target: "/home/${{ secrets.USERNAME }}/solid-connect-server/" - - - name: Copy docker compose file to remote - uses: appleboy/scp-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.PRIVATE_KEY }} - source: "./docker-compose.prod.yml" - target: "/home/${{ secrets.USERNAME }}/solid-connect-server/" - - - name: Copy alloy config file to remote - uses: appleboy/scp-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.PRIVATE_KEY }} - source: "./docs/infra-config/config.alloy" - target: "/home/${{ secrets.USERNAME }}/solid-connect-server/" - - - name: Copy nginx config to remote - uses: appleboy/scp-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.PRIVATE_KEY }} - source: "./docs/infra-config/nginx.prod.conf" - target: "/home/${{ secrets.USERNAME }}/solid-connection-prod/nginx" - rename: "default.conf" - - - name: Run docker compose and apply nginx config - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.HOST }} - username: ${{ secrets.USERNAME }} - key: ${{ secrets.PRIVATE_KEY }} - script_stop: true - script: | - sudo cp /home/${{ secrets.USERNAME }}/solid-connection-prod/nginx/default.conf /etc/nginx/conf.d/default.conf - sudo nginx -t - sudo nginx -s reload + scp -i deploy_key.pem \ + -o StrictHostKeyChecking:no \ + ./docker-compose.prod.yml \ + ./docs/infra-config/config.alloy \ + ./docs/infra-config/nginx.prod.conf \ + ${{ secrets.USERNAME }}@${{ secrets.HOST }}:/home/${{ secrets.USERNAME }}/solid-connection-prod/ + + # --- 5. 서버에서 'docker pull' 및 서비스 재시작 --- + - name: Run docker compose and apply nginx config + run: | + echo "${{ secrets.PRIVATE_KEY }}" > deploy_key_ssh.pem + chmod 600 deploy_key_ssh.pem + + ssh -i deploy_key_ssh.pem \ + -o StrictHostKeyChecking:no \ + ${{ secrets.USERNAME }}@${{ secrets.HOST }} \ + ' + set -e + + # 1. 변수 설정 + export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + export IMAGE_TAG_ONLY=${{ steps.image_meta.outputs.image_tag }} + export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-server:${IMAGE_TAG_ONLY}" + + # 2. 서버가 GHCR에 로그인 (pull 받기 위해) + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + + # 3. docker pull (전체 이미지 이름 사용) + echo "Pulling new image layer from GHCR..." + docker pull $FULL_IMAGE_NAME + + # 4. 작업 디렉토리로 이동 및 Nginx 설정 이동 + cd /home/${{ secrets.USERNAME }}/solid-connection-prod + mkdir -p ./nginx + mv ./nginx.prod.conf ./nginx/default.conf + + # 5. Nginx 재시작 + sudo cp ./nginx/default.conf /etc/nginx/conf.d/default.conf + sudo nginx -t + sudo nginx -s reload + + # 6. Docker Compose 재시작 (안정성 확보 로직 포함) + echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY" + echo "Stopping containers gracefully..." + docker compose -f docker-compose.prod.yml stop + + echo "Removing old containers and networks..." + docker compose -f docker-compose.prod.yml down --remove-orphans + + echo "Starting new containers..." + OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.prod.yml up -d + + # 7. 이미지 정리 + echo "Pruning dangling docker images..." + docker image prune -f + + echo "Deploy and Docker Compose restart finished." + ' - cd /home/${{ secrets.USERNAME }}/solid-connect-server - docker compose -f docker-compose.prod.yml down - docker compose -f docker-compose.prod.yml up -d --build + # --- 6. 이미지 정리 --- + - name: Clean up old image versions from GHCR + if: success() + uses: snok/container-retention-policy@v2 + with: + token: ${{ secrets.GITHUB_TOKEN }} + image-names: solid-connection-prod + delete-untagged: true + keep-n-tags: 5 + account-type: org + org-name: ${{ github.repository_owner }} + cut-off: '7 days ago UTC' \ No newline at end of file diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml index d805031d0..5b26eecf9 100644 --- a/docker-compose.prod.yml +++ b/docker-compose.prod.yml @@ -18,9 +18,7 @@ services: - redis solid-connection-server: - build: - context: . - dockerfile: Dockerfile + image: ghcr.io/${OWNER_LOWERCASE}/solid-connection-server:${IMAGE_TAG:-latest} container_name: solid-connection-server ports: - "8080:8080" From a76e446dddff79bd9ff943cde5af86a8fef1101d Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Wed, 5 Nov 2025 02:29:39 +0900 Subject: [PATCH 05/15] =?UTF-8?q?fix:=20prod=20=EC=9D=B8=EC=8A=A4=ED=84=B4?= =?UTF-8?q?=EC=8A=A4=20old=20image=20=EC=9D=B4=EB=A6=84=20=ED=86=B5?= =?UTF-8?q?=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 9e0a71953..b88c09718 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -135,7 +135,7 @@ jobs: uses: snok/container-retention-policy@v2 with: token: ${{ secrets.GITHUB_TOKEN }} - image-names: solid-connection-prod + image-names: solid-connection-server delete-untagged: true keep-n-tags: 5 account-type: org From 59c01163d5a5c42ef3bfb31630b37da34a3b23af Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Wed, 5 Nov 2025 23:47:09 +0900 Subject: [PATCH 06/15] =?UTF-8?q?fix:=20prod-cd.yml=20StrictHostKeyCheckin?= =?UTF-8?q?g=20=EC=98=B5=EC=85=98=20=EB=AC=B8=EB=B2=95=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index b88c09718..38e997fb9 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -71,7 +71,7 @@ jobs: chmod 600 deploy_key.pem scp -i deploy_key.pem \ - -o StrictHostKeyChecking:no \ + -o StrictHostKeyChecking=no \ ./docker-compose.prod.yml \ ./docs/infra-config/config.alloy \ ./docs/infra-config/nginx.prod.conf \ From c86901a38e738e4e3c7dee0e5ebe6c83f98d5cae Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Thu, 6 Nov 2025 18:27:11 +0900 Subject: [PATCH 07/15] =?UTF-8?q?fix:=20prod-cd.yml=20StrictHostKeyCheckin?= =?UTF-8?q?g=20=EC=98=B5=EC=85=98=20=EB=AC=B8=EB=B2=95=20=EC=98=A4?= =?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/prod-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 38e997fb9..3d28cdae8 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -84,7 +84,7 @@ jobs: chmod 600 deploy_key_ssh.pem ssh -i deploy_key_ssh.pem \ - -o StrictHostKeyChecking:no \ + -o StrictHostKeyChecking=no \ ${{ secrets.USERNAME }}@${{ secrets.HOST }} \ ' set -e From 595c6aae19c24f4f66d62934f71b1d608fb94eb0 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Thu, 6 Nov 2025 18:32:31 +0900 Subject: [PATCH 08/15] =?UTF-8?q?fix:=20dev-cd.yml=20Old=20images=20?= =?UTF-8?q?=EC=A0=95=EB=A6=AC=20=EC=9E=91=EC=97=85=20=EC=A4=91=20=EC=9D=B4?= =?UTF-8?q?=EB=AF=B8=EC=A7=80=20=EC=9D=B4=EB=A6=84=20=EB=B6=88=EC=9D=BC?= =?UTF-8?q?=EC=B9=98=20=EB=AC=B8=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/dev-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index ebcf8079c..ad9344709 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -131,7 +131,7 @@ jobs: uses: snok/container-retention-policy@v2 with: token: ${{ secrets.GITHUB_TOKEN }} - image-names: solid-connection + image-names: solid-connection-dev delete-untagged: true keep-n-tags: 5 account-type: org From 63a16fabfb20c776fa74d1ca75f70ff0c0477c53 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Thu, 6 Nov 2025 18:33:21 +0900 Subject: [PATCH 09/15] =?UTF-8?q?chore:=20=EB=A7=88=EC=A7=80=EB=A7=89=20?= =?UTF-8?q?=EC=A4=84=20=EA=B0=9C=ED=96=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- .github/workflows/prod-cd.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index ad9344709..cbcf95bc2 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -136,4 +136,4 @@ jobs: keep-n-tags: 5 account-type: org org-name: ${{ github.repository_owner }} - cut-off: '7 days ago UTC' \ No newline at end of file + cut-off: '7 days ago UTC' diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 3d28cdae8..125e3600d 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -140,4 +140,4 @@ jobs: keep-n-tags: 5 account-type: org org-name: ${{ github.repository_owner }} - cut-off: '7 days ago UTC' \ No newline at end of file + cut-off: '7 days ago UTC' From ab3054e4daf7c91b57e39909f1692066caf4142d Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Thu, 6 Nov 2025 18:33:50 +0900 Subject: [PATCH 10/15] =?UTF-8?q?chore:=20=EB=A7=88=EC=A7=80=EB=A7=89=20?= =?UTF-8?q?=EC=A4=84=20=EA=B0=9C=ED=96=89=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 2 +- docker-compose.dev.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index 8a067cefc..f598c9395 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,4 +11,4 @@ COPY ${JAR_FILE} app.jar ENTRYPOINT ["java", "-jar", "/app.jar"] # 볼륨 설정 -VOLUME /tmp \ No newline at end of file +VOLUME /tmp diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index cb0ef325c..29aaf5bb1 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -41,4 +41,4 @@ services: - ./logs:/var/log/spring - ./docs/infra-config/config.alloy:/etc/alloy/config.alloy:ro environment: - - ALLOY_ENV=dev \ No newline at end of file + - ALLOY_ENV=dev From 01114c31955f3fd81083af0cf192f9c8d4db7162 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Mon, 10 Nov 2025 13:58:06 +0900 Subject: [PATCH 11/15] =?UTF-8?q?feat:=20stage=20=EC=9D=B8=EC=8A=A4?= =?UTF-8?q?=ED=84=B4=EC=8A=A4=EC=97=90=20=EB=8C=80=ED=95=9C=20=EC=B5=9C?= =?UTF-8?q?=EC=8B=A0=20=EC=9D=B4=EB=AF=B8=EC=A7=80=205=EA=B0=9C=20?= =?UTF-8?q?=EC=9C=A0=EC=A7=80=20=EA=B8=B0=EB=8A=A5=20=EB=B0=8F=20old=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=A0=9C=EA=B1=B0=20=EA=B8=B0?= =?UTF-8?q?=EB=8A=A5=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index cbcf95bc2..e90c84075 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -122,6 +122,15 @@ jobs: echo "Pruning dangling docker images..." docker image prune -f + # 8. stage 인스턴스의 오래된 태그 이미지 정리 (최신 5개 유지) + echo "Cleaning up old tagged images on host, keeping last 5..." + IMAGE_NAME_BASE="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev" + + docker images "${IMAGE_NAME_BASE}" --format "{{.Tag}}" | \ + sort -r | \ + tail -n +6 | \ + xargs -I {} docker rmi "${IMAGE_NAME_BASE}:{}" || true + echo "Deploy and Docker Compose restart finished." ' From 229d9aac5866b25babb342521b10c303a1206193 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Mon, 10 Nov 2025 14:45:26 +0900 Subject: [PATCH 12/15] =?UTF-8?q?chore:=20=EC=A4=91=EB=B3=B5=EB=90=9C=20?= =?UTF-8?q?=ED=99=98=EA=B2=BD=EB=B3=80=EC=88=98=20=EC=A7=80=EC=A0=95=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 --- .github/workflows/dev-cd.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index e90c84075..735a282d3 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -91,7 +91,7 @@ jobs: ' set -e - # [수정] 1. 변수를 'image_meta' 단계의 출력값에서 가져옴 + # 1. 변수를 'image_meta' 단계의 출력값에서 가져옴 export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') export IMAGE_TAG_ONLY=${{ steps.image_meta.outputs.image_tag }} export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG_ONLY}" @@ -116,7 +116,7 @@ jobs: # 6. Docker Compose 재시작 echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY" docker compose -f docker-compose.dev.yml down - OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d + IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d # 7. 이미지 정리 echo "Pruning dangling docker images..." From 1b57e748be109d6f5dd1e6c151ce6210d9627bd4 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Mon, 10 Nov 2025 17:11:45 +0900 Subject: [PATCH 13/15] =?UTF-8?q?chore:=20=EC=A4=91=EB=B3=B5=EB=90=9C=20pe?= =?UTF-8?q?m=ED=82=A4=20=EC=83=9D=EC=84=B1=20=EB=A1=9C=EC=A7=81=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 --- .github/workflows/dev-cd.yml | 3 --- src/main/resources/secret | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 735a282d3..cd6c96319 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -82,9 +82,6 @@ jobs: # --- 5. 서버에서 'docker pull' 및 서비스 재시작 --- - name: Run docker compose and apply nginx config run: | - echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key_ssh.pem - chmod 600 deploy_key_ssh.pem - ssh -i deploy_key_ssh.pem \ -o StrictHostKeyChecking=no \ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }} \ diff --git a/src/main/resources/secret b/src/main/resources/secret index b2fb51671..2f4a16822 160000 --- a/src/main/resources/secret +++ b/src/main/resources/secret @@ -1 +1 @@ -Subproject commit b2fb5167196dd5f36703a8541eca03fcc3ea33a1 +Subproject commit 2f4a168223ea81cfe3447d6d95441b1a020fdbfe From 0c431df0bbb5cd3159849ef3fe61f0c439bfe1d9 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Mon, 10 Nov 2025 21:01:21 +0900 Subject: [PATCH 14/15] =?UTF-8?q?fix:=20=EC=9E=98=EB=AA=BB=EB=90=9C=20pem?= =?UTF-8?q?=ED=82=A4=20=EC=9D=B4=EB=A6=84=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index cd6c96319..07ca0b2e4 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -82,7 +82,7 @@ jobs: # --- 5. 서버에서 'docker pull' 및 서비스 재시작 --- - name: Run docker compose and apply nginx config run: | - ssh -i deploy_key_ssh.pem \ + ssh -i deploy_key.pem \ -o StrictHostKeyChecking=no \ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }} \ ' From 7ae94b1d6137be9063fc94095939a67441f18a15 Mon Sep 17 00:00:00 2001 From: HEX <123macanic@naver.com> Date: Sat, 15 Nov 2025 20:54:34 +0900 Subject: [PATCH 15/15] =?UTF-8?q?refactor:=20=EC=9B=90=EA=B2=A9=20?= =?UTF-8?q?=ED=98=B8=EC=8A=A4=ED=8A=B8=EC=97=90=EC=84=9C=20pull=ED=95=A0?= =?UTF-8?q?=20=EA=B2=BD=EC=9A=B0,=20=EC=B5=9C=EC=86=8C=20=EA=B6=8C?= =?UTF-8?q?=ED=95=9C=EC=9C=BC=EB=A1=9C=20=EC=8B=A4=ED=96=89=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20Github=20App=EC=9C=BC=EB=A1=9C=20=EC=9E=84?= =?UTF-8?q?=EC=8B=9C=ED=86=A0=ED=81=B0=20=EB=B0=9C=EA=B8=89=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/dev-cd.yml | 14 +++++++++++--- .github/workflows/prod-cd.yml | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/.github/workflows/dev-cd.yml b/.github/workflows/dev-cd.yml index 07ca0b2e4..9a3ae34a4 100644 --- a/.github/workflows/dev-cd.yml +++ b/.github/workflows/dev-cd.yml @@ -66,7 +66,15 @@ jobs: cache-from: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache cache-to: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max - # --- 4. 설정 파일들만 scp로 전송 --- + # --- 4. Github App으로 임시 토큰 생성 --- + - name: Create installation token + id: app + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.GH_APP_ID }} + private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} + + # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote run: | echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key.pem @@ -79,7 +87,7 @@ jobs: ./docs/infra-config/nginx.dev.conf \ ${{ secrets.DEV_USERNAME }}@${{ secrets.DEV_HOST }}:/home/${{ secrets.DEV_USERNAME }}/solid-connection-dev/ - # --- 5. 서버에서 'docker pull' 및 서비스 재시작 --- + # --- 6. 서버에서 'docker pull' 및 서비스 재시작 --- - name: Run docker compose and apply nginx config run: | ssh -i deploy_key.pem \ @@ -94,7 +102,7 @@ jobs: export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev:${IMAGE_TAG_ONLY}" # 2. 서버가 GHCR에 로그인 (pull 받기 위해) - echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin # 3. docker pull (전체 이미지 이름 사용) echo "Pulling new image layer from GHCR..." diff --git a/.github/workflows/prod-cd.yml b/.github/workflows/prod-cd.yml index 125e3600d..c96074d19 100644 --- a/.github/workflows/prod-cd.yml +++ b/.github/workflows/prod-cd.yml @@ -63,8 +63,16 @@ jobs: tags: ${{ format('{0}:{1}', steps.image_meta.outputs.image_name, steps.image_meta.outputs.image_tag) }} cache-from: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache cache-to: type=registry,ref=${{ steps.image_meta.outputs.image_name }}:buildcache,mode=max + + # --- 4. Github App으로 임시 토큰 생성 --- + - name: Create installation token + id: app + uses: actions/create-github-app-token@v2 + with: + app-id: ${{ secrets.GH_APP_ID }} + private-key: ${{ secrets.GH_APP_PRIVATE_KEY }} - # --- 4. 설정 파일들만 scp로 전송 --- + # --- 5. 설정 파일들만 scp로 전송 --- - name: Copy config files to remote run: | echo "${{ secrets.PRIVATE_KEY }}" > deploy_key.pem @@ -77,7 +85,7 @@ jobs: ./docs/infra-config/nginx.prod.conf \ ${{ secrets.USERNAME }}@${{ secrets.HOST }}:/home/${{ secrets.USERNAME }}/solid-connection-prod/ - # --- 5. 서버에서 'docker pull' 및 서비스 재시작 --- + # --- 6. 서버에서 'docker pull' 및 서비스 재시작 --- - name: Run docker compose and apply nginx config run: | echo "${{ secrets.PRIVATE_KEY }}" > deploy_key_ssh.pem @@ -95,7 +103,7 @@ jobs: export FULL_IMAGE_NAME="ghcr.io/${OWNER_LOWERCASE}/solid-connection-server:${IMAGE_TAG_ONLY}" # 2. 서버가 GHCR에 로그인 (pull 받기 위해) - echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + echo "${{ steps.app.outputs.token }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin # 3. docker pull (전체 이미지 이름 사용) echo "Pulling new image layer from GHCR..."