Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4d49527
#45 feat: EC2 배포용 통합 docker-compose.yml 구성 (프론트+백엔드+DB+nginx)
rimeir Apr 16, 2025
cd3f3b1
#45 feat: feat: nginx 리버스 프록시 및 HTTPS 설정 추가
rimeir Apr 16, 2025
65a8d18
#45 feat: 프론트 SSR용 Dockerfile 작성
rimeir Apr 16, 2025
1fab866
#45 feat: 프론트엔드 GitHub Actions 배포 워크플로우 추가
rimeir Apr 16, 2025
1c291cd
#45 fix: 테스트 환경 파일 비공개
rimeir Apr 16, 2025
ba94204
#45 test: CI/CD 파이프라인 테스트
rimeir Apr 16, 2025
74e25b3
#45 test: CI/CD 파이프라인 테스트 수정
rimeir Apr 16, 2025
20e153d
#45 test: CI/CD 파이프라인 수동 테스트
rimeir Apr 16, 2025
c187345
#45 fix: 프론트엔드 CI/CD 파이프라인 수정
rimeir Apr 16, 2025
9b61c95
#45 fix: 프론트엔드 CI/CD 배포 이미지 이름 수정
rimeir Apr 16, 2025
b5958f3
#45 fix: CI/CD EC2 배포 경로 수정
rimeir Apr 17, 2025
2b4289d
#45 fix: 프론트엔드 CI/CD docker 설정 수정
rimeir Apr 17, 2025
1cc9622
#45 fix: 프론트엔드, 백엔드 CI 분리
rimeir Apr 21, 2025
582ba86
#45 fix: 프론트엔드, 백엔드 통합 CD 구성
rimeir Apr 21, 2025
fd87726
#45 test: 프론트엔드, 백엔드 CI 테스트
rimeir Apr 21, 2025
9aba3fe
#45 fix: 프론트엔드, 백엔드 CI가 성공적으로 완료된 경우에만 동작하도록 설정 및 리전 설정
rimeir Apr 21, 2025
53a561f
#45 fix: 프론트엔드, 백엔드 CI 성공 조건 삭제
rimeir Apr 21, 2025
da09f1f
#45 fix: AWS 자격 증명 구성 설정
rimeir Apr 21, 2025
8e4b3ea
#45 fix: jobs로 CI/CD 통합 파일로 구성
rimeir Apr 21, 2025
5b2bdc0
#45 fix: 프론트 및 백엔드 ECR 이미지 모두 반영
rimeir Apr 21, 2025
f6d6cd1
#45 fix: docker compose ECR 이미지 수정
rimeir Apr 22, 2025
5ddf1ff
Merge remote-tracking branch 'origin/develop' into feature/#45-fronte…
rimeir May 6, 2025
93079bb
#45 fix: docker compose nginx 설정 수정
rimeir May 12, 2025
f188546
#45 fix: nginx 실행 순서 변경
rimeir May 12, 2025
b827ff3
#45 fix: 테스트를 위한 nginx 인증서 발급 부분 삭제
rimeir May 13, 2025
20fc274
#45 fix: nginx 필수 블록 추가
rimeir May 15, 2025
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
109 changes: 64 additions & 45 deletions .github/workflows/backend.yml → .github/workflows/ci_cd_pipeline.yml
Original file line number Diff line number Diff line change
@@ -1,38 +1,51 @@
name: Deploy Backend to EC2
name: CI/CD Pipeline

on:
push:
branches:
- main
- develop
- feature/**
workflow_dispatch:

jobs:
deploy:
frontend:
name: Build & Push Frontend
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Get GitHub Actions Public IP
id: ip
uses: haythem/public-ip@v1.3

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

- name: Add GitHub Actions IP to EC2 security group
- name: Login to Amazon ECR
uses: aws-actions/amazon-ecr-login@v1

- name: Build Docker image and push to AWS ECR
run: |
echo "Authorizing IP ${{ steps.ip.outputs.ipv4 }}"
aws ec2 authorize-security-group-ingress \
--group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \
--protocol tcp \
--port 22 \
--cidr ${{ steps.ip.outputs.ipv4 }}/32
cd frontend
docker build -t frontend-service .
docker tag frontend-service:latest ${{ secrets.AWS_ECR_FRONTEND_REPOSITORY }}:latest
docker push ${{ secrets.AWS_ECR_FRONTEND_REPOSITORY }}:latest

backend:
name: Build & Push Backend
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3

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

- name: Login to AWS ECR
run: |
Expand All @@ -47,69 +60,75 @@ jobs:
docker tag backend-service:latest ${{ secrets.AWS_ECR_REPOSITORY }}:latest
docker push ${{ secrets.AWS_ECR_REPOSITORY }}:latest

- name: Logout from AWS ECR
run: |
docker logout ${{ secrets.AWS_ECR_REPOSITORY }}
echo "Logged out from AWS ECR."
deploy:
name: Deploy to EC2
runs-on: ubuntu-latest
needs: [frontend, backend]
steps:
- uses: actions/checkout@v3

- name: Copy backend directory to EC2
uses: appleboy/ssh-action@master
- name: Get GitHub Actions Public IP
id: ip
uses: haythem/public-ip@v1.3

- name: Configure AWS Credentials
uses: aws-actions/configure-aws-credentials@v2
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
port: 22
source: "backend/*,docker-compose.yml"
target: "/home/${{ secrets.EC2_USERNAME }}/backend"
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2

- name: Deploy to EC2 via SSH
uses: appleboy/ssh-action@master
- name: Authorize GitHub IP
run: |
aws ec2 authorize-security-group-ingress \
--group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \
--protocol tcp \
--port 22 \
--cidr ${{ steps.ip.outputs.ipv4 }}/32

- name: Deploy to EC2 with docker-compose
uses: appleboy/ssh-action@v0.1.10
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_PRIVATE_KEY }}
port: ${{ secrets.PORT }}
script: |
cd /home/${{ secrets.EC2_USERNAME }}/backend
cd /home/${{ secrets.EC2_USERNAME }}/postdm

echo "Logging in to ECR..."
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_REPOSITORY }}
aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin ${{ secrets.AWS_ECR_FRONTEND_REPOSITORY }}

echo "PULLING LATEST IMAGE..."
docker pull ${{ secrets.AWS_ECR_REPOSITORY }}:latest

echo "STOPPING AND REMOVING EXISTING CONTAINERS..."
sudo docker compose down --remove-orphans || true

echo "REMOVING UNUSED DOCKER IMAGES..."
docker image rm ${{ secrets.AWS_ECR_REPOSITORY }}:latest || true

echo "UPDATING .env FILE..."
echo "Updating .env file"
cat <<EOF > .env
MYSQL_URL=${{ secrets.MYSQL_URL }}
MYSQL_USERNAME=${{ secrets.MYSQL_USERNAME }}
MYSQL_PASSWORD=${{ secrets.MYSQL_PASSWORD }}
MYSQL_ROOT_PASSWORD=${{ secrets.MYSQL_ROOT_PASSWORD }}
MYSQL_DATABASE=${{ secrets.MYSQL_DATABASE }}

SPRING_PROFILES_ACTIVE=${{ secrets.SPRING_PROFILES_ACTIVE }}
JWT_SECRET=${{ secrets.JWT_SECRET }}
JWT_EXPIRATION=${{ secrets.JWT_EXPIRATION }}
JWT_EXPIREDMS=${{ secrets.JWT_EXPIREDMS }}
JWT_REFRESHEDMS=${{ secrets.JWT_REFRESHEDMS }}

SPRING_MAIL_HOST=${{ secrets.SPRING_MAIL_HOST }}
SPRING_MAIL_PORT=${{ secrets.SPRING_MAIL_PORT }}
SPRING_MAIL_USERNAME=${{ secrets.SPRING_MAIL_USERNAME }}
SPRING_MAIL_PASSWORD=${{ secrets.SPRING_MAIL_PASSWORD }}

EOF

echo "STARTING NEW CONTAINER..."
sudo docker compose up -d --force-recreate
echo "Pulling latest images..."
docker compose pull

echo "✅ DEPLOYMENT COMPLETE!"
echo "Starting containers..."
docker compose up -d --force-recreate

- name: Remove GitHub Actions IP from EC2 security group
- name: Revoke GitHub IP
if: always()
run: |
echo "Revoking IP ${{ steps.ip.outputs.ipv4 }}"
aws ec2 revoke-security-group-ingress \
--group-id ${{ secrets.AWS_SECURITY_GROUP_ID }} \
--protocol tcp \
Expand Down
65 changes: 42 additions & 23 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,29 +1,6 @@
version: '3.8'

services:
backend:
container_name: backend
image: backend-service
build:
context: backend
dockerfile: Dockerfile
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: ${MYSQL_URL}
SPRING_DATASOURCE_USERNAME: ${MYSQL_USERNAME}
SPRING_DATASOURCE_PASSWORD: ${MYSQL_PASSWORD}
env_file:
- .env
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
interval: 10s
retries: 5
start_period: 20s
timeout: 5s
volumes:
- ./config/application-prod.yml:/app/config/application-prod.yml

db:
container_name: mysql
image: mysql:8.0
Expand All @@ -37,6 +14,48 @@ services:
- "3306:3306"
volumes:
- mysql_data:/var/lib/mysql # 데이터를 Docker Volume에 저장
healthcheck:
test: [ "CMD", "mysqladmin", "ping", "-h", "localhost" ]
interval: 10s
timeout: 5s
retries: 5
start_period: 20s
env_file:
- .env

frontend:
container_name: frontend
image: 536697226608.dkr.ecr.ap-northeast-2.amazonaws.com/postdm/frontend-app
ports:
- "3000:3000"
restart: always

backend:
container_name: backend
image: 536697226608.dkr.ecr.ap-northeast-2.amazonaws.com/postdm/backend-app
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: ${MYSQL_URL}
SPRING_DATASOURCE_USERNAME: ${MYSQL_USERNAME}
SPRING_DATASOURCE_PASSWORD: ${MYSQL_PASSWORD}
env_file:
- .env

nginx:
image: nginx:1.25-alpine
container_name: nginx
depends_on:
- frontend
- backend
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx/nginx.conf:/etc/nginx/nginx.conf
- /etc/letsencrypt:/etc/letsencrypt:ro
- /var/www/html:/var/www/html
restart: always

volumes:
mysql_data: # 데이터 영구 저장 Docker Volume
11 changes: 11 additions & 0 deletions frontend/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM node:18-alpine

WORKDIR /app

COPY . .

RUN npm install
RUN npm run build

EXPOSE 3000
CMD ["npm", "start"]
30 changes: 30 additions & 0 deletions nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
events {}

http {
server {
listen 80;
server_name postdmex.com www.postdmex.com;

location ~ /.well-known/acme-challenge/ {
root /var/www/html;
}

location / {
proxy_pass http://frontend:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

location /api/ {
proxy_pass http://backend:8080;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
Loading