Skip to content

Commit 99f4a5e

Browse files
authored
Merge pull request #9 from Block-Guard/setting/#8/zero-downtime-deployment
[Setting] 무중단 배포 적용
2 parents 59e358d + fdb6f68 commit 99f4a5e

File tree

3 files changed

+44
-7
lines changed

3 files changed

+44
-7
lines changed

.github/workflows/deploy.yml

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,51 @@ jobs:
3838
needs: build
3939

4040
steps:
41-
- name: EC2에 SSH 접속하여 Docker 컨테이너 재배포
41+
- name: EC2에 SSH 접속하여 무중단 배포 수행
4242
uses: appleboy/ssh-action@v0.1.10
4343
with:
4444
host: ${{ secrets.EC2_HOST }}
4545
username: ubuntu
4646
key: ${{ secrets.EC2_PRIVATE_KEY }}
4747
script: |
48+
CURRENT_PORT=$(docker ps --filter "name=blockguard_server_blue" --format "{{.Ports}}" | grep -q "8080" && echo blue || echo green)
49+
50+
if [ "$CURRENT_PORT" = "blue" ]; then
51+
NEW_PORT=8081
52+
NEW_NAME=blockguard_server_green
53+
OLD_NAME=blockguard_server_blue
54+
else
55+
NEW_PORT=8080
56+
NEW_NAME=blockguard_server_blue
57+
OLD_NAME=blockguard_server_green
58+
fi
59+
60+
echo "새 컨테이너 실행: $NEW_NAME (포트: $NEW_PORT)"
4861
docker pull ${{ secrets.DOCKER_USERNAME }}/blockguard_server:latest
49-
docker stop blockguard_server || true
50-
docker rm blockguard_server || true
51-
docker run -d -p 8080:8080 --name blockguard_server ${{ secrets.DOCKER_USERNAME }}/blockguard_server:latest
62+
docker run -d --name $NEW_NAME -p $NEW_PORT:8080 ${{ secrets.DOCKER_USERNAME }}/blockguard_server:latest
63+
64+
echo "헬스체크 진행 중..."
65+
for i in {1..10}; do
66+
STATUS=$(curl -s http://localhost:$NEW_PORT/actuator/health | grep '"status":"UP"' || true)
67+
if [ -n "$STATUS" ]; then
68+
echo "헬스체크 통과"
69+
break
70+
else
71+
echo "⏱ 대기 중..."
72+
sleep 3
73+
fi
74+
done
75+
76+
if [ -z "$STATUS" ]; then
77+
echo "헬스체크 실패: 롤백 없음"
78+
docker logs $NEW_NAME
79+
exit 1
80+
fi
81+
82+
echo "nginx 포트 전환"
83+
sudo sed -i "s/proxy_pass http:\/\/localhost:808[0-9];/proxy_pass http:\/\/localhost:$NEW_PORT;/" /etc/nginx/sites-available/default
84+
sudo nginx -s reload
85+
86+
echo "이전 컨테이너 정리: $OLD_NAME"
87+
docker stop $OLD_NAME || true
88+
docker rm $OLD_NAME || true

build.gradle

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ dependencies {
2727
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
2828
implementation 'org.springframework.boot:spring-boot-starter-security'
2929
implementation 'org.springframework.boot:spring-boot-starter-web'
30+
implementation 'org.springframework.boot:spring-boot-starter-actuator'
31+
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0'
3032
compileOnly 'org.projectlombok:lombok'
3133
runtimeOnly 'com.mysql:mysql-connector-j'
3234
annotationProcessor 'org.projectlombok:lombok'
@@ -37,9 +39,6 @@ dependencies {
3739
implementation 'io.jsonwebtoken:jjwt-api:0.11.5'
3840
implementation 'io.jsonwebtoken:jjwt-impl:0.11.5'
3941
implementation 'io.jsonwebtoken:jjwt-jackson:0.11.5'
40-
41-
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.7.0'
42-
4342
}
4443

4544
tasks.named('test') {

src/main/java/com/blockguard/server/global/config/SecurityConfig.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ public SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Excepti
5454
.authorizeHttpRequests((registry) ->
5555
registry
5656
.requestMatchers("/api/auth/**").permitAll() // 로그인/회원가입만 허용
57+
.requestMatchers("/actuator/health").permitAll() // 헬스체크 허용
5758
.requestMatchers("/v3/api-docs/**", "/swagger-ui.html", "/swagger-ui/**", "/swagger-resources/**", "/webjars/**").permitAll()
5859
.anyRequest().authenticated()
5960
)

0 commit comments

Comments
 (0)