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
14 changes: 11 additions & 3 deletions .github/workflows/Backend-CD.yml
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ jobs:
HEALTH_PORT="${{ env.HEALTH_CHECK_PORT }}"
NET="${{ env.DOCKER_NETWORK }}"
ENV_FILE="/tmp/relife.env"
DOCKER_PROJECT_DIR="/dockerProjects/relife_app"

echo "🔹 Use image: ${IMAGE}"
if ! docker pull "${IMAGE}"; then
Expand Down Expand Up @@ -317,21 +318,28 @@ jobs:
# ---------------------------------------------------------
# 4) green 역할 컨테이너 재기동
# - 같은 네트워크 상에서 NPM이 컨테이너명:PORT로 프록시하므로 -p 불필요
# - 호스트 볼륨 마운트로 Blue/Green 간 데이터 영속성 보장
# ---------------------------------------------------------
docker rm -f "${GREEN}" >/dev/null 2>&1 || true

# 볼륨 디렉토리 생성 (없으면)
mkdir -p ${DOCKER_PROJECT_DIR}/{data,logs}

echo "🚀 run new container → ${GREEN}"
docker run -d --name "${GREEN}" \
--restart unless-stopped \
--network "${NET}" \
--env-file "${ENV_FILE}" \
-e TZ=Asia/Seoul \
-v ${DOCKER_PROJECT_DIR}/data:/app/data \
-v ${DOCKER_PROJECT_DIR}/logs:/app/logs \
"${IMAGE}"

# ---------------------------------------------------------
# 5) 헬스체크 (/actuator/health/readiness 200 OK까지 대기)
# ---------------------------------------------------------
echo "⏱ health-check: ${GREEN}"
TIMEOUT=120
TIMEOUT=180
INTERVAL=3
ELAPSED=0
sleep 8 # 초기 부팅 여유
Expand All @@ -350,7 +358,7 @@ jobs:

if [[ "${CODE:-000}" != "200" ]]; then
echo "❌ ${GREEN} health failed"
docker logs --tail=200 "${GREEN}" || true
docker logs --tail=300 "${GREEN}" || true
docker rm -f "${GREEN}" || true
exit 1;
fi
Expand All @@ -371,7 +379,7 @@ jobs:
else
echo "❌ Failed to switch upstream! Received HTTP status code: ${HTTP_CODE}"
# [수정] 전환 실패 시, 새로 띄운 Green 컨테이너는 즉시 제거하고 실패 처리
docker logs --tail=200 "${GREEN}" || true
docker logs --tail=300 "${GREEN}" || true
docker rm -f "${GREEN}" || true
exit 1
fi
Expand Down
2 changes: 1 addition & 1 deletion back/docker-compose-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ services:
environment:
TZ: "Asia/Seoul"
volumes:
- /dockerProjects/redis_1/volumes/data:/data
- ~/dockerProjects/redis_1/volumes/data:/data

networks:
common:
Expand Down
73 changes: 48 additions & 25 deletions infra/aws/terraform/cloudfront.tf
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ resource "aws_cloudfront_distribution" "cloudfront_distribution" {
cached_methods = ["GET", "HEAD"]
target_origin_id = "S3-${aws_s3_bucket.s3_1.id}"
viewer_protocol_policy = "redirect-to-https"
compress = true # Gzip/Brotli 압축 활성화

forwarded_values {
query_string = false
Expand All @@ -39,10 +40,10 @@ resource "aws_cloudfront_distribution" "cloudfront_distribution" {
}
}

# 캐시 설정
# 캐시 설정 - 정적 리소스는 길게
min_ttl = 0
default_ttl = 86400
max_ttl = 31536000
default_ttl = 86400 # 1일
max_ttl = 31536000 # 1년
}

restrictions {
Expand All @@ -51,9 +52,22 @@ resource "aws_cloudfront_distribution" "cloudfront_distribution" {
}
}

# 존재하지 않는 오브젝트 요청 시
custom_error_response {
error_caching_min_ttl = 600
error_code = 404
error_caching_min_ttl = 300 # 5분 (에러 캐싱으로 Origin 부하 감소)
}

# 권한 없음 에러 (예: S3 퍼미션 문제)
custom_error_response {
error_code = 403
error_caching_min_ttl = 120
}

# S3 서비스 장애 시
custom_error_response {
error_code = 503
error_caching_min_ttl = 10
}

# 과금 정책
Expand All @@ -62,15 +76,15 @@ resource "aws_cloudfront_distribution" "cloudfront_distribution" {
# PriceClass_All: 전세계
price_class = "PriceClass_100"

# fixme: CDN 도메인 설정
# aliases = [var.cdn_domain]
# CDN 도메인 설정
aliases = [var.cdn_domain]

viewer_certificate {
cloudfront_default_certificate = true
# fixme: ACM 인증서 사용(CDN 도메인 설정) 시 아래 주석 해제
# acm_certificate_arn = aws_acm_certificate.cdn_domain_cert.arn
# ssl_support_method = "sni-only"
# minimum_protocol_version = "TLSv1.2_2021"
# cloudfront_default_certificate = true
# ACM 인증서 사용(CDN 도메인 설정) 시 아래 주석 해제
acm_certificate_arn = aws_acm_certificate_validation.cdn_domain_cert_validation.certificate_arn
ssl_support_method = "sni-only"
minimum_protocol_version = "TLSv1.2_2021"
}

tags = merge(local.common_tags, {
Expand All @@ -82,17 +96,26 @@ resource "aws_cloudfront_distribution" "cloudfront_distribution" {
# ACM 인증서
##################
# CloudFront는 us-east-1 리전에 있어야 함
# fixme: CDN 도메인 설정 시 주석 해제
# resource "aws_acm_certificate" "cdn_domain_cert" {
# provider = "us-east-1"
# domain_name = var.cdn_domain
# validation_method = "DNS"
#
# lifecycle {
# create_before_destroy = true
# }
#
# tags = merge(local.common_tags, {
# Name = "${var.prefix}-cdn-domain-cert"
# })
# }
resource "aws_acm_certificate" "cdn_domain_cert" {
provider = aws.us_east_1
domain_name = var.cdn_domain
key_algorithm = "EC_prime256v1"
validation_method = "DNS"

lifecycle {
create_before_destroy = true
}

tags = merge(local.common_tags, {
Name = "${var.prefix}-cdn-domain-cert"
})
}

resource "aws_acm_certificate_validation" "cdn_domain_cert_validation" {
provider = aws.us_east_1
certificate_arn = aws_acm_certificate.cdn_domain_cert.arn

timeouts {
create = "1h"
}
}
7 changes: 4 additions & 3 deletions infra/aws/terraform/ec2.tf
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,10 @@ resource "aws_instance" "ec2_1" {

# 루트 볼륨 설정
root_block_device {
volume_type = "gp2"
volume_size = 30 # 볼륨 크기를 30GB로 설정
encrypted = true
volume_type = "gp2"
volume_size = 30 # 볼륨 크기를 30GB로 설정
encrypted = true
delete_on_termination = false
}

user_data = local.ec2_user_data
Expand Down
8 changes: 7 additions & 1 deletion infra/aws/terraform/main.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
########################################################
# 마지막 수정: 251001
# 마지막 수정: 251010
# 작성자: gooraeng
#
# AWS 인프라를 코드로 관리하기 위한 Terraform 메인 설정 파일
Expand Down Expand Up @@ -29,6 +29,12 @@ provider "aws" {
region = var.region
}

# CloudFront는 us-east-1 리전의 ACM 인증서가 필요
provider "aws" {
alias = "us_east_1"
region = "us-east-1"
}

################
# 로컬 변수
################
Expand Down
41 changes: 20 additions & 21 deletions infra/aws/terraform/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,23 @@ output "cloudfront_domain" {
##################
# ACM 인증서 출력 (CDN 도메인 설정 시)
##################
# fixme: CDN 도메인 설정 시 주석 해제
# output "cdn_domain_cert_arn" {
# description = "ACM Certificate ARN"
# value = aws_acm_certificate.cdn_domain_cert.arn
# }
#
# output "cdn_domain_cert_status" {
# description = "Certificate Status"
# value = aws_acm_certificate.cdn_domain_cert.status
# }
#
# output "cdn_domain_cert_validation_records" {
# description = "DNS validation records for certificate"
# value = {
# for dvo in aws_acm_certificate.cdn_domain_cert.domain_validation_options : dvo.domain_name => {
# name = dvo.resource_record_name
# record = dvo.resource_record_value
# type = dvo.resource_record_type
# }
# }
# }
output "cdn_domain_cert_arn" {
description = "ACM Certificate ARN"
value = aws_acm_certificate.cdn_domain_cert.arn
}

output "cdn_domain_cert_status" {
description = "Certificate Status"
value = aws_acm_certificate.cdn_domain_cert.status
}

output "cdn_domain_cert_validation_records" {
description = "DNS validation records for certificate"
value = {
for dvo in aws_acm_certificate.cdn_domain_cert.domain_validation_options : dvo.domain_name => {
name = dvo.resource_record_name
record = dvo.resource_record_value
type = dvo.resource_record_type
}
}
}
24 changes: 8 additions & 16 deletions infra/aws/terraform/s3.tf
Original file line number Diff line number Diff line change
Expand Up @@ -36,37 +36,29 @@ resource "aws_s3_bucket_ownership_controls" "s3_1_ownership" {
# S3 버킷 정책
#########################
# CloudFront OAI가 S3 버킷에 접근할 수 있도록 허용
# EC2 인스턴스가 파일 업로드/관리 가능
# AWS 계정 소유자 및 Admin 사용자 접근 허용
# Presigned URL을 통한 접근 차단
resource "aws_s3_bucket_policy" "s3_1_policy" {
bucket = aws_s3_bucket.s3_1.id
policy = jsonencode({
Version = "2012-10-17",
Statement = [
# CloudFront가 S3 버킷에 접근할 수 있도록 허용
# 1. CloudFront OAI: S3 객체 읽기 (CDN 콘텐츠 제공)
{
Sid = "AllowCloudFrontOAIReadOnly",
Effect = "Allow",
Principal = {
AWS = aws_cloudfront_origin_access_identity.oai_1.iam_arn
},
Action = "s3:GetObject",
Resource = "${aws_s3_bucket.s3_1.arn}/*"
},
# Presigned URL을 통한 접근 차단
{
Sid = "DenyPresignedUrls",
Effect = "Deny",
Principal = "*",
Action = "s3:*",
Action = [
"s3:GetObject",
"s3:ListBucket"
],
Resource = [
aws_s3_bucket.s3_1.arn,
"${aws_s3_bucket.s3_1.arn}/*"
],
Condition = {
StringLike = {
"s3:authType" = "REST-QUERY-STRING"
}
}
]
}
]
})
Expand Down
11 changes: 5 additions & 6 deletions infra/aws/terraform/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,11 @@ variable "base_domain" {
default = "relife.kr"
}

# fixme: CDN 도메인 변수
# variable "cdn_domain" {
# description = "cdn domain"
# type = string
# default = "cdn.gooraeng.xyz"
# }
variable "cdn_domain" {
description = "cdn domain"
type = string
default = "cdn.relife.kr"
}

variable "encryption_type" {
description = "S3 암호화 타입 (AES256, aws:kms)"
Expand Down