Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
122 changes: 122 additions & 0 deletions .github/workflows/cd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: Deploy to EC2

on:
push:
branches: [ main ]

jobs:
deploy:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4

- name: Docker Build
run: docker build -t eightyage .

- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v2
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_KEY }}
aws-region: ap-northeast-2

- name: ECR Login
run: |
aws ecr get-login-password | \
docker login --username AWS --password-stdin ${{ secrets.ECR_URI }}

- name: Docker Images Check
run: docker images

- name: ECR Push
run: |
docker tag eightyage:latest ${{ secrets.ECR_URI }}
docker push ${{ secrets.ECR_URI }}

- name: Deploy on EC2
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_SSH_KEY }}
envs: ECR_URI,DB_URL,DB_USER,DB_PASSWORD,JWT_SECRET_KEY,AWS_ACCESS_KEY,AWS_SECRET_KEY,REDIS_HOST

script: |
export ECR_URI=${{ secrets.ECR_URI }}
export DB_URL=${{ secrets.DB_URL }}
export DB_USER=${{ secrets.DB_USER }}
export DB_PASSWORD=${{ secrets.DB_PASSWORD }}
export JWT_SECRET_KEY=${{ secrets.JWT_SECRET_KEY }}
export AWS_ACCESS_KEY=${{ secrets.AWS_ACCESS_KEY }}
export AWS_SECRET_KEY=${{ secrets.AWS_SECRET_KEY }}
export REDIS_HOST=${{ secrets.REDIS_HOST }}

docker ps -q --filter ancestor=$ECR_URI | xargs -r docker stop
docker ps -aq --filter ancestor=$ECR_URI | xargs -r docker rm

aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin $ECR_URI
docker pull $ECR_URI
docker run -d -p 8080:8080 \
-e DB_URL=$DB_URL \
-e DB_USER=$DB_USER \
-e DB_PASSWORD=$DB_PASSWORD \
-e JWT_SECRET_KEY=$JWT_SECRET_KEY \
-e AWS_ACCESS_KEY=$AWS_ACCESS_KEY \
-e AWS_SECRET_KEY=$AWS_SECRET_KEY \
-e REDIS_HOST=$REDIS_HOST \
$ECR_URI

- name: Health Check
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.EC2_HOST }}
username: ubuntu
key: ${{ secrets.EC2_SSH_KEY }}
script: |
for i in {1..10}; do
echo "⏳ Health check attempt $i..."
if curl -f http://localhost:8080/actuator/health; then
echo "✅ Health check succeeded!"
exit 0
fi
sleep 5
done
echo "❌ Health check failed after multiple attempts"
exit 1

- name: Notify Slack - 배포 성공
if: success()
run: |
curl -X POST -H 'Content-type: application/json' \
--data '{
"text": "✅ *배포 성공!* 🎉",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*✅ 배포 성공했습니다!*\n\n*브랜치:* `${{ github.ref_name }}`\n<http://3.39.158.229:8080/actuator/health|🔗 배포된 서비스 상태 보기>"
}
}
]
}' \
${{ secrets.SLACK_WEBHOOK_URL }}

- name: Notify Slack - 배포 실패
if: failure()
run: |
curl -X POST -H 'Content-type: application/json' \
--data '{
"text": "❌ *배포 실패!* 🔥",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "*❌ 배포 실패했습니다!*\n\n*브랜치:* `${{ github.ref_name }}`\n<https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}|🔗 실패 로그 확인하기>"
}
}
]
}' \
${{ secrets.SLACK_WEBHOOK_URL }}
12 changes: 12 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM gradle:8.6-jdk17 AS build
WORKDIR /app
COPY . .
RUN gradle clean build -x test

FROM eclipse-temurin:17-jdk-alpine
WORKDIR /app

COPY --from=build /app/build/libs/*.jar app.jar
EXPOSE 8080

ENTRYPOINT ["java", "-Dspring.profiles.active=prod", "-jar", "app.jar"]
2 changes: 2 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ dependencies {
implementation 'org.redisson:redisson:3.23.5'

testImplementation 'org.mockito:mockito-inline:5.2.0'

implementation 'org.springframework.boot:spring-boot-starter-actuator'
}

tasks.named('test') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,19 @@
import org.redisson.config.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;

@Configuration
public class RedissonConfig {

@Value("${spring.data.redis.host}")
private String redisHost;

@Bean
public RedissonClient redisson() {
Config config = new Config();
config.useSingleServer()
.setAddress("redis://localhost:6379");
return Redisson.create();
.setAddress("redis://" + redisHost + ":6379");
return Redisson.create(config);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Excepti
.rememberMe(AbstractHttpConfigurer::disable)
.authorizeHttpRequests(auth -> auth
.requestMatchers(request -> request.getRequestURI().startsWith("/api/v1/auth")).permitAll()
.requestMatchers("/actuator/**").permitAll()
.anyRequest().authenticated()
)
.build();
Expand Down
50 changes: 50 additions & 0 deletions src/main/resources/application-prod.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
server:
port: 8080
servlet:
context-path: /
encoding:
charset: UTF-8
enabled: true
force: true
session:
timeout: 1800

spring:
application:
name: eightyage

data:
redis:
host: ${SPRING_DATA_REDIS_HOST}
port: 6379

datasource:
url: ${DB_URL}
username: ${DB_USER}
password: ${DB_PASSWORD}
driver-class-name: com.mysql.cj.jdbc.Driver

jpa:
hibernate:
ddl-auto: update
properties:
hibernate:
show_sql: false
format_sql: true
use_sql_comments: false
dialect: org.hibernate.dialect.MySQLDialect

jwt:
secret:
key: ${JWT_SECRET_KEY}

management:
endpoints:
web:
exposure:
include: health,info
endpoint:
health:
show-details: always
security:
enabled: false