diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..d793ffc --- /dev/null +++ b/.dockerignore @@ -0,0 +1,9 @@ +node_modules +frontend/node_modules +backend/node_modules +frontend/dist +backend/dist +logo +docs +.git +*.md diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..872d9e7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,20 @@ +FROM node:20-alpine +WORKDIR /app + +# 프론트엔드 빌드 +COPY frontend/package*.json ./frontend/ +RUN cd frontend && npm install +COPY frontend/ ./frontend/ +RUN cd frontend && npm run build + +# 백엔드 +COPY backend/package*.json ./backend/ +RUN cd backend && npm install --omit=dev +COPY backend/ ./backend/ + +# 프론트엔드 빌드 결과를 백엔드 dist로 복사 +RUN cp -r frontend/dist backend/dist + +WORKDIR /app/backend +EXPOSE 80 +CMD ["node", "src/server.js"] diff --git a/backend/Dockerfile b/backend/Dockerfile index b68cfc0..b0f436c 100644 --- a/backend/Dockerfile +++ b/backend/Dockerfile @@ -1,4 +1,21 @@ -# 개발 모드 -FROM node:20-alpine +# 배포 모드 +FROM node:20-alpine AS base WORKDIR /app -CMD ["sh", "-c", "npm install && npm run dev"] + +# 프론트엔드 빌드 +COPY frontend/package*.json ./frontend/ +RUN cd frontend && npm ci +COPY frontend/ ./frontend/ +RUN cd frontend && npm run build + +# 백엔드 +COPY backend/package*.json ./backend/ +RUN cd backend && npm ci --production +COPY backend/ ./backend/ + +# 프론트엔드 빌드 결과를 백엔드 dist로 복사 +RUN cp -r frontend/dist backend/dist + +WORKDIR /app/backend +EXPOSE 80 +CMD ["node", "src/server.js"] diff --git a/backend/package.json b/backend/package.json index d79b2b2..5662e6d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -8,6 +8,7 @@ }, "dependencies": { "@fastify/cors": "^11.2.0", + "@fastify/static": "^8.0.0", "dayjs": "^1.11.13", "fastify": "^5.2.1", "fastify-plugin": "^5.0.1", diff --git a/backend/src/app.js b/backend/src/app.js index ee1c1d6..0c4bffe 100644 --- a/backend/src/app.js +++ b/backend/src/app.js @@ -1,10 +1,17 @@ +import fs from 'fs'; +import path from 'path'; +import { fileURLToPath } from 'url'; import Fastify from 'fastify'; import fastifyCors from '@fastify/cors'; +import fastifyStatic from '@fastify/static'; import config from './config/index.js'; import dbPlugin from './plugins/db.js'; import trackerPlugin from './plugins/tracker.js'; import routes from './routes/index.js'; +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + export async function buildApp(opts = {}) { const fastify = Fastify({ logger: { @@ -33,5 +40,22 @@ export async function buildApp(opts = {}) { return { status: 'ok', timestamp: new Date().toISOString() }; }); + // 정적 파일 서빙 (프론트엔드 빌드 결과물) + const distPath = path.join(__dirname, '../dist'); + if (fs.existsSync(distPath)) { + await fastify.register(fastifyStatic, { + root: distPath, + prefix: '/', + }); + + // SPA fallback + fastify.setNotFoundHandler((request, reply) => { + if (request.url.startsWith('/api/')) { + return reply.code(404).send({ error: 'Not found' }); + } + return reply.sendFile('index.html'); + }); + } + return fastify; } diff --git a/docker-compose.yml b/docker-compose.yml index 42e3e5e..a45e089 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,26 +1,11 @@ services: - traeon-frontend: - build: ./frontend - container_name: traeon-frontend - labels: - - "com.centurylinklabs.watchtower.enable=false" - volumes: - - ./frontend:/app - depends_on: - - traeon-backend - networks: - - app - restart: unless-stopped - - traeon-backend: - build: ./backend - container_name: traeon-backend + traeon: + build: . + container_name: traeon labels: - "com.centurylinklabs.watchtower.enable=false" env_file: - .env - volumes: - - ./backend:/app depends_on: - delivery-tracker networks: diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 2f915b7..33c1768 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,4 +1,7 @@ -# 개발 모드 -FROM node:20-alpine +# 프론트엔드 빌드 전용 +FROM node:20-alpine AS build WORKDIR /app -CMD ["sh", "-c", "npm install --include=dev && npm run dev -- --host 0.0.0.0"] +COPY package*.json ./ +RUN npm ci +COPY . . +RUN npm run build diff --git a/frontend/src/pages/MainPage.jsx b/frontend/src/pages/MainPage.jsx index 7310d02..acfd468 100644 --- a/frontend/src/pages/MainPage.jsx +++ b/frontend/src/pages/MainPage.jsx @@ -262,10 +262,10 @@ function MainPage({ showForm, setShowForm }) { e.stopPropagation(); toggleCheck(parcel.id); }} - className={`w-5 h-5 rounded-md border-2 flex items-center justify-center shrink-0 transition-all duration-300 ${ + className={`h-5 rounded-md border-2 flex items-center justify-center shrink-0 transition-all duration-300 ${ deleteMode - ? "opacity-100 scale-100 mr-0" - : "opacity-0 scale-0 w-0 -mr-2" + ? "w-5 opacity-100 scale-100 mr-0" + : "w-0 opacity-0 scale-0 -mr-2" } ${ deleteMode && checkedIds.has(parcel.id) ? "bg-primary border-primary cursor-pointer"