Skip to content

Commit ab02cea

Browse files
committed
[feat]: CI/CD 파이프라인 완성
1 parent 540d8d9 commit ab02cea

File tree

3 files changed

+243
-48
lines changed

3 files changed

+243
-48
lines changed

.github/workflows/README.md

Lines changed: 110 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,73 +1,135 @@
1-
# GitHub Actions CI 파이프라인 설정 가이드
1+
# GitHub Actions CI/CD 파이프라인 설정 가이드
22

3-
## ? 현재 구성
3+
## 🎯 현재 구성
44

5-
이 프로젝트는 **CI (Continuous Integration)** 파이프라인만 구축되어 있습니다.
6-
코드 푸시/PR자동으로 빌드 검증이 실행됩니다.
5+
- **CI (Continuous Integration)**: 코드 푸시/PR 시 자동 빌드 검증
6+
- **CD (Continuous Deployment)**: develop 브랜치 푸시EC2 자동 배포
77

8-
## ? 워크플로우 설명
8+
## 🚀 워크플로우 설명
99

10-
### `ci.yml` - 지속적 통합 (CI)
11-
**트리거**:
12-
- Pull Request 생성/업데이트 (develop, main 브랜치 대상)
13-
- 코드 푸시 (develop, main, feature/*, fix/*, hotfix/* 브랜치)
10+
### 1. `ci.yml` - 지속적 통합 (CI)
11+
**트리거**:
12+
- Pull Request 생성/업데이트 (develop, main 브랜치 대상)
13+
- 코드 푸시 (develop, main, feature/*, fix/*, hotfix/* 브랜치)
1414

15-
**동작**:
16-
1. **Backend 빌드 검증**
17-
- Node.js 20 환경 설정
18-
- npm 의존성 설치
19-
- Prisma Client 생성
20-
- JavaScript 문법 검증
21-
- Docker 이미지 빌드 테스트
15+
**동작**:
16+
1. **Backend 빌드 검증**
17+
- Node.js 20 환경 설정
18+
- npm 의존성 설치
19+
- Prisma Client 생성
20+
- JavaScript 문법 검증
21+
- Docker 이미지 빌드 테스트
2222

23-
2. **FastAPI 빌드 검증**
24-
- Python 3.11 환경 설정
25-
- pip 의존성 설치
26-
- Python 문법 검증
27-
- Docker 이미지 빌드 테스트
23+
2. **FastAPI 빌드 검증**
24+
- Python 3.11 환경 설정
25+
- pip 의존성 설치
26+
- Python 문법 검증
27+
- Docker 이미지 빌드 테스트
2828

29-
3. **Docker Compose 검증**
30-
- docker-compose.yml 설정 검증
31-
- MySQL/Redis 컨테이너 시작 테스트
29+
3. **Docker Compose 검증**
30+
- docker-compose.yml 설정 검증
31+
- MySQL/Redis 컨테이너 시작 테스트
3232

33-
## ? 사용법
33+
### 2. `cd-deploy.yml` - 자동 배포 (CD)
34+
**트리거**:
35+
- develop 브랜치 푸시
36+
- 수동 실행 (Actions 탭에서)
3437

35-
### 1?? 코드 푸시 시 자동 실행
38+
**동작**:
39+
1. **Docker 이미지 빌드 & 푸시**
40+
- GitHub Container Registry (GHCR)에 이미지 업로드
41+
- `ghcr.io/{owner}/{repo}/backend:latest`
42+
- `ghcr.io/{owner}/{repo}/fastapi:latest`
43+
44+
2. **EC2 서버 배포**
45+
- SSH로 서버 접속
46+
- 최신 코드 pull (develop 브랜치)
47+
- GHCR에서 최신 이미지 pull
48+
- Docker Compose로 컨테이너 재시작
49+
- 구버전 이미지 정리
50+
51+
## 📋 필요한 GitHub Secrets 설정
52+
53+
**Repository → Settings → Secrets and variables → Actions**
54+
55+
### 🔐 현재 설정된 Secrets
56+
```
57+
EC2_HOST: EC2 서버 IP 주소
58+
EC2_USER: ubuntu
59+
EC2_SSH_KEY: SSH 프라이빗 키
60+
```
61+
62+
## 🔄 배포 플로우
63+
64+
```
65+
1. feature 브랜치에서 개발
66+
67+
2. develop 브랜치로 PR 생성 → CI 자동 실행 (검증만)
68+
69+
3. PR 머지 → develop 브랜치
70+
71+
4. CD 자동 실행 → EC2 서버 배포 🚀
72+
```
73+
74+
## 📝 사용법
75+
76+
### 1️⃣ 코드 푸시 시 CI 자동 실행
3677
```bash
3778
git add .
38-
git commit -m "[feat]: 새로운 기능 추가"
79+
git commit -m "[feat]: 새로운 기능 추가"
3980
git push origin feature/new-feature
4081
```
4182

42-
### 2?? PR 생성 시 자동 검증
83+
### 2️⃣ PR 생성 시 자동 검증
84+
```bash
85+
# GitHub에서 PR 생성
86+
feature/new-feature → develop
87+
# → CI가 자동 실행되어 빌드 검증
88+
```
89+
90+
### 3️⃣ PR 머지 후 자동 배포
4391
```bash
44-
# GitHub에서 PR 생성
45-
feature/new-feature → develop
92+
# PR 머지 완료
93+
# → develop 브랜치에 반영
94+
# → CD가 자동 실행되어 EC2에 배포
4695
```
4796

48-
### 3?? 결과 확인
49-
**GitHub Repository → Actions 탭**에서 실시간 로그 확인 가능
97+
### 4️⃣ 결과 확인
98+
**GitHub Repository → Actions 탭**에서 실시간 로그 확인 가능
99+
100+
## 🐛 트러블슈팅
101+
102+
### CI 실패 시
103+
104+
**npm install 실패**
105+
`package.json` 의존성 확인 또는 `package-lock.json` 삭제 후 재생성
106+
107+
**Python 문법 에러**
108+
`fastapi-server/main.py` 코드 검토
50109

51-
## ? CI 통과 조건
110+
**Docker 빌드 실패**
111+
`Dockerfile` 또는 `fastapi-server/Dockerfile` 검토
52112

53-
- Node.js 빌드 성공
54-
- Python 빌드 성공
55-
- Docker 이미지 빌드 성공
56-
- Docker Compose 설정 유효성 검증 통과
113+
**Docker Compose 에러**
114+
`docker-compose.yml` 문법 및 서비스 설정 확인
57115

58-
## ? 트러블슈팅
116+
### CD 실패 시
59117

60-
### npm install 실패
61-
`package.json` 의존성 확인 또는 `package-lock.json` 삭제 후 재생성
118+
**SSH 접속 실패**
119+
→ EC2_HOST, EC2_USER, EC2_SSH_KEY 값 확인
120+
→ EC2 보안 그룹에서 22번 포트 열려있는지 확인
62121

63-
### Python 문법 에러
64-
`fastapi-server/main.py` 코드 검토
122+
**git pull 실패**
123+
→ EC2 서버에 프로젝트가 클론되어 있는지 확인
124+
`/home/ubuntu/moduwa-server` 경로 존재 여부 확인
65125

66-
### Docker 빌드 실패
67-
`Dockerfile` 또는 `fastapi-server/Dockerfile` 검토
126+
**docker pull 실패**
127+
→ GHCR 권한 문제: 워크플로우의 `permissions: packages: write` 확인
128+
→ 이미지가 Public으로 설정되어 있는지 확인
68129

69-
### Docker Compose 에러
70-
`docker-compose.yml` 문법 및 서비스 설정 확인
130+
**docker-compose 실패**
131+
→ EC2 서버의 `.env` 파일 확인
132+
→ 환경변수가 제대로 설정되어 있는지 확인
71133

72-
## ? 로그 확인
73-
GitHub Actions 실행 로그: **Repository → Actions 탭 → 해당 워크플로우 클릭**
134+
## 📞 로그 확인
135+
**GitHub Actions 실행 로그**: Repository → Actions 탭 → 해당 워크플로우 클릭

.github/workflows/cd-deploy.yml

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
name: CD - Deploy to EC2
2+
3+
on:
4+
push:
5+
branches: [develop]
6+
workflow_dispatch: # 수동 실행 가능
7+
8+
env:
9+
REGISTRY: ghcr.io
10+
IMAGE_PREFIX: ghcr.io/${{ github.repository_owner }}
11+
12+
jobs:
13+
# ==========================================
14+
# Build & Push Docker Images
15+
# ==========================================
16+
build-and-push:
17+
name: Build and Push Images
18+
runs-on: ubuntu-latest
19+
permissions:
20+
contents: read
21+
packages: write # GHCR 푸시 권한
22+
23+
steps:
24+
- name: Checkout code
25+
uses: actions/checkout@v4
26+
27+
- name: Set up Docker Buildx
28+
uses: docker/setup-buildx-action@v3
29+
30+
- name: Log in to GitHub Container Registry
31+
uses: docker/login-action@v3
32+
with:
33+
registry: ghcr.io
34+
username: ${{ github.actor }}
35+
password: ${{ secrets.GITHUB_TOKEN }}
36+
37+
- name: Convert repository name to lowercase
38+
id: repo
39+
run: echo "repo_lower=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
40+
41+
- name: Build and push Backend image
42+
uses: docker/build-push-action@v5
43+
with:
44+
context: .
45+
file: ./Dockerfile
46+
target: production
47+
push: true
48+
tags: |
49+
ghcr.io/${{ steps.repo.outputs.repo_lower }}/backend:latest
50+
ghcr.io/${{ steps.repo.outputs.repo_lower }}/backend:${{ github.sha }}
51+
cache-from: type=registry,ref=ghcr.io/${{ steps.repo.outputs.repo_lower }}/backend:latest
52+
cache-to: type=inline
53+
54+
- name: Build and push FastAPI image
55+
uses: docker/build-push-action@v5
56+
with:
57+
context: ./fastapi-server
58+
file: ./fastapi-server/Dockerfile
59+
push: true
60+
tags: |
61+
ghcr.io/${{ steps.repo.outputs.repo_lower }}/fastapi:latest
62+
ghcr.io/${{ steps.repo.outputs.repo_lower }}/fastapi:${{ github.sha }}
63+
cache-from: type=registry,ref=ghcr.io/${{ steps.repo.outputs.repo_lower }}/fastapi:latest
64+
cache-to: type=inline
65+
66+
# ==========================================
67+
# Deploy to EC2 Server
68+
# ==========================================
69+
deploy:
70+
name: Deploy to EC2
71+
runs-on: ubuntu-latest
72+
needs: build-and-push
73+
74+
steps:
75+
- name: Checkout code
76+
uses: actions/checkout@v4
77+
78+
- name: Convert repository name to lowercase
79+
id: repo
80+
run: echo "repo_lower=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]')" >> $GITHUB_OUTPUT
81+
82+
- name: Deploy to EC2 via SSH
83+
uses: appleboy/ssh-action@v1.0.3
84+
with:
85+
host: ${{ secrets.EC2_HOST }}
86+
username: ${{ secrets.EC2_USER }}
87+
key: ${{ secrets.EC2_SSH_KEY }}
88+
port: 22
89+
script: |
90+
# 프로젝트 디렉토리로 이동
91+
cd /home/ubuntu/moduwa-server || exit 1
92+
93+
# 최신 코드 pull
94+
git fetch origin
95+
git checkout develop
96+
git pull origin develop
97+
98+
# GHCR 로그인 (GitHub Token 사용)
99+
echo "${{ secrets.GITHUB_TOKEN }}" | docker login ghcr.io -u ${{ github.actor }} --password-stdin
100+
101+
# 최신 이미지 pull
102+
docker pull ghcr.io/${{ steps.repo.outputs.repo_lower }}/backend:latest
103+
docker pull ghcr.io/${{ steps.repo.outputs.repo_lower }}/fastapi:latest
104+
105+
# docker-compose.yml에서 이미지 이름 업데이트
106+
export BACKEND_IMAGE=ghcr.io/${{ steps.repo.outputs.repo_lower }}/backend:latest
107+
export FASTAPI_IMAGE=ghcr.io/${{ steps.repo.outputs.repo_lower }}/fastapi:latest
108+
109+
# 컨테이너 재시작
110+
docker-compose down
111+
docker-compose up -d
112+
113+
# 잠시 대기 후 상태 확인
114+
sleep 10
115+
docker-compose ps
116+
117+
# 헬스체크 (선택사항)
118+
echo "배포 완료: develop-${{ github.sha }}"
119+
120+
# 구버전 이미지 정리
121+
docker image prune -af --filter "until=24h"
122+
123+
- name: Deployment Status
124+
if: always()
125+
run: |
126+
if [ "${{ job.status }}" == "success" ]; then
127+
echo "배포 성공 - 최신 이미지로 업데이트되었습니다"
128+
else
129+
echo "배포 실패 - 로그를 확인하세요"
130+
exit 1
131+
fi

docker-compose.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ services:
4848
# FastAPI AI Server (Python)
4949
# ==========================================
5050
fastapi:
51+
image: ${FASTAPI_IMAGE:-fastapi-local}
5152
build:
5253
context: ./fastapi-server
5354
dockerfile: Dockerfile
@@ -71,6 +72,7 @@ services:
7172
# Backend API (Node.js + Express + Prisma)
7273
# ==========================================
7374
backend:
75+
image: ${BACKEND_IMAGE:-backend-local}
7476
build:
7577
context: .
7678
dockerfile: Dockerfile

0 commit comments

Comments
 (0)