Skip to content

Commit f11496e

Browse files
authored
Merge pull request #29 from JECT-Study/develop
release: develop → main
2 parents f4d4c6e + 57bac26 commit f11496e

4 files changed

Lines changed: 116 additions & 27 deletions

File tree

.github/workflows/cicd-deploy.yml

Lines changed: 14 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,25 @@
11
name: CI/CD - Deploy
22

33
on:
4-
push:
5-
branches: [ main ]
4+
workflow_run:
5+
workflows: ["Create Release"]
6+
types:
7+
- completed
68

79
jobs:
810
build-and-deploy:
911
runs-on: ubuntu-latest
12+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
1013

1114
steps:
1215
- name: Repository 접근
1316
uses: actions/checkout@v4
1417

15-
- name: JDK 25 셋팅
16-
uses: actions/setup-java@v4
17-
with:
18-
java-version: '25'
19-
distribution: 'temurin'
20-
21-
- name: Gradle 의존성 캐싱
22-
uses: actions/cache@v4
23-
with:
24-
path: |
25-
~/.gradle/caches
26-
~/.gradle/wrapper
27-
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties') }}
28-
restore-keys: |
29-
${{ runner.os }}-gradle-
30-
31-
- name: Setup Gradle
32-
uses: gradle/actions/setup-gradle@v4
33-
34-
- name: 프로젝트 빌드
35-
run: ./gradlew build
18+
- name: 최신 릴리즈 태그 가져오기
19+
id: release
20+
run: echo "tag=$(gh release view --json tagName -q '.tagName')" >> $GITHUB_OUTPUT
21+
env:
22+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
3623

3724
- name: Docker Hub 로그인
3825
uses: docker/login-action@v3
@@ -43,10 +30,10 @@ jobs:
4330
- name: Docker 이미지 빌드 & 푸시
4431
run: |
4532
IMAGE=${{ secrets.DOCKER_HUB_USERNAME }}/vs-server
46-
TAG=${{ github.sha }}
33+
TAG=${{ steps.release.outputs.tag }}
4734
4835
docker build -t $IMAGE:$TAG .
49-
docker build -t $IMAGE:latest .
36+
docker tag $IMAGE:$TAG $IMAGE:latest
5037
docker push $IMAGE:$TAG
5138
docker push $IMAGE:latest
5239
@@ -57,5 +44,5 @@ jobs:
5744
username: ${{ secrets.EC2_USERNAME }}
5845
key: ${{ secrets.EC2_SSH_KEY }}
5946
script: |
60-
cd /home/ubuntu/app
61-
./deploy.sh ${{ secrets.DOCKER_HUB_USERNAME }}/vs-server:${{ github.sha }}
47+
curl -fsSL https://raw.githubusercontent.com/JECT-Study/JECT2-4th-Server/main/scripts/deploy.sh \
48+
| bash -s ${{ secrets.DOCKER_HUB_USERNAME }}/vs-server:${{ steps.release.outputs.tag }}

docker-compose.yaml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
services:
2+
nginx:
3+
image: nginx:latest
4+
container_name: nginx
5+
ports:
6+
- "80:80"
7+
volumes:
8+
- ./nginx/app.conf:/etc/nginx/conf.d/default.conf
9+
networks:
10+
- app-network
11+
restart: unless-stopped
12+
13+
networks:
14+
app-network:
15+
name: app-network
16+
driver: bridge

nginx/app.conf

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
server {
2+
listen 80;
3+
4+
location / {
5+
proxy_pass http://app:8080;
6+
proxy_set_header Host $host;
7+
proxy_set_header X-Real-IP $remote_addr;
8+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
9+
proxy_set_header X-Forwarded-Proto $scheme;
10+
}
11+
}

scripts/deploy.sh

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/bin/bash
2+
IMAGE=$1
3+
4+
if [ -z "$IMAGE" ]; then
5+
echo ">>> 사용법: ./deploy.sh <이미지명:태그>"
6+
exit 1
7+
fi
8+
9+
NETWORK="app-network"
10+
11+
# 현재 활성 컨테이너 확인
12+
CURRENT=$(cat /home/ubuntu/app/current_container 2>/dev/null || echo "")
13+
14+
if [ "$CURRENT" == "app-blue" ]; then
15+
NEW_CONTAINER="app-green"
16+
OLD_CONTAINER="app-blue"
17+
else
18+
NEW_CONTAINER="app-blue"
19+
OLD_CONTAINER="app-green"
20+
fi
21+
22+
echo ">>> 현재: ${OLD_CONTAINER:-없음} → 새로운: $NEW_CONTAINER"
23+
24+
# 새 이미지 pull
25+
echo ">>> 이미지 pull 중..."
26+
docker pull $IMAGE
27+
28+
# 혹시 남아있는 동일 이름 컨테이너 정리
29+
docker stop $NEW_CONTAINER 2>/dev/null && docker rm $NEW_CONTAINER 2>/dev/null
30+
31+
# 새 컨테이너 실행 (네트워크 연결 없이)
32+
echo ">>> 새 컨테이너($NEW_CONTAINER) 실행 중..."
33+
docker run -d --name $NEW_CONTAINER \
34+
-e SPRING_PROFILES_ACTIVE=prod \
35+
--health-cmd="curl -f http://localhost:8080/actuator/health || exit 1" \
36+
--health-interval=5s \
37+
--health-timeout=3s \
38+
--health-start-period=30s \
39+
--health-retries=10 \
40+
$IMAGE
41+
42+
# 헬스체크 (docker inspect로 healthy 상태 확인)
43+
echo ">>> 헬스체크 시작..."
44+
for i in $(seq 1 60); do
45+
STATUS=$(docker inspect --format='{{.State.Health.Status}}' $NEW_CONTAINER 2>/dev/null)
46+
if [ "$STATUS" == "healthy" ]; then
47+
echo ">>> 헬스체크 통과! (${i}초)"
48+
break
49+
fi
50+
if [ $i -eq 60 ]; then
51+
echo ">>> 헬스체크 실패! 롤백합니다."
52+
docker stop $NEW_CONTAINER && docker rm $NEW_CONTAINER
53+
exit 1
54+
fi
55+
sleep 1
56+
done
57+
58+
# 새 컨테이너를 네트워크에 연결 (app alias 부여 → 이 순간 트래픽 전환)
59+
echo ">>> 트래픽 전환 중..."
60+
docker network connect --alias app $NETWORK $NEW_CONTAINER
61+
62+
# 이전 컨테이너 네트워크에서 분리 + 정리
63+
if [ -n "$CURRENT" ]; then
64+
echo ">>> 이전 컨테이너($OLD_CONTAINER) 정리 중..."
65+
docker network disconnect $NETWORK $OLD_CONTAINER 2>/dev/null
66+
docker stop $OLD_CONTAINER 2>/dev/null && docker rm $OLD_CONTAINER 2>/dev/null
67+
fi
68+
69+
# 현재 컨테이너 기록
70+
echo $NEW_CONTAINER > /home/ubuntu/app/current_container
71+
72+
# 오래된 Docker 이미지 정리
73+
docker image prune -f
74+
75+
echo ">>> 배포 완료! 활성 컨테이너: $NEW_CONTAINER"

0 commit comments

Comments
 (0)