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
37 changes: 37 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
node_modules
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

개발 관련 파일, 테스트 파일 잘 제외하셨네요!

# Keep environment variables out of version control
.env
.env.test

/generated/prisma
.DS_Store

# 기타 파일
erd/
archive/
http/
infra/
scripts/
test/
DockerImage.txt

# Git
.git
.gitignore
.github

# Logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Dependency
.npm
.yarn-cache

# Build outputs
/dist
/build

# Test coverage
coverage/
5 changes: 4 additions & 1 deletion .env.sample
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
DATABASE_URL="postgresql://아이디:비번@localhost:5432/db이름?schema=public"
# 도커용
DATABASE_URL=postgresql://devuser:devpassword@localhost:5432/devdatabase?schema=public
# 실제 db용
DATABASE_URL=postgresql://아이디:비번@localhost:5432/db이름?schema=public

PORT=3000
CORS_ORIGIN=http://localhost:3000
Expand Down
94 changes: 94 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
name: Deploy to AWS EC2

on:
push:
branches:
- main

env:
AWS_REGION: ap-northeast-2 # 서울 리전
ECR_REPOSITORY: uju-api-sever # ECR 리포지토리 이름
DOCKER_CONTAINER_NAME: 4-sprint-mission-server # EC2에서 실행할 컨테이너 이름

jobs:
build-and-deploy:
name: Build and Deploy to EC2
runs-on: ubuntu-latest

steps:
- name: Checkout
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: ${{ env.AWS_REGION }}

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR
id: build-image
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
IMAGE_TAG: ${{ github.sha }}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

오 sha로 태깅한것 훌륭합니다.

run: |
IMAGE_URI=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker build --build-arg NODE_VERSION=22.17.1 -t $IMAGE_URI .
docker push $IMAGE_URI
echo "IMAGE_URI=$IMAGE_URI" >> $GITHUB_ENV

- name: Get GitHub Actions Runner IP
id: get_ip
run: echo "ip=$(curl -s http://checkip.amazonaws.com)" >> $GITHUB_OUTPUT

- name: Add Runner IP to EC2 Security Group
run: |
aws ec2 authorize-security-group-ingress \
--group-id ${{ secrets.EC2_SECURITY_GROUP_ID }} \
--protocol tcp \
--port 22 \
--cidr ${{ steps.get_ip.outputs.ip }}/32

- name: Get ECR Login Password
id: ecr_password
run: echo "ECR_PASSWORD=$(aws ecr get-login-password --region ${{ env.AWS_REGION }})" >> $GITHUB_ENV

- name: Deploy to EC2 instance
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.EC2_HOST }}
username: ${{ secrets.EC2_USERNAME }}
key: ${{ secrets.EC2_SSH_KEY }}
script: |
echo ${{ env.ECR_PASSWORD }} | docker login --username AWS --password-stdin ${{ steps.login-ecr.outputs.registry }}

cd /home/ec2-user/4-sprint-mission

docker stop ${{ env.DOCKER_CONTAINER_NAME }} || true
docker rm ${{ env.DOCKER_CONTAINER_NAME }} || true

docker image prune -a -f

docker pull ${{ env.IMAGE_URI }}

docker run \
-d \
--name ${{ env.DOCKER_CONTAINER_NAME }} \
--restart always \
-p 3000:3000 \
--env-file ./.env \
-e DATABASE_URL='${{ secrets.DATABASE_URL }}' \
${{ env.IMAGE_URI }}

- name: Remove Runner IP from EC2 Security Group
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

보안 신경쓴 것 좋습니다!

if: always()
run: |
aws ec2 revoke-security-group-ingress \
--group-id ${{ secrets.EC2_SECURITY_GROUP_ID }} \
--protocol tcp \
--port 22 \
--cidr ${{ steps.get_ip.outputs.ip }}/32
68 changes: 68 additions & 0 deletions .github/workflows/pr-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
name: PR test Check (DB 포함)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Postgres 컨테이너까지 띄워서 통합 테스트를 안정적으로 실행하는 것 좋네요!


on: pull_request

jobs:
test:
runs-on: ubuntu-latest

services:
postgres:
image: postgres:16.5
env:
POSTGRES_USER: ci_user
POSTGRES_PASSWORD: ci_password

POSTGRES_DB: test_db
ports:
- 5432:5432
options: >-
--health-cmd pg_isready
--health-interval 5s
--health-timeout 5s
--health-retries 5

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

- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 22

- name: Install dependencies
run: npm ci

- name: Run Integration Tests
run: |
echo "Waiting for PostgreSQL service to be fully ready..."
sleep 5

echo "Running Prisma migrate deploy..."
npx prisma migrate deploy

echo "Running Prisma generate..."
npx prisma generate

echo "Running npm tests..."
npm test && echo "✅ Test Passed" || (echo "❌ Test Failed" && exit 1)
env:
DATABASE_URL: postgres://ci_user:ci_password@localhost:5432/test_db?schema=public
DB_HOST: localhost
DB_PORT: 5432
DB_USER: ci_user
DB_PASSWORD: ci_password
DB_NAME: test_db

JWT_ACCESS_TOKEN_SECRET: 'ci_test_access_token_secret_123'
JWT_REFRESH_TOKEN_SECRET: 'ci_test_refresh_token_secret_456'

CLOUDINARY_CLOUD_NAME: 'ci-test-cloud'
CLOUDINARY_API_KEY: '123456789012345'
CLOUDINARY_API_SECRET: 'ci_test_cloudinary_secret_key'

AWS_S3_BUCKET_NAME: 'ci-test-bucket'
AWS_S3_REGION: 'us-east-1'
AWS_ACCESS_KEY_ID: 'ASIA_CI_TEST_KEY'
AWS_SECRET_ACCESS_KEY: 'ci_test_aws_secret_key_abcdef'
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ yarn-debug.log*
yarn-error.log*

# Dependency
/node_modules
/frontend/node_modules
/backend/node_modules
.npm
.yarn-cache

Expand Down
27 changes: 27 additions & 0 deletions DockerImage.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
도커 빌드
docker image build \
-t parkdaseul/uju-api:1.0.0-slim-express \
--build-arg NODE_VERSION=22.17.1 \
-f ./Dockerfile \
--pull \
.

도커 허브 push
docker push parkdaseul/uju-api:1.0.0-express

도커 컨테이너 마이그레이션 1회성 생성
docker run \
--rm \
--name uju-api-migration \
--env-file ./.env \
parkdaseul/uju-api:1.0.0-slim-express \
npx prisma migrate deploy

도커 컨테이터 생성
docker run \
-d \
--rm \
--name uju-api-container \
-p 3000:3000 \
--env-file ./.env \
parkdaseul/uju-api:1.0.0-slim-express
39 changes: 39 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# ----------------------------------------------------------------------
# 1단계: 빌드 스테이지 (Builder Stage)
# ----------------------------------------------------------------------
ARG NODE_VERSION=
FROM node:${NODE_VERSION}-slim AS builder
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

github action에서는 괜찮을 것 같은데 docker-compose에서는 NODE_VERSION환경변수가 빠져서 보완이 필요할 것 같습니다.


WORKDIR /app

COPY package.json package-lock.json ./
RUN npm ci

RUN apt-get update && \
apt-get install -y openssl libssl-dev && \
rm -rf /var/lib/apt/lists/*

COPY . .
RUN npx prisma generate --schema=./prisma/schema.prisma
RUN npm run build

# ----------------------------------------------------------------------
# 2단계: 실행 스테이지 (Runtime Stage)
# ----------------------------------------------------------------------
FROM node:${NODE_VERSION}-slim AS runner

WORKDIR /app

RUN apt-get update && \
apt-get install -y openssl libssl-dev && \
rm -rf /var/lib/apt/lists/*

COPY package.json package-lock.json ./
RUN npm ci --only=production

COPY --from=builder /app/dist ./dist
COPY --from=builder /app/node_modules/.prisma/client ./node_modules/.prisma/client
COPY --from=builder /app/prisma ./prisma

ENV NODE_ENV=production
CMD ["node", "dist/server.js"]
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# 🚀 UJU API 서버

10번째 스프린트 미션을 위해 제작된 API 서버입니다. 이 서버는 상품 및 게시글 관리를 위한 백엔드 서비스를 제공하며, 사용자 인증, 실시간 알림 등 다양한 기능을 포함하고 있습니다.
11번째 스프린트 미션을 위해 제작된 API 서버입니다. 이 서버는 상품 및 게시글 관리를 위한 백엔드 서비스를 제공하며, 사용자 인증, 실시간 알림 등 다양한 기능을 포함하고 있습니다.

## ✨ 주요 기능

Expand All @@ -24,6 +24,7 @@
- **실시간 통신:** Socket.io
- **환경 변수 관리:** Dotenv
- **코드 포맷팅:** Prettier
- **컨테이너:** Docker, Docker Compose

## 🚀 배포

Expand Down Expand Up @@ -81,6 +82,7 @@
- Node.js (v18 이상 권장)
- npm
- PostgreSQL 데이터베이스
- [Docker Desktop](https://www.docker.com/products/docker-desktop/)

### 설치 및 설정

Expand Down
37 changes: 37 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
version: '3.8'

services:
db:
image: postgres:16.5
container_name: my-local-postgres
restart: always
ports:
- '5432:5432'
environment:
POSTGRES_USER: devuser
POSTGRES_PASSWORD: devpassword
POSTGRES_DB: devdatabase
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ['CMD-SHELL', 'pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB']
interval: 5s
timeout: 5s
retries: 5

app:
build: .
container_name: my-app-container
ports:
- '3000:3000'
env_file:
- ./.env
volumes:
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

전체 소스 마운트하는게 개발환경에서는 편리한데 프로덕션에서는 빌드된 이미지만 포함하는게 좋아요~ 환경을 분리해서 docker-compose를 작성해보면 좋을 것 같습니다!

- .:/app
- /app/node_modules
depends_on:
db:
condition: service_healthy

volumes:
postgres-data: