Skip to content

Commit 651da2a

Browse files
authored
Merge pull request #59 from boostcampwm2025/devops
[Devops] Docker Compose 기반 서버 생성
2 parents bd8333f + 7631b36 commit 651da2a

File tree

8 files changed

+333
-106
lines changed

8 files changed

+333
-106
lines changed

.github/CICD_GUIDE.md

Lines changed: 162 additions & 60 deletions
Large diffs are not rendered by default.

.github/scripts/detect-changes.sh

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,10 @@ check_package_dependencies() {
4444
}
4545

4646
# 서비스별 변경 감지
47-
check_service_change "frontend" "frontend"
48-
check_service_change "api-server" "backend/api-server"
49-
check_service_change "ticket-server" "backend/ticket-server"
50-
check_service_change "queue-backend" "queue-backend"
47+
check_service_change "frontend" "frontend" || true
48+
check_service_change "api-server" "backend/api-server" || true
49+
check_service_change "ticket-server" "backend/ticket-server" || true
50+
check_service_change "queue-backend" "queue-backend" || true
5151

5252
# 공통 패키지 변경 시 의존 서비스 추가
5353
check_package_dependencies "shared-types" "api-server" "ticket-server"
@@ -78,13 +78,13 @@ else
7878

7979
echo "changed_services=$SERVICES_JSON" >> $GITHUB_OUTPUT
8080
echo "has_changes=true" >> $GITHUB_OUTPUT
81-
82-
# 개별 서비스 플래그 설정
83-
for service in "frontend" "api-server" "ticket-server" "queue-backend"; do
84-
if [[ " ${CHANGED_SERVICES[@]} " =~ " ${service} " ]]; then
85-
echo "${service//-/_}_changed=true" >> $GITHUB_OUTPUT
86-
else
87-
echo "${service//-/_}_changed=false" >> $GITHUB_OUTPUT
88-
fi
89-
done
9081
fi
82+
83+
# 개별 서비스 플래그 설정 (변경 여부와 관계없이 항상 설정)
84+
for service in "frontend" "api-server" "ticket-server" "queue-backend"; do
85+
if [[ " ${CHANGED_SERVICES[@]} " =~ " ${service} " ]]; then
86+
echo "${service//-/_}_changed=true" >> $GITHUB_OUTPUT
87+
else
88+
echo "${service//-/_}_changed=false" >> $GITHUB_OUTPUT
89+
fi
90+
done

.github/scripts/test-detect-changes.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,10 +53,10 @@ check_package_dependencies() {
5353

5454
echo "=== 서비스별 변경 감지 ==="
5555
# 서비스별 변경 감지
56-
check_service_change "frontend" "frontend"
57-
check_service_change "api-server" "backend/api-server"
58-
check_service_change "ticket-server" "backend/ticket-server"
59-
check_service_change "queue-backend" "queue-backend"
56+
check_service_change "frontend" "frontend" || true
57+
check_service_change "api-server" "backend/api-server" || true
58+
check_service_change "ticket-server" "backend/ticket-server" || true
59+
check_service_change "queue-backend" "queue-backend" || true
6060

6161
echo ""
6262
echo "=== 공통 패키지 의존성 체크 ==="

.github/workflows/cd.yml

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,33 +38,46 @@ jobs:
3838
steps:
3939
- name: Deploy to frontend server
4040
env:
41-
SSH_PRIVATE_KEY: ${{ secrets.FRONTEND_SSH_KEY }}
41+
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
4242
SERVER_HOST: ${{ secrets.FRONTEND_SERVER_HOST }}
4343
SERVER_USER: ${{ secrets.FRONTEND_SERVER_USER }}
44+
NCP_REGISTRY_URL: ${{ secrets.NCP_REGISTRY_URL }}
45+
NCP_REGISTRY_USERNAME: ${{ secrets.NCP_REGISTRY_USERNAME }}
46+
NCP_REGISTRY_PASSWORD: ${{ secrets.NCP_REGISTRY_PASSWORD }}
47+
IMAGE_TAG: ${{ github.sha }}
4448
run: |
4549
# SSH 키 설정
4650
mkdir -p ~/.ssh
4751
echo "$SSH_PRIVATE_KEY" > ~/.ssh/deploy_key
4852
chmod 600 ~/.ssh/deploy_key
4953
ssh-keyscan -H $SERVER_HOST >> ~/.ssh/known_hosts
5054
51-
# 프론트엔드 서버에서 빌드 및 배포
52-
ssh -i ~/.ssh/deploy_key $SERVER_USER@$SERVER_HOST << 'EOF'
53-
cd /app/web10-beastcamp
54-
55-
# 최신 코드 가져오기
56-
git fetch origin main
57-
git reset --hard origin/main
58-
59-
# frontend 서비스 재배포
60-
cd frontend
61-
docker-compose build
62-
docker-compose up -d
63-
64-
# 이전 이미지 정리
55+
# 프론트엔드 서버에 이미지 pull 및 배포
56+
ssh -i ~/.ssh/deploy_key $SERVER_USER@$SERVER_HOST << EOF
57+
# NCP Container Registry 로그인
58+
echo "$NCP_REGISTRY_PASSWORD" | docker login $NCP_REGISTRY_URL -u $NCP_REGISTRY_USERNAME --password-stdin
59+
60+
# CI에서 빌드된 이미지 pull
61+
docker pull $NCP_REGISTRY_URL/beastcamp-frontend:$IMAGE_TAG
62+
63+
# 기존 컨테이너 중지 및 삭제
64+
docker stop frontend 2>/dev/null || true
65+
docker rm frontend 2>/dev/null || true
66+
67+
# 새 컨테이너 실행
68+
docker run -d \
69+
--name frontend \
70+
-p 80:3000 \
71+
--restart unless-stopped \
72+
-e NODE_ENV=production \
73+
-e NEXT_PUBLIC_API_URL=http://localhost/api \
74+
-e NEXT_PUBLIC_API_MODE=mock \
75+
$NCP_REGISTRY_URL/beastcamp-frontend:$IMAGE_TAG
76+
77+
# 이전 이미지 정리 (현재 사용 중인 이미지 제외)
6578
docker image prune -f
6679
67-
echo "✅ Frontend deployed successfully"
80+
echo "✅ Frontend deployed successfully from registry (image built in CI)"
6881
EOF
6982
7083
# Backend Servers Deploy (api-server + ticket-server)
@@ -76,7 +89,7 @@ jobs:
7689
steps:
7790
- name: Deploy to backend server
7891
env:
79-
SSH_PRIVATE_KEY: ${{ secrets.BACKEND_SSH_KEY }}
92+
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
8093
SERVER_HOST: ${{ secrets.BACKEND_SERVER_HOST }}
8194
SERVER_USER: ${{ secrets.BACKEND_SERVER_USER }}
8295
API_SERVER_CHANGED: ${{ needs.detect-changes.outputs.api_server_changed }}
@@ -126,7 +139,7 @@ jobs:
126139
steps:
127140
- name: Deploy to queue server
128141
env:
129-
SSH_PRIVATE_KEY: ${{ secrets.QUEUE_SSH_KEY }}
142+
SSH_PRIVATE_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
130143
SERVER_HOST: ${{ secrets.QUEUE_SERVER_HOST }}
131144
SERVER_USER: ${{ secrets.QUEUE_SERVER_USER }}
132145
run: |

.github/workflows/ci.yml

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ jobs:
3131
id: detect
3232
run: |
3333
chmod +x .github/scripts/detect-changes.sh
34-
.github/scripts/detect-changes.sh origin/main
34+
# PR의 base 브랜치와 비교 (feature->dev는 dev와, dev->main은 main과 비교)
35+
BASE_BRANCH="origin/${{ github.base_ref }}"
36+
echo "Comparing with base branch: $BASE_BRANCH"
37+
.github/scripts/detect-changes.sh "$BASE_BRANCH"
3538
3639
# Frontend CI
3740
ci-frontend:
@@ -66,13 +69,44 @@ jobs:
6669
- name: Set up Docker Buildx
6770
uses: docker/setup-buildx-action@v3
6871

69-
- name: Build Docker image
72+
# dev -> main PR인 경우에만 NCP Registry에 로그인
73+
- name: Login to NCP Container Registry
74+
if: github.base_ref == 'main' && github.event_name == 'pull_request'
75+
uses: docker/login-action@v3
76+
with:
77+
registry: ${{ secrets.NCP_REGISTRY_URL }}
78+
username: ${{ secrets.NCP_REGISTRY_USERNAME }}
79+
password: ${{ secrets.NCP_REGISTRY_PASSWORD }}
80+
81+
# dev -> main PR인 경우: 이미지 빌드 및 푸시
82+
- name: Build and push Docker image (dev -> main)
83+
if: github.base_ref == 'main' && github.event_name == 'pull_request'
84+
uses: docker/build-push-action@v5
85+
with:
86+
context: .
87+
file: frontend/Dockerfile
88+
push: true
89+
tags: |
90+
${{ secrets.NCP_REGISTRY_URL }}/beastcamp-frontend:${{ github.sha }}
91+
${{ secrets.NCP_REGISTRY_URL }}/beastcamp-frontend:latest
92+
build-args: |
93+
NEXT_PUBLIC_API_URL=http://localhost/api
94+
NEXT_PUBLIC_API_MODE=mock
95+
cache-from: type=registry,ref=${{ secrets.NCP_REGISTRY_URL }}/beastcamp-frontend:buildcache
96+
cache-to: type=registry,ref=${{ secrets.NCP_REGISTRY_URL }}/beastcamp-frontend:buildcache,mode=max
97+
98+
# feature -> dev PR인 경우: 이미지 빌드만 (푸시 안 함)
99+
- name: Build Docker image (feature -> dev)
100+
if: github.base_ref != 'main' || github.event_name != 'pull_request'
70101
uses: docker/build-push-action@v5
71102
with:
72103
context: .
73104
file: frontend/Dockerfile
74105
push: false
75106
tags: beastcamp-frontend:ci-${{ github.sha }}
107+
build-args: |
108+
NEXT_PUBLIC_API_URL=http://localhost/api
109+
NEXT_PUBLIC_API_MODE=mock
76110
cache-from: type=gha
77111
cache-to: type=gha,mode=max
78112

frontend/README.md

Lines changed: 85 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,27 @@
11
## Docker를 이용한 배포
22

3-
### 프론트엔드 Docker 빌드 및 실행
3+
### 방법 1: Docker Compose 사용 (로컬 개발)
4+
5+
프론트엔드 디렉토리에서 다음 명령어를 실행합니다.
6+
7+
```bash
8+
# 1. frontend 디렉토리로 이동
9+
cd frontend
10+
11+
# 2. Docker Compose로 빌드 및 실행
12+
docker compose up -d --build
13+
14+
# 3. 브라우저에서 확인
15+
# http://localhost 접속
16+
17+
# 4. 로그 확인
18+
docker compose logs -f
19+
20+
# 5. 중지 및 삭제
21+
docker compose down
22+
```
23+
24+
### 방법 2: Docker 직접 빌드 및 실행 (로컬 개발)
425

526
프로젝트 루트에서 다음 명령어를 실행합니다.
627

@@ -15,6 +36,37 @@ docker run -d -p 80:3000 --name frontend beastcamp-frontend
1536
# http://localhost 접속
1637
```
1738

39+
### 방법 3: NCP Container Registry 사용 (프로덕션 배포)
40+
41+
프로덕션 배포는 NCP Container Registry를 사용하여 빌드 시간을 최소화합니다.
42+
43+
```bash
44+
# 1. NCP Container Registry 로그인
45+
docker login <NCP_REGISTRY_URL> -u <USERNAME>
46+
47+
# 2. 최신 이미지 pull
48+
docker pull <NCP_REGISTRY_URL>/beastcamp-frontend:latest
49+
50+
# 3. 기존 컨테이너 중지 및 삭제
51+
docker stop frontend 2>/dev/null || true
52+
docker rm frontend 2>/dev/null || true
53+
54+
# 4. 새 컨테이너 실행
55+
docker run -d \
56+
--name frontend \
57+
-p 80:3000 \
58+
--restart unless-stopped \
59+
-e NODE_ENV=production \
60+
-e NEXT_PUBLIC_API_URL=http://localhost/api \
61+
-e NEXT_PUBLIC_API_MODE=mock \
62+
<NCP_REGISTRY_URL>/beastcamp-frontend:latest
63+
64+
# 5. 로그 확인
65+
docker logs -f frontend
66+
```
67+
68+
**참고**: CD 워크플로우가 자동으로 이미지를 빌드하여 NCP Container Registry에 푸시하므로, 프로덕션 서버에서는 빌드 없이 pull만 수행합니다.
69+
1870
### Docker 관리 명령어
1971

2072
```bash
@@ -37,20 +89,45 @@ docker rm -f frontend
3789
docker rmi beastcamp-frontend
3890
```
3991

92+
### Docker Compose 관리 명령어
93+
94+
```bash
95+
# 서비스 시작 (백그라운드)
96+
docker compose up -d
97+
98+
# 서비스 중지
99+
docker compose stop
100+
101+
# 서비스 재시작
102+
docker compose restart
103+
104+
# 서비스 중지 및 컨테이너 삭제
105+
docker compose down
106+
107+
# 이미지까지 삭제
108+
docker compose down --rmi all
109+
110+
# 로그 실시간 확인
111+
docker compose logs -f
112+
113+
# 특정 서비스만 재빌드
114+
docker compose up -d --build frontend
115+
```
116+
40117
### 프로덕션 배포 최적화
41118

42119
Dockerfile은 3단계 멀티 스테이지 빌드로 구성되어 있습니다:
43120

44121
1. **deps**: pnpm을 사용하여 필요한 의존성만 설치
45-
2. **builder**: Vite로 프로덕션 빌드 수행
46-
3. **production**: Nginx로 정적 파일 서빙 (최종 이미지 크기 최소화)
122+
2. **builder**: Next.js Standalone 모드로 프로덕션 빌드 수행
123+
3. **production**: Node.js로 최적화된 서버 실행 (최종 이미지 크기 최소화)
47124

48-
--
125+
### 캐시 없이 빌드 (문제 해결 시)
49126

127+
```bash
50128
# Docker 캐시 클리어 후 빌드
51-
52129
docker build --no-cache -f frontend/Dockerfile -t beastcamp-frontend .
53130

54-
# 빌드 성공 후 실행
55-
56-
docker run -d -p 3000:3000 --name frontend beastcamp-frontend
131+
# 또는 Docker Compose 사용 시
132+
docker compose build --no-cache
133+
```

frontend/docker-compose.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ services:
66
context: ..
77
dockerfile: frontend/Dockerfile
88
ports:
9-
- "80:3000"
9+
- '80:3000'
1010
environment:
1111
- NODE_ENV=production
1212
- INTERNAL_API_URL=http://localhost:3000/api

queue-backend/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,4 @@ pids
5454

5555
# Diagnostic reports (https://nodejs.org/api/report.html)
5656
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
57+

0 commit comments

Comments
 (0)