Skip to content

Commit 642fa2c

Browse files
authored
Merge pull request #47 from team8-nbc/cd/setup
[feat] EC2 ๋ฐฐํฌ ์ž๋™ํ™”๋ฅผ ์œ„ํ•œ CD ํŒŒ์ดํ”„๋ผ์ธ ๊ตฌ์ถ•
2 parents f6200a2 + 60e9bf9 commit 642fa2c

File tree

6 files changed

+193
-2
lines changed

6 files changed

+193
-2
lines changed

โ€Ž.github/workflows/cd.ymlโ€Ž

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
name: Deploy to EC2
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
7+
jobs:
8+
deploy:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout
12+
uses: actions/checkout@v4
13+
14+
- name: Docker Build
15+
run: docker build -t eightyage .
16+
17+
- name: Configure AWS credentials
18+
uses: aws-actions/configure-aws-credentials@v2
19+
with:
20+
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
21+
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
22+
aws-region: ap-northeast-2
23+
24+
- name: ECR Login
25+
run: |
26+
aws ecr get-login-password | \
27+
docker login --username AWS --password-stdin ${{ secrets.ECR_URI }}
28+
29+
- name: Docker Images Check
30+
run: docker images
31+
32+
- name: ECR Push
33+
run: |
34+
docker tag eightyage:latest ${{ secrets.ECR_URI }}
35+
docker push ${{ secrets.ECR_URI }}
36+
37+
- name: Deploy on EC2
38+
uses: appleboy/ssh-action@v1
39+
with:
40+
host: ${{ secrets.EC2_HOST }}
41+
username: ubuntu
42+
key: ${{ secrets.EC2_SSH_KEY }}
43+
envs: ECR_URI,DB_URL,DB_USER,DB_PASSWORD,JWT_SECRET_KEY,AWS_ACCESS_KEY,AWS_SECRET_KEY,REDIS_HOST
44+
45+
script: |
46+
export ECR_URI=${{ secrets.ECR_URI }}
47+
export DB_URL=${{ secrets.DB_URL }}
48+
export DB_USER=${{ secrets.DB_USER }}
49+
export DB_PASSWORD=${{ secrets.DB_PASSWORD }}
50+
export JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }}
51+
export AWS_ACCESS_KEY=${{ secrets.AWS_ACCESS_KEY }}
52+
export AWS_SECRET_KEY=${{ secrets.AWS_SECRET_KEY }}
53+
export REDIS_HOST=${{ secrets.REDIS_HOST }}
54+
55+
docker ps -q --filter ancestor=$ECR_URI | xargs -r docker stop
56+
docker ps -aq --filter ancestor=$ECR_URI | xargs -r docker rm
57+
58+
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $ECR_URI
59+
docker pull $ECR_URI
60+
docker run -d -p 8080:8080 \
61+
-e DB_URL=$DB_URL \
62+
-e DB_USER=$DB_USER \
63+
-e DB_PASSWORD=$DB_PASSWORD \
64+
-e JWT_SECRET_KEY=$JWT_SECRET_KEY \
65+
-e AWS_ACCESS_KEY=$AWS_ACCESS_KEY \
66+
-e AWS_SECRET_KEY=$AWS_SECRET_KEY \
67+
-e REDIS_HOST=$REDIS_HOST \
68+
$ECR_URI
69+
70+
- name: Health Check
71+
uses: appleboy/ssh-action@v1
72+
with:
73+
host: ${{ secrets.EC2_HOST }}
74+
username: ubuntu
75+
key: ${{ secrets.EC2_SSH_KEY }}
76+
script: |
77+
for i in {1..10}; do
78+
echo "โณ Health check attempt $i..."
79+
if curl -f http://localhost:8080/actuator/health; then
80+
echo "โœ… Health check succeeded!"
81+
exit 0
82+
fi
83+
sleep 5
84+
done
85+
echo "โŒ Health check failed after multiple attempts"
86+
exit 1
87+
88+
- name: Notify Slack - ๋ฐฐํฌ ์„ฑ๊ณต
89+
if: success()
90+
run: |
91+
curl -X POST -H 'Content-type: application/json' \
92+
--data '{
93+
"text": "โœ… *๋ฐฐํฌ ์„ฑ๊ณต!* ๐ŸŽ‰",
94+
"blocks": [
95+
{
96+
"type": "section",
97+
"text": {
98+
"type": "mrkdwn",
99+
"text": "*โœ… ๋ฐฐํฌ ์„ฑ๊ณตํ–ˆ์Šต๋‹ˆ๋‹ค!*\n\n*๋ธŒ๋žœ์น˜:* `${{ github.ref_name }}`\n<http://3.39.158.229:8080/actuator/health|๐Ÿ”— ๋ฐฐํฌ๋œ ์„œ๋น„์Šค ์ƒํƒœ ๋ณด๊ธฐ>"
100+
}
101+
}
102+
]
103+
}' \
104+
${{ secrets.SLACK_WEBHOOK_URL }}
105+
106+
- name: Notify Slack - ๋ฐฐํฌ ์‹คํŒจ
107+
if: failure()
108+
run: |
109+
curl -X POST -H 'Content-type: application/json' \
110+
--data '{
111+
"text": "โŒ *๋ฐฐํฌ ์‹คํŒจ!* ๐Ÿ”ฅ",
112+
"blocks": [
113+
{
114+
"type": "section",
115+
"text": {
116+
"type": "mrkdwn",
117+
"text": "*โŒ ๋ฐฐํฌ ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค!*\n\n*๋ธŒ๋žœ์น˜:* `${{ github.ref_name }}`\n<https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|๐Ÿ”— ์‹คํŒจ ๋กœ๊ทธ ํ™•์ธํ•˜๊ธฐ>"
118+
}
119+
}
120+
]
121+
}' \
122+
${{ secrets.SLACK_WEBHOOK_URL }}

โ€ŽDockerfileโ€Ž

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
FROM gradle:8.6-jdk17 AS build
2+
WORKDIR /app
3+
COPY . .
4+
RUN gradle clean build -x test
5+
6+
FROM eclipse-temurin:17-jdk-alpine
7+
WORKDIR /app
8+
9+
COPY --from=build /app/build/libs/*.jar app.jar
10+
EXPOSE 8080
11+
12+
ENTRYPOINT ["java", "-Dspring.profiles.active=prod", "-jar", "app.jar"]

โ€Žbuild.gradleโ€Ž

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ dependencies {
5959
implementation 'org.redisson:redisson:3.23.5'
6060

6161
testImplementation 'org.mockito:mockito-inline:5.2.0'
62+
63+
implementation 'org.springframework.boot:spring-boot-starter-actuator'
6264
}
6365

6466
tasks.named('test') {

โ€Žsrc/main/java/com/example/eightyage/global/config/RedissonConfig.javaโ€Ž

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@
55
import org.redisson.config.Config;
66
import org.springframework.context.annotation.Bean;
77
import org.springframework.context.annotation.Configuration;
8+
import org.springframework.beans.factory.annotation.Value;
89

910
@Configuration
1011
public class RedissonConfig {
1112

13+
@Value("${spring.data.redis.host}")
14+
private String redisHost;
15+
1216
@Bean
1317
public RedissonClient redisson() {
1418
Config config = new Config();
1519
config.useSingleServer()
16-
.setAddress("redis://localhost:6379");
17-
return Redisson.create();
20+
.setAddress("redis://" + redisHost + ":6379");
21+
return Redisson.create(config);
1822
}
1923
}

โ€Žsrc/main/java/com/example/eightyage/global/config/SecurityConfig.javaโ€Ž

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
4242
.rememberMe(AbstractHttpConfigurer::disable)
4343
.authorizeHttpRequests(auth -> auth
4444
.requestMatchers(request -> request.getRequestURI().startsWith("/api/v1/auth")).permitAll()
45+
.requestMatchers("/actuator/**").permitAll()
4546
.anyRequest().authenticated()
4647
)
4748
.build();
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
server:
2+
port: 8080
3+
servlet:
4+
context-path: /
5+
encoding:
6+
charset: UTF-8
7+
enabled: true
8+
force: true
9+
session:
10+
timeout: 1800
11+
12+
spring:
13+
application:
14+
name: eightyage
15+
16+
data:
17+
redis:
18+
host: ${SPRING_DATA_REDIS_HOST}
19+
port: 6379
20+
21+
datasource:
22+
url: ${DB_URL}
23+
username: ${DB_USER}
24+
password: ${DB_PASSWORD}
25+
driver-class-name: com.mysql.cj.jdbc.Driver
26+
27+
jpa:
28+
hibernate:
29+
ddl-auto: update
30+
properties:
31+
hibernate:
32+
show_sql: false
33+
format_sql: true
34+
use_sql_comments: false
35+
dialect: org.hibernate.dialect.MySQLDialect
36+
37+
jwt:
38+
secret:
39+
key: ${JWT_SECRET_KEY}
40+
41+
management:
42+
endpoints:
43+
web:
44+
exposure:
45+
include: health,info
46+
endpoint:
47+
health:
48+
show-details: always
49+
security:
50+
enabled: false

0 commit comments

Comments
ย (0)