-
Notifications
You must be signed in to change notification settings - Fork 8
refactor: CD 성능 개선 #552
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
refactor: CD 성능 개선 #552
Conversation
Walkthrough1. GitHub Actions 워크플로우 전환. Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes
Suggested reviewers
Pre-merge checks and finishing touches✅ Passed checks (5 passed)
✨ Finishing touches🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration used: CodeRabbit UI Review profile: CHILL Plan: Pro 📒 Files selected for processing (2)
🧰 Additional context used🧠 Learnings (1)📚 Learning: 2025-11-10T01:55:03.827ZApplied to files:
🔇 Additional comments (13)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
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.
Actionable comments posted: 3
🧹 Nitpick comments (2)
.github/workflows/prod-cd.yml (1)
82-130: 원격 배포 SSH 스크립트의 복원력 개선이 필요합니다.현재 SSH 스크립트는 여러 단계를 순차적으로 실행하며
set -e로 에러 시 중단하도록 설정되어 있습니다. 그러나 다음과 같은 시나리오에서 개선이 필요합니다:상황별 개선 사항:
docker pull 실패 시 처리
- 현재: 에러 발생 시 그냥 중단
- 제안: 기존 이미지로 서비스 유지 또는 명확한 실패 알림
docker compose up -d 실패 시 처리
- Line 123에서 새 컨테이너 시작 실패 시, 이전 컨테이너가 이미 down된 상태
- 제안: 스크린샷 또는 파일로 이전 상태 백업 후 롤백 가능하도록 개선
Nginx 설정 적용 실패 시 처리
- Line 111의 nginx -t 검증 후 reload가 실패하면 서비스 불가
- 제안: 구 설정 백업 후 검증 실패 시 복구
아래와 같이 개선하는 것을 권장합니다:
# Nginx 설정 변경 전 백업 cp /etc/nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf.backup # 새 설정 적용 sudo cp ./nginx/default.conf /etc/nginx/conf.d/default.conf # 검증 실패 시 복구 if ! sudo nginx -t; then echo "Nginx configuration test failed. Reverting..." sudo cp /etc/nginx/conf.d/default.conf.backup /etc/nginx/conf.d/default.conf sudo nginx -t exit 1 fi sudo nginx -s reload또한 Docker Compose도 이전 상태 보존을 고려하세요:
# 이전 상태 백업 docker compose -f docker-compose.prod.yml cp solid-connection-server:/var/log/spring ./logs.backup # 새 버전으로 재시작 OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.prod.yml up -d # 헬스 체크 (옵션) sleep 5 curl -f http://localhost:8080/health || { echo "Health check failed"; exit 1; }.github/workflows/dev-cd.yml (1)
118-119: Docker Compose 정리 명령어가 prod 워크플로우와 불일치합니다.현재 dev-cd.yml:
- Line 118:
docker compose -f docker-compose.dev.yml downprod-cd.yml (더 견고함):
- Line 117-120:
docker compose ... stop(graceful shutdown)docker compose ... down --remove-orphans(고아 네트워크/볼륨 정리)차이점:
- prod는 명시적으로 stop → down 순서 진행
- prod는
--remove-orphans플래그 사용 (고아 리소스 제거)- dev는 이 두 가지를 누락
이로 인해 dev 환경에서 장기 실행 후 불필요한 네트워크/볼륨이 쌓일 수 있습니다.
prod 워크플로우와 일치하도록 수정하세요:
# 6. Docker Compose 재시작 echo "Restarting Docker Compose with tag: $IMAGE_TAG_ONLY" - docker compose -f docker-compose.dev.yml down + echo "Stopping containers gracefully..." + docker compose -f docker-compose.dev.yml stop + + echo "Removing old containers and networks..." + docker compose -f docker-compose.dev.yml down --remove-orphans + + echo "Starting new containers..." OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
.github/workflows/dev-cd.yml(2 hunks).github/workflows/prod-cd.yml(1 hunks)Dockerfile(2 hunks)docker-compose.dev.yml(2 hunks)docker-compose.prod.yml(1 hunks)src/main/resources/secret(1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-25T10:59:42.734Z
Learnt from: whqtker
Repo: solid-connection/solid-connect-server PR: 481
File: docs/infra-config/nginx.conf:36-36
Timestamp: 2025-08-25T10:59:42.734Z
Learning: When using network_mode: host in Docker Compose, containers share the host's network namespace, so nginx proxy_pass should target localhost:PORT instead of container service names like solid-connection-server:PORT.
Applied to files:
docker-compose.prod.yml
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
- GitHub Check: build
🔇 Additional comments (6)
src/main/resources/secret (1)
1-1: 서브모듈 포인터 업데이트 확인 필요합니다.
src/main/resources/secret서브모듈이ae3e90ef→b2fb5167로 업데이트되었습니다. 다음 사항을 확인해 주세요:
- 변경 내용 검증: 새 커밋 (
b2fb5167)에서 어떤 변경사항이 발생했는지 확인 필요- CD 리팩터링 연관성: 현재 PR의 CD 워크플로우 개선(GitHub Actions → GHCR → docker-compose)과 이 서브모듈 업데이트의 관계 확인
- 보안 영향도:
secret디렉토리 특성상 민감한 정보 포함 여부 및 변경에 따른 보안 영향 검토이 서브모듈이 실제로 이 PR의 범위에 포함되어야 하는지, 아니면 별도로 관리되어야 하는지 명확히 해 주시기 바랍니다.
docker-compose.dev.yml (1)
21-21: 환경 변수 전달 방식 확인이 필요합니다.Line 21의 이미지 참조가
OWNER_LOWERCASE와IMAGE_TAG환경 변수에 의존하고 있습니다. 워크플로우에서OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose로 명시적으로 전달하고 있으므로 동작하겠지만, 로컬 개발 환경에서도 이 변수들을 설정하고 실행해야 합니다.로컬에서 수동 테스트 시 아래 명령어로 실행되는지 확인하세요:
export OWNER_LOWERCASE=<your-org> export IMAGE_TAG=<tag-or-leave-for-latest> docker compose -f docker-compose.dev.yml up -ddocker-compose.prod.yml (1)
21-21: 환경 변수 전달 방식 일관성 유지 필요합니다.docker-compose.dev.yml과 마찬가지로 Line 21의 이미지 참조는
OWNER_LOWERCASE와IMAGE_TAG환경 변수에 의존합니다. 워크플로우에서 올바르게 전달되고 있으나, 배포 전 로컬 테스트 시에도 동일한 방식으로 환경 변수를 설정해야 합니다.추가적으로, nginx 설정(prod-cd.yml의 라인 107~112)이 이 compose 파일 외부에서 관리되므로, nginx 컨테이너가 bridge network을 사용하는 경우
proxy_pass http://solid-connection-server:8080형식으로 서비스명을 사용해야 함을 확인하세요.Dockerfile (1)
2-2: Base image 변경이 적절합니다.OpenJDK는 더 이상 유지보수되지 않으며, Eclipse Temurin은 공식 대체 이미지입니다. 변경 자체는 명확하고 문제없어 보입니다.
다만 한 가지 검증 항목:
- 빌드 플랫폼 호환성: 워크플로우에서
linux/arm64플랫폼을 지정하고 있습니다. Eclipse Temurin:17-jdk가 이 플랫폼에서 정상 작동하는지 확인하세요..github/workflows/prod-cd.yml (1)
106-112: Nginx 설정 변경 시 권한 문제 검토가 필요합니다.원격 SSH 명령어에서 Nginx 설정을 다음과 같이 처리하고 있습니다:
- 로컬에서 nginx.prod.conf를 scp로 전송 (Line 76)
- 원격에서 ./nginx/default.conf로 이동 (Line 107)
- sudo로 /etc/nginx/conf.d/default.conf에 복사 (Line 110)
- sudo nginx -t 및 sudo nginx -s reload 실행 (Lines 111-112)
문제점:
sudo명령어 실행 시 비밀번호 입력 없이 동작해야 하는데, 배포 키 기반 SSH에서 이것이 보장되는지 확인 필요- Nginx 설정 검증 실패 시 에러 처리 미흡 (set -e가 있으므로 중단되지만, 롤백 로직 없음)
다음을 확인하세요:
- 배포 서버의 sudoers 파일에서 해당 사용자(
${{ secrets.USERNAME }})가 비밀번호 없이 nginx 명령어를 실행할 수 있도록 설정되었는지 확인- nginx -t 검증 실패 시 이전 설정으로 복구하는 로직 추가 검토
.github/workflows/dev-cd.yml (1)
130-139: 이미지 보관 정책의 이미지명을 검토하세요.Line 134에서
image-names: solid-connection로 지정되어 있으나, 실제 푸시된 이미지명은:
- Line 54:
ghcr.io/${OWNER_LOWERCASE}/solid-connection-dev또한 prod-cd.yml의 보관 정책과도 불일치:
- prod:
image-names: solid-connection-prod- dev:
image-names: solid-connection다음을 확인하고 수정하세요:
- 실제 GHCR에 푸시되는 이미지명 확인
- 보관 정책의 이미지명을 정확하게 매칭:
- image-names: solid-connection + image-names: solid-connection-dev또는 조직 수준의 보관 정책을 사용하려면 와일드카드 지원 여부 확인 필요.
.github/workflows/dev-cd.yml
Outdated
| 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 |
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.
GHCR 로그인 시 사용자명 대소문자 불일치 문제가 있습니다.
dev-cd.yml도 prod-cd.yml과 동일한 문제가 있습니다.
Line 100에서 docker login 시 사용자명으로 ${{ github.repository_owner }}를 사용하고 있으나, 이미지 태그는 소문자로 변환되어 있습니다:
- Line 52:
OWNER_LOWERCASE=$(echo ... | tr '[:upper:]' '[:lower:]') - Line 54: 이미지명에 OWNER_LOWERCASE 사용
GitHub 저장소 소유자명에 대문자가 있으면 로그인 실패 또는 권한 오류 발생 가능성이 있습니다.
수정 방법:
# 2. 서버가 GHCR에 로그인 (pull 받기 위해)
- echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
+ OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
+ echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${OWNER_LOWERCASE} --password-stdin📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin | |
| OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') | |
| echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${OWNER_LOWERCASE} --password-stdin |
🤖 Prompt for AI Agents
.github/workflows/dev-cd.yml around line 100: the docker login uses ${{
github.repository_owner }} which may contain uppercase letters while the image
tag and OWNER_LOWERCASE are used elsewhere, causing GHCR auth failures; change
the login username to the already-computed OWNER_LOWERCASE variable (or compute
a lowercase owner just before login) so the docker login user matches the
lowercase image namespace, and apply the same change in prod-cd.yml.
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.
이전에 lower_case로 통일하도록 이미지 메타데이터 정의 스텝에서 전처리를 해두었기에 문제가 나지 않을 것 같은데?
심지어 내 닉네임이 Hexeong인데, fork 레포에서 깃헙 액션을 실행시켰을 때에 문제가 발생하지 않았었어
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.
맞습니다! 제가 잘못 지적했네요. 죄송합니다. 🙇
-
Docker/GHCR 로그인은 사용자명 대소문자를 구분하지 않습니다.
- Line 100의
docker login ghcr.io -u ${{ github.repository_owner }}는Hexeong이든hexeong이든 정상적으로 인증됩니다.
- Line 100의
-
이미지 경로는 올바르게 소문자를 사용하고 있습니다.
- Line 95에서
OWNER_LOWERCASE를 재계산하고 - Line 97에서
FULL_IMAGE_NAME에 소문자 버전을 사용하여 - Line 103의
docker pull이 정상 작동합니다.
- Line 95에서
실제 테스트에서 문제가 없었다는 것이 이를 증명하네요. 불필요한 수정 제안을 드려 혼란을 드려 죄송합니다!
| - 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 }} |
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.
GHCR 로그인 시 사용자명 대소문자 불일치 문제가 있습니다.
워크플로우를 자세히 보면:
- GitHub Actions에서 GHCR 로그인 (Line 44):
${{ github.repository_owner }}(원본 대소문자 유지) - 이미지 메타데이터 정의 (Lines 51-54):
OWNER_LOWERCASE=$(echo ... | tr '[:upper:]' '[:lower:]')로 소문자 변환 - 원격 서버 GHCR 로그인 (Line 98):
${{ github.repository_owner }}(원본 대소문자 유지)
문제: GitHub 저장소 소유자명이 대문자를 포함하면, docker pull 시 이미지명과 로그인 사용자명의 대소문자 불일치로 인증 오류가 발생할 수 있습니다.
아래와 같이 수정하세요:
# 2. 서버가 GHCR에 로그인 (pull 받기 위해)
- echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin
+ OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')
+ echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${OWNER_LOWERCASE} --password-stdinAlso applies to: 98-100
🤖 Prompt for AI Agents
.github/workflows/prod-cd.yml lines 40-45 (also applies to lines 98-100): GHCR
login uses `${{ github.repository_owner }}` which can contain uppercase letters
causing mismatch with the image names that are converted to lowercase; update
the workflow to pass a lowercased owner username to docker/login-action (use the
same lowercase transformation used for OWNER_LOWERCASE) so both GHCR login steps
use the lowercase repository owner; ensure the environment variable or step
output holding the lowercase owner is referenced in both login steps.
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.
레지스트리 경로명은 항상 소문자로 유지되기에 repository_owner가 대문자가 포함되어 있어도 이후에 문제가 되지 않아!
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.
@Hexeong, 설명 감사합니다! GHCR의 인증 과정에서 사용자명은 대소문자를 구분하지 않고, 레지스트리 경로는 자동으로 소문자로 정규화되는 점을 확인해주셨네요. 제가 너무 신중하게 접근했습니다. 현재 구현이 문제없이 작동하겠네요! 👍
✏️ Learnings added
Learnt from: Hexeong
Repo: solid-connection/solid-connect-server PR: 552
File: .github/workflows/prod-cd.yml:40-45
Timestamp: 2025-11-10T01:55:03.812Z
Learning: GHCR (GitHub Container Registry)에서는 docker login 시 사용자명의 대소문자를 구분하지 않으며, 레지스트리 경로명은 항상 소문자로 정규화됩니다. 따라서 `github.repository_owner`를 그대로 사용해도 이미지 경로와의 대소문자 불일치 문제가 발생하지 않습니다.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
| - 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 }} |
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.
이미지 보관 정책의 이미지명 불일치가 있습니다.
Line 138에서 image-names: solid-connection-prod로 지정되어 있으나, 실제 푸시된 이미지는:
- Line 53:
ghcr.io/${OWNER_LOWERCASE}/solid-connection-server
동일하게 dev-cd.yml (Line 134)는 image-names: solid-connection로 지정되어 있습니다.
두 워크플로우 간 네이밍 정책이 일관되지 않습니다. 정리해야 할 항목:
- prod 워크플로우:
solid-connection-prodvs 실제 푸시 이미지명solid-connection-server - dev 워크플로우:
solid-connectionvs 실제 푸시 이미지명solid-connection-dev
이미지 보관 정책이 정확한 이미지명과 일치하도록 수정하세요:
- name: Clean up old image versions from GHCR
...
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
org-name: ${{ github.repository_owner }}
cut-off: '7 days ago UTC'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| - 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 }} | |
| - 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-server | |
| delete-untagged: true | |
| keep-n-tags: 5 | |
| account-type: org | |
| org-name: ${{ github.repository_owner }} |
🤖 Prompt for AI Agents
In .github/workflows/prod-cd.yml around lines 133-142 the image-names value is
set to "solid-connection-prod" but the pushed image is
"ghcr.io/${OWNER_LOWERCASE}/solid-connection-server" (see push at line 53);
update image-names to "solid-connection-server". Also update the dev workflow
(.github/workflows/dev-cd.yml around line 134) where image-names is
"solid-connection" to the actual pushed name "solid-connection-dev". Ensure the
container-retention-policy steps in both workflows use the exact image names
that are pushed to GHCR.
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.
@coderabbitai 해당 내용 반영했어!
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.
Gyuhyeok99
left a comment
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.
하지만, prod의 경우 release 버전으로 이미지가 관리될 수 있다 보니, 이미지 태그에 대한 내용을 스크립트 상에 하드코딩할 수 없는 상태입니다.
이게 어떤 말씀이신가요~?? release tag 활용하면 되는 건 아닌가요!?
.github/workflows/prod-cd.yml
Outdated
| sudo nginx -t | ||
| sudo nginx -s reload | ||
| scp -i deploy_key.pem \ | ||
| -o StrictHostKeyChecking:no \ |
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.
@coderabbitai
StrictHostKeyChecking:no
StrictHostKeyChecking=no
이거 문법 뭐가 맞아?
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.
올바른 문법은 StrictHostKeyChecking=no 입니다 (등호 사용).
SSH 옵션은 -o option=value 형식을 사용해야 합니다. 콜론(:)이 아니라 등호(=)를 사용해야 합니다.
현재 파일에서 두 곳 모두 수정이 필요합니다:
-
Line 71 (scp 명령어):
scp -i deploy_key.pem \ -o StrictHostKeyChecking=no \
-
Line 83 (ssh 명령어):
ssh -i deploy_key_ssh.pem \ -o StrictHostKeyChecking=no \
콜론을 사용하면 SSH가 옵션을 올바르게 인식하지 못할 수 있습니다.
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.
반영했습니다!
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.
Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!
아하 제가 릴리즈 기능을 써본 적이 없어서 몰랐던 것 같습니다;; 이 방식으로 배포할 경우 |
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.
Actionable comments posted: 2
♻️ Duplicate comments (2)
.github/workflows/prod-cd.yml (2)
40-45:⚠️ GHCR 로그인 시 소유자명 대소문자 불일치 문제 (이전 리뷰의 미해결 항목)앞선 리뷰에서 지적되었던 문제가 여전히 남아 있습니다.
문제:
- Line 44의 GHCR 로그인:
${{ github.repository_owner }}(원본 대소문자 유지)- Line 53의 이미지명:
ghcr.io/${OWNER_LOWERCASE}/solid-connection-server(소문자 변환)리포지토리 소유자명에 대문자가 포함되면, 로그인 사용자명과 이미지명의 대소문자 불일치로 인증 오류가 발생합니다.
수정:
- name: Log in to GitHub Container Registry (GHCR) uses: docker/login-action@v3 with: registry: ghcr.io - username: ${{ github.repository_owner }} + username: ${{ steps.image_meta.outputs.owner_lowercase }} password: ${{ secrets.GITHUB_TOKEN }}그리고 Line 48-54의 메타데이터 정의 단계에 다음 줄을 추가하세요:
- name: Define image name and tag id: image_meta run: | OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + echo "owner_lowercase=${OWNER_LOWERCASE}" >> $GITHUB_OUTPUT 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
98-98:⚠️ 원격 서버의 GHCR 로그인에서도 소유자명 대소문자 불일치 (이전 리뷰의 미해결 항목)Line 40-45의 GHCR 로그인 문제와 동일하게, 원격 서버에서의 docker login 명령어에서도 대소문자 불일치가 발생합니다.
문제:
- Line 93:
export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]')로 소문자 변수 생성- Line 98:
docker login ghcr.io -u ${{ github.repository_owner }}(원본 대소문자 사용)변수가 정의되었으므로 일관성 있게 사용하세요.
수정:
# 2. 서버가 GHCR에 로그인 (pull 받기 위해) - echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${OWNER_LOWERCASE} --password-stdin
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/prod-cd.yml(1 hunks)
🔇 Additional comments (4)
.github/workflows/prod-cd.yml (4)
1-34: 기본 설정 단계가 잘 구성되었습니다.Java, Gradle 설정과 초기 빌드 단계가 명확하게 작성되었습니다. 특히 submodule 체크아웃과 Gradle wrapper 권한 설정이 적절합니다.
56-65: Docker 빌드 및 푸시 구성이 잘 설계되었습니다.메타데이터를 올바르게 활용하고, 레지스트리 캐시를 통해 빌드 성능 최적화를 구현한 점이 좋습니다. 멀티 플랫폼 지원도 명시되어 있습니다.
100-130: 배포 로직이 견고하게 구성되었습니다.이미지 pull부터 Nginx 재시작, Docker Compose 재시작, 정리까지의 단계가 명확하고,
set -e를 통한 에러 처리와 graceful shutdown 로직이 좋습니다. 위의 문법 오류들을 수정하면 배포 흐름이 안정적으로 작동할 것입니다.
132-143: GHCR 이미지 정리 정책이 올바르게 수정되었습니다. ✅이전 리뷰에서 지적했던 image-names 불일치 문제(solid-connection-prod → solid-connection-server)가 이미 반영되었습니다. 실제 푸시된 이미지명과 일치하며, 5개 태그 유지 및 7일 이상 된 이미지 정리 정책이 적절합니다.
Gyuhyeok99
left a comment
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.
이미지를 pull하는 방식으로 잘 개선해주신 거 같네요! 고생하셨습니다!
길게 잡고 점진적으로 개선해나가봐요!
.github/workflows/dev-cd.yml
Outdated
| keep-n-tags: 5 | ||
| account-type: org | ||
| org-name: ${{ github.repository_owner }} | ||
| cut-off: '7 days ago UTC' |
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.
개행 하나 부탁드려요~
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.
반영했습니다!
.github/workflows/prod-cd.yml
Outdated
| keep-n-tags: 5 | ||
| account-type: org | ||
| org-name: ${{ github.repository_owner }} | ||
| cut-off: '7 days ago UTC' |
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.
여기도요!
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.
반영했습니다!
Dockerfile
Outdated
|
|
||
| # 볼륨 설정 | ||
| VOLUME /tmp | ||
| VOLUME /tmp |
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.
개행!
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.
반영했습니다!
docker-compose.dev.yml
Outdated
| - ./docs/infra-config/config.alloy:/etc/alloy/config.alloy:ro | ||
| environment: | ||
| - ALLOY_ENV=dev | ||
| - ALLOY_ENV=dev |
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.
개행!
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.
반영했습니다!
whqtker
left a comment
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.
| - name: Define image name and tag | ||
| id: image_meta | ||
| run: | | ||
| OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') |
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.
github.repository_owner 로 설정하면 레포 소유자 이름(e.g. whqtker)으로 고정되는 건가요 ? 만약 그렇다면, solid-connection 과 같이 사용자에 종속되지 않는 이름으로 설정하는 게 좋을 거 같습니다 !
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.
Organization에 속한 레포의 워크플로우 실행의 경우 github.repository_owner은 Organization 이름인 solid-connection이 됩니다! 때문에 사용자 이름으로 종속되지는 않아 해당 문제는 없을 것 같아요!
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.
확인했습니다 ~!
.github/workflows/dev-cd.yml
Outdated
| uses: snok/container-retention-policy@v2 | ||
| with: | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
| image-names: solid-connection |
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.
image-names 를 solid-connection-dev 로 설정해야 할 듯 합니다 ~!
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.
반영했습니다!
어 그럼 이부분도 GHCR Clean up 작업처럼 하나 추가해서 최신 이미지 10개만 유지하게 할까요?? 어떻게 생각하시나용 @whqtker |
Gyuhyeok99
left a comment
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.
이번 pr만큼은 수연님도 리뷰해주시면 좋겠습니다~
Hexeong
left a comment
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.
반영사항들 반영해두었습니다! pending 처리되어있던 걸 제가 늦게 확인했네요;; 빠르게 stage 인스턴스에 대해서도 old 이미지를 지우는 step도 추가해두겠습니다!
.github/workflows/dev-cd.yml
Outdated
| 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 |
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.
이전에 lower_case로 통일하도록 이미지 메타데이터 정의 스텝에서 전처리를 해두었기에 문제가 나지 않을 것 같은데?
심지어 내 닉네임이 Hexeong인데, fork 레포에서 깃헙 액션을 실행시켰을 때에 문제가 발생하지 않았었어
| - 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 }} |
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.
@coderabbitai 해당 내용 반영했어!
| - 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 }} |
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.
레지스트리 경로명은 항상 소문자로 유지되기에 repository_owner가 대문자가 포함되어 있어도 이후에 문제가 되지 않아!
.github/workflows/prod-cd.yml
Outdated
| sudo nginx -t | ||
| sudo nginx -s reload | ||
| scp -i deploy_key.pem \ | ||
| -o StrictHostKeyChecking:no \ |
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.
반영했습니다!
| - name: Define image name and tag | ||
| id: image_meta | ||
| run: | | ||
| OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') |
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.
Organization에 속한 레포의 워크플로우 실행의 경우 github.repository_owner은 Organization 이름인 solid-connection이 됩니다! 때문에 사용자 이름으로 종속되지는 않아 해당 문제는 없을 것 같아요!
.github/workflows/prod-cd.yml
Outdated
| keep-n-tags: 5 | ||
| account-type: org | ||
| org-name: ${{ github.repository_owner }} | ||
| cut-off: '7 days ago UTC' |
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.
반영했습니다!
Dockerfile
Outdated
|
|
||
| # 볼륨 설정 | ||
| VOLUME /tmp | ||
| VOLUME /tmp |
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.
반영했습니다!
docker-compose.dev.yml
Outdated
| - ./docs/infra-config/config.alloy:/etc/alloy/config.alloy:ro | ||
| environment: | ||
| - ALLOY_ENV=dev | ||
| - ALLOY_ENV=dev |
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.
반영했습니다!
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.
Actionable comments posted: 1
🧹 Nitpick comments (3)
.github/workflows/dev-cd.yml (3)
69-80: SCP 전송 시 에러 처리 추가 권장.현재 설정 파일 전송 단계에서 scp 명령이 실패해도 워크플로우가 계속 진행됩니다. 예를 들어, 파일이 존재하지 않거나 네트워크 오류가 발생할 경우를 대비하세요.
다음과 같이 개선하면 실패 시 명확히 감지할 수 있습니다:
- name: Copy config files to remote run: | echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key.pem chmod 600 deploy_key.pem + set -e # 에러 발생 시 즉시 중단 + 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/
118-119: docker compose 명령어 실행 시 환경 변수 설정 방식 정리.현재 Line 119에서:
OWNER_LOWERCASE=$OWNER_LOWERCASE IMAGE_TAG=$IMAGE_TAG_ONLY docker compose -f docker-compose.dev.yml up -d이 패턴은 작동하지만,
OWNER_LOWERCASE가 Line 95에서 이미 export되었다면 불필요한 중복입니다. 일관성을 위해 다음 중 하나로 정리하세요:옵션 1: 환경 변수를 명시적으로 선언하고 재사용
export OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') export IMAGE_TAG_ONLY=${{ steps.image_meta.outputs.image_tag }} # ... docker compose -f docker-compose.dev.yml up -d옵션 2: 매번 인라인으로 설정 (현재 방식이지만 정리)
IMAGE_TAG=${{ steps.image_meta.outputs.image_tag }} \ OWNER_LOWERCASE=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') \ docker compose -f docker-compose.dev.yml up -d
129-132: 오래된 이미지 정리 로직이 정상 작동하는지 검증 권장.Line 129-132의 이미지 정리 로직은 수동으로 태그를 정렬하고 삭제합니다:
docker images "${IMAGE_NAME_BASE}" --format "{{.Tag}}" | \ sort -r | \ tail -n +6 | \ xargs -I {} docker rmi "${IMAGE_NAME_BASE}:{}" || true주의할 점:
docker images출력에<none>태그가 포함될 수 있으며, 이는 정렬 순서에 영향을 미칠 수 있습니다.- 태그가 6개 미만이면 아무것도 삭제되지 않습니다 (의도한 동작이라면 문제 없음).
|| true로 인해 삭제 실패가 무시되므로, 실제 오류를 인지하기 어려울 수 있습니다.개선 제안:
GHCR의 자동 정리 정책(Line 137-147, 최신 5개 유지)과의 일관성을 위해, 로컬 환경에서도 같은 개수를 유지하되, 더 명확한 로직을 고려하세요:
docker images "${IMAGE_NAME_BASE}" --format "table {{.Repository}}:{{.Tag}}\t{{.CreatedAt}}" | \ tail -n +2 | \ sort -k2 -r | \ tail -n +6 | \ awk '{print $1}' | \ xargs -r docker rmi또는 snok/container-retention-policy 같은 로컬 도구도 검토해볼 가치가 있습니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/dev-cd.yml(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T01:55:03.812Z
Learnt from: Hexeong
Repo: solid-connection/solid-connect-server PR: 552
File: .github/workflows/prod-cd.yml:40-45
Timestamp: 2025-11-10T01:55:03.812Z
Learning: GHCR (GitHub Container Registry)에서는 docker login 시 사용자명의 대소문자를 구분하지 않으며, 레지스트리 경로명은 항상 소문자로 정규화됩니다. 따라서 `github.repository_owner`를 그대로 사용해도 이미지 경로와의 대소문자 불일치 문제가 발생하지 않습니다.
Applied to files:
.github/workflows/dev-cd.yml
🔇 Additional comments (2)
.github/workflows/dev-cd.yml (2)
47-55: 이미지 메타데이터 정의 로직이 명확하고 효율적입니다.이미지 이름과 태그를 GitHub Actions Output으로 미리 정의하여 여러 단계에서 재사용할 수 있게 설계된 점이 좋습니다. 특히:
- OWNER_LOWERCASE로 소문자 정규화: GHCR 이미지명 규칙 준수 ✓
- 타임스탬프 기반 태깅(YYYYMMDD-HHMMSS): 버전 추적 명확함 ✓
- 이미지명 포맷 표준화: 코드 가독성 향상 ✓
137-147: GHCR 자동 정리 정책이 체계적으로 구성되었습니다.snok/container-retention-policy를 활용한 정책이 명확합니다:
- 태그 없는 이미지 자동 삭제 (delete-untagged: true)
- 최신 5개 버전 유지 (keep-n-tags: 5)
- 7일 이상 오래된 버전 정리 (cut-off: 7 days ago)
- 성공 시에만 실행 (if: success()) — 안정성 고려 ✓
로컬 정리 정책(Line 129-132)과도 일관성이 있어, 스토리지 관리가 예측 가능합니다.
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
.github/workflows/dev-cd.yml (1)
137-147: GHCR 이미지 정리 정책과 로컬 호스트 정리 정책의 일관성이 확인됩니다.GHCR에서 최신 5개 태그를 유지(
keep-n-tags: 5)하고, Line 131에서 로컬 호스트에서도 동일하게 최신 5개를 유지하는 방식으로 정책이 일관되어 있습니다.delete-untagged: true로 미태그 이미지도 정리하므로 레지스트리 저장소 효율이 좋습니다.다만, 다음 사항을 확인해주세요:
- 정기적 정리 스케줄: 현재 구조에서는 성공적인 배포 시에만 정리가 실행됩니다(
if: success()). 배포가 자주 이루어지지 않는 기간이 있다면 저장소가 누적될 수 있으니, 필요시 별도의 정기 정리 워크플로우(예: 주 1회 스케줄 실행)도 고려해보세요.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
.github/workflows/dev-cd.yml(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T01:55:03.812Z
Learnt from: Hexeong
Repo: solid-connection/solid-connect-server PR: 552
File: .github/workflows/prod-cd.yml:40-45
Timestamp: 2025-11-10T01:55:03.812Z
Learning: GHCR (GitHub Container Registry)에서는 docker login 시 사용자명의 대소문자를 구분하지 않으며, 레지스트리 경로명은 항상 소문자로 정규화됩니다. 따라서 `github.repository_owner`를 그대로 사용해도 이미지 경로와의 대소문자 불일치 문제가 발생하지 않습니다.
Applied to files:
.github/workflows/dev-cd.yml
🔇 Additional comments (3)
.github/workflows/dev-cd.yml (3)
47-67: 이미지 메타데이터 정의 및 빌드 캐시 전략이 명확합니다.이미지명과 태그를 명시적으로 정의하고, Docker BuildX의 레지스트리 캐시(
type=registry)를 활용해 빌드 성능을 개선하는 구조가 좋습니다. 타임스탬프 기반 태그(YYYYMMDD-HHMMSS)는 dev 환경에서 이미지 버전 추적에 효과적입니다.
87-135: SSH 배포 스크립트의 변수 관리와 함께 일관성 개선을 제안합니다.현재 구조는 다음과 같은 점에서 정상 작동하지만, 명확성을 위해 몇 가지 정리를 제안합니다:
로그인 사용자명 일관성
- Line 95에서
OWNER_LOWERCASE를 계산하지만, Line 100의docker login에서는 여전히${{ github.repository_owner }}를 사용 중입니다.- 비록 GHCR에서 대소문자를 구분하지 않지만, 코드의 일관성과 가독성 차원에서 이미 계산한
OWNER_LOWERCASE변수를 사용하는 것이 좋습니다.환경 변수 전달 방식
- Line 119의
IMAGE_TAG=$IMAGE_TAG_ONLY docker compose ...는 정상 작동합니다(IMAGE_TAG환경변수가 해당 명령 실행 시에만 유효).- 다만,
OWNER_LOWERCASE는 Line 95에서 이미 export되었으므로, docker-compose.dev.yml이 두 변수를 모두 필요로 한다면 현재 구조로 충분합니다.오래된 이미지 정리 로직 확인
- Lines 129-132에서
sort -r | tail -n +6으로 최신 5개를 제외한 나머지를 삭제하는 로직은 정확합니다.- 다만, 타임스탬프 기반 정렬(이미지 태그 문자열)과 실제 생성 시간의 순서가 일치하는지 확인이 필요합니다. (현재 YYYYMMDD-HHMMSS 형식이므로 문자열 정렬과 시간 순서가 일치함)
다음 개선안을 고려해주세요:
# 2. 서버가 GHCR에 로그인 (pull 받기 위해) - echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.repository_owner }} --password-stdin + echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${OWNER_LOWERCASE} --password-stdin이렇게 하면 로그인 사용자명이 이미지명 계산 부분과 완전히 일치하게 됩니다.
69-80: 설정 파일 전송 단계가 효율적으로 통합되었습니다.기존의 개별 파일 전송 방식에서 하나의 scp 명령으로 여러 파일을 전송하도록 통합되어, 워크플로우 단계가 간결해졌습니다. SSH 보안 설정(StrictHostKeyChecking=no, 권한 600)도 적절합니다.
lsy1307
left a comment
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.
개인적으로 on push 방식으로 release태그를 사용하는 게 배포 자동화 면에서 이점이 있다고 생각합니당
.github/workflows/dev-cd.yml
Outdated
| echo "${{ secrets.DEV_PRIVATE_KEY }}" > deploy_key_ssh.pem | ||
| chmod 600 deploy_key_ssh.pem |
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.
위에서 생성한 key를 그대로 사용해도 되지 않나요..?
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.
해당 내용 반영했습니다!
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.
이름도 바꿔주셔야 할 것 같아요! deploy_key.pem으로 저장이 되었는데 deploy_key_ssh.pem을 사용하고 있습니당
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.
반영했습니다!
.github/workflows/dev-cd.yml
Outdated
| 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 |
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.
지금 쓰기가 가능한 토큰이 서버로 전송되는데 보안상 취약하지 않을까요...? 읽기 전용 토큰을 따로 발급해서 사용하는 게 좋아보입니당
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.
SSH를 통해 GHCR에 접근하는 이 방식을 적용하려면, SUBMODULE_ACCESS_TOKEN처럼 Fine-grained Token을 사용하는 것이 보안상 가장 좋다고 생각합니다!
하지만 이 방식을 사용하려면 GHCR 읽기 권한이 있는 분이 직접 토큰을 발급해야 하는데, 이는 특정 계정에 파이프라인이 의존하게 되는 문제가 있어 망설여졌습니다.
그래서 일단은 임시로 GITHUB_TOKEN을 사용하는 방식을 적용했습니다만, 혹시 이 '개인 종속성' 문제를 해결할 더 좋은 방법이 있다면 의견 부탁드립니다! @lsy1307
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.
machine user 개념으로 CI/CD용 계정을 따로 만들어서 사용하는 건 어떨까요? Github Docs에도 나와있는 내용입니다!
참고 : https://docs.github.com/en/get-started/learning-about-github/types-of-github-accounts#user-accounts
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.
machine user 대신 최근 Github 추천하는 방식인 Github App을 사용해서 Repository에서 임시 토큰을 발급할 수 있도록 개선했습니다! 해당 문제는 해결된 것 같아요!
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
.github/workflows/dev-cd.yml (1)
83-132: SSH 스크립트 내 환경 변수 정의 정리 제안.현재 설계:
- 라인 52–55에서 GitHub Actions 컨텍스트에서
OWNER_LOWERCASE와IMAGE_TAG생성- 라인 92–94에서 SSH 스크립트 내부에서 동일한 값을 재계산
재계산은 작동하지만 불필요한 중복입니다. GitHub Actions 출력값이 이미 SSH 스크립트 내
${{ steps.image_meta.outputs.* }}구문으로 전달되므로, 아래처럼 간소화할 수 있습니다: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}"이미 export된
OWNER_LOWERCASE를 재계산할 필요 없이 일관성 있게 사용할 수 있으며, 라인 116의IMAGE_TAG=$IMAGE_TAG_ONLY docker compose...부분도 명확해집니다.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
.github/workflows/dev-cd.yml(2 hunks)src/main/resources/secret(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- src/main/resources/secret
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-10T01:55:03.812Z
Learnt from: Hexeong
Repo: solid-connection/solid-connect-server PR: 552
File: .github/workflows/prod-cd.yml:40-45
Timestamp: 2025-11-10T01:55:03.812Z
Learning: GHCR (GitHub Container Registry)에서는 docker login 시 사용자명의 대소문자를 구분하지 않으며, 레지스트리 경로명은 항상 소문자로 정규화됩니다. 따라서 `github.repository_owner`를 그대로 사용해도 이미지 경로와의 대소문자 불일치 문제가 발생하지 않습니다.
Applied to files:
.github/workflows/dev-cd.yml
🔇 Additional comments (4)
.github/workflows/dev-cd.yml (4)
11-33: 좋은 권한 설정과 표준 Gradle 스택.권한에
packages: write를 추가했고, 최신 공식 Gradle 액션(v3)을 사용하여 정확하게 구성되었습니다. JDK 17 temurin 배포판도 Dockerfile 변경과 일치합니다.
35-67: Docker 빌드·푸시 단계가 잘 설계됨.Docker Buildx 멀티 아키텍처 지원, GHCR 로그인, 이미지 메타데이터(이름·태그) 사전 정의, 레지스트리 캐시 전략까지 모두 CD 성능 개선 목표와 일치합니다. 특히 buildcache 태그를 활용한 레이어 캐싱은 반복 배포 시 빌드 시간 단축에 효과적입니다.
103-132: 원격 배포 및 정리 로직이 효율적으로 구성됨.다음 항목들이 잘 구성되었습니다:
- Config 파일 재배치: Nginx 설정을 정확한 경로(
/etc/nginx/conf.d/default.conf)로 이동- Nginx 검증 및 재시작:
nginx -t로 사전 검증 후 재시작 (무중단 배포)- Docker Compose 재시작:
down→up -d로 깔끔한 순환- 이미지 정리:
docker image prune -f로 이미지 제거 및 로컬 태그 이미지 최신 5개 유지- GHCR 정리: snok/container-retention-policy로 오래된 이미지 자동 삭제
특히 로컬(라인 122–129)과 GHCR(라인 135–144) 양쪽에서 정리 정책을 일관되게 적용(최신 5개 유지)하는 것이 스토리지 효율성과 유지보수성 면에서 좋습니다.
70-81: Deploy 키 파일명 오류.라인 72에서
deploy_key.pem을 생성하고 있으나, 라인 85의 SSH 명령어에서deploy_key_ssh.pem을 참조하고 있습니다. 이는 파일을 찾을 수 없는 오류로 인해 배포가 실패합니다.라인 85를 다음과 같이 수정하세요:
- ssh -i deploy_key_ssh.pem \ + ssh -i deploy_key.pem \Likely an incorrect or invalid review comment.
whqtker
left a comment
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.
제가 남긴 리뷰들에 대해서 해소가 되어서 approve하겠습니다 !
다른 분들까지 approve되면 머지 진행해주시면 될 거 같습니다. 고생하셨어요 !!
…ening-cd-time # Conflicts: # src/main/resources/secret


관련 이슈
작업 내용
jar파일을 포함,nginx와alloy등의 설정 파일을ssh copy(scp)명령으로 전송 이후, 원격 호스트에서build하고docker-compose를 실행하는 방식을 사용해왔습니다.GHCR(Github Container Registry)를 사용하여 Github Action에서 이미지 빌드 이후,GHCR로 push/원격호스트에서 pull하는 방식으로docker-compose를 실행하도록 리팩토링했습니다.3분이었지만, 현재는 평균2분 15초로25%단축시킨 결과가 나왔습니다. (테스트 결과는 아래 첨부파일에 올려두겠습니다.)이미지:날짜-시간방식으로 태그가 되어 있는 상태입니다. 하지만 prod 인스턴스는 릴리즈 버전으로 관리될 수 있기에 여러분의 의견을 듣고 내용 반영하여 추가 commit 올리겠습니다!특이 사항
base image로openjdk:17-jdk를 사용해왔지만, 해당 base image가 deprecated되어 공식 대체 이미지인eclipse-temurin:17-jdk로 변경하였습니다.리뷰 요구사항 (선택)
날짜-시간으로 설정해두었습니다.첨부파일(테스트 결과)