Compare commits

..

8 Commits

Author SHA1 Message Date
ttipo 67f5d815c9 DB 서비스 이름을 postgres에서 db로 변경
Deploy / deploy (push) Successful in 20s
- depends_on, DB_HOST 기본값도 db로 갱신
- deploy: 서비스 이름 변경으로 남는 orphan 컨테이너 정리를 위해 --remove-orphans 추가

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 18:15:38 +09:00
ttipo f3e97d6c44 DB 데이터 경로를 프로젝트 폴더 기준 상대 경로로 변경
Deploy / deploy (push) Successful in 15s
- DB_DATA_DIR 기본값 /data/postgres -> ./data/postgres (다른 스택과 동일하게 프로젝트 폴더 하위에 생성)
- data/ gitignore 추가
- deploy: backend/frontend를 매 배포마다 force-recreate - DB 교체 시 스키마 미동기화, nginx 낡은 upstream 캐시 문제 방지

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 18:02:38 +09:00
ttipo 126c0169aa DB 볼륨을 /data/postgres 바인드 마운트로 변경
Deploy / deploy (push) Successful in 35s
- named volume 대신 호스트 경로 바인드 마운트 사용 (DB_DATA_DIR, 기본 /data/postgres)
- backend: DB 연결/동기화 실패 시 프로세스 종료 - restart: always가 DB 준비까지 재시도하도록 fail-fast 적용

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:56:44 +09:00
ttipo 8770b1b47b 호스트 포트 매핑 제거, npm 프록시 경유 구조로 전환
Deploy / deploy (push) Successful in 19s
- 모든 서비스 ports -> expose로 변경 (외부 포트 노출 없음)
- frontend/backend를 공용 proxy 네트워크에 연결 - npm이 컨테이너 이름(report-frontend:80)으로 라우팅
- DB는 내부 app-network 전용 유지
- 미사용이 된 BACKEND_PORT/FRONTEND_PORT 변수 제거

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:43:52 +09:00
ttipo dbcda9dd6b compose 네트워크 이름을 app-network로 통일
Deploy / deploy (push) Successful in 13s
다른 스택(adform, innertab)과 동일한 명명 규칙 적용

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 17:41:28 +09:00
ttipo 1d21d4b49b 비밀값 하드코딩 기본값 제거
Deploy / deploy (push) Successful in 37s
- docker-compose: DB_PASSWORD, ACCESS_SECRET, REFRESH_SECRET, ADMIN_USER, ADMIN_PASS를 필수(:?)로 변경 - 누락 시 명확한 에러로 실패
- server.js: 시크릿/관리자 계정의 하드코딩 폴백 제거 (JWT 시크릿 누락 시 기동 중단, 관리자 계정 미설정 시 생성 건너뜀)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 16:02:42 +09:00
ttipo c8dbaf167f Revert "frontend를 npm 공용 proxy 네트워크에 연결"
Deploy / deploy (push) Successful in 13s
This reverts commit 0e9e5b0283.
2026-07-19 15:42:10 +09:00
ttipo 0e9e5b0283 frontend를 npm 공용 proxy 네트워크에 연결
Deploy / deploy (push) Successful in 20s
npm(Nginx Proxy Manager)이 proxy 네트워크에서 report-frontend:80 으로 접근할 수 있도록 external 네트워크 추가 (adform/innertab과 동일 패턴). 도메인 접속 시 502 나던 문제 해결

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-19 15:38:48 +09:00
5 changed files with 53 additions and 36 deletions
+3 -5
View File
@@ -6,10 +6,12 @@
# PostgreSQL
DB_PORT=5432
DB_HOST=postgres
DB_HOST=db
DB_USER=
DB_PASSWORD=
DB_NAME=report_db
# DB 데이터 저장 경로 (프로젝트 폴더 기준 상대 경로, 기본값 ./data/postgres)
DB_DATA_DIR=./data/postgres
# Admin Account
ADMIN_USER=
@@ -21,7 +23,3 @@ REFRESH_SECRET=
# Gemini API Key
JEMINI_KEY=
# Ports
BACKEND_PORT=54530
FRONTEND_PORT=55110
+4 -1
View File
@@ -43,7 +43,10 @@ jobs:
- name: Restart containers
run: |
cd "$DEPLOY_DIR"
docker compose up -d
docker compose up -d --remove-orphans
# backend/frontend는 항상 새로 기동: DB 교체 시 스키마 재동기화,
# nginx의 낡은 upstream IP 캐시 방지
docker compose up -d --no-deps --force-recreate backend frontend
- name: Prune dangling images
run: docker image prune -f
+3
View File
@@ -12,6 +12,9 @@ dist/
# Uploads / generated assets
backend/img/
# DB data (bind mount)
data/
# Logs & OS files
*.log
.DS_Store
+17 -6
View File
@@ -20,7 +20,7 @@ const PORT = process.env.PORT || 3000;
const sequelize = new Sequelize(
process.env.DB_NAME || "report_db",
process.env.DB_USER || "postgres",
process.env.DB_PASSWORD || "password",
process.env.DB_PASSWORD,
{
host: process.env.DB_HOST || "localhost",
port: process.env.DB_PORT || 5432,
@@ -86,8 +86,12 @@ const swaggerOptions = {
const swaggerDocs = swaggerJsdoc(swaggerOptions);
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocs));
const ACCESS_SECRET = process.env.ACCESS_SECRET || "access_secret_123";
const REFRESH_SECRET = process.env.REFRESH_SECRET || "refresh_secret_123";
const ACCESS_SECRET = process.env.ACCESS_SECRET;
const REFRESH_SECRET = process.env.REFRESH_SECRET;
if (!ACCESS_SECRET || !REFRESH_SECRET) {
console.error("ACCESS_SECRET / REFRESH_SECRET 환경변수가 필요합니다.");
process.exit(1);
}
// OpenAI 추가
const { OpenAI } = require("openai");
@@ -215,8 +219,12 @@ sequelize
.then(async () => {
console.log("DB Tables Synced...");
// 초기 관리자 계정 생성 (환경 변수 기반)
const adminUser = process.env.ADMIN_USER || "admin";
const adminPass = process.env.ADMIN_PASS || "admin123!";
const adminUser = process.env.ADMIN_USER;
const adminPass = process.env.ADMIN_PASS;
if (!adminUser || !adminPass) {
console.log("ADMIN_USER/ADMIN_PASS 미설정 - 관리자 계정 생성을 건너뜁니다.");
return;
}
const adminExists = await User.findOne({ where: { username: adminUser } });
const hashedPassword = await bcrypt.hash(adminPass, 10);
@@ -240,7 +248,10 @@ sequelize
);
}
})
.catch((err) => console.log("PostgreSQL Connection/Sync Error:", err));
.catch((err) => {
console.error("PostgreSQL Connection/Sync Error:", err);
process.exit(1);
});
// Auth Middleware
const authenticateToken = (req, res, next) => {
+25 -23
View File
@@ -1,18 +1,18 @@
services:
postgres:
db:
image: postgres:16-alpine
container_name: report-db
restart: always
environment:
POSTGRES_DB: ${DB_NAME:-report_db}
POSTGRES_USER: ${DB_USER:-postgres}
POSTGRES_PASSWORD: ${DB_PASSWORD:-daoblock12!!}
ports:
- "5442:5432"
POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD가 .env에 설정되어야 합니다}
expose:
- "5432"
volumes:
- postgres-data:/var/lib/postgresql/data
- ${DB_DATA_DIR:-./data/postgres}:/var/lib/postgresql/data
networks:
- report-network
- app-network
healthcheck:
test: [ "CMD-SHELL", "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-report_db}" ]
interval: 5s
@@ -24,41 +24,43 @@ services:
build: ./backend
container_name: report-backend
restart: always
ports:
- "${BACKEND_PORT:-54530}:3000"
expose:
- "3000"
environment:
- DB_HOST=${DB_HOST:-postgres}
- DB_HOST=${DB_HOST:-db}
- DB_PORT=${DB_PORT:-5432}
- DB_USER=${DB_USER:-postgres}
- DB_PASSWORD=${DB_PASSWORD:-daoblock12!!}
- DB_PASSWORD=${DB_PASSWORD:?DB_PASSWORD가 .env에 설정되어야 합니다}
- DB_NAME=${DB_NAME:-report_db}
- ACCESS_SECRET=${ACCESS_SECRET:-your_jwt_access_secret_123}
- REFRESH_SECRET=${REFRESH_SECRET:-your_jwt_refresh_secret_123}
- ADMIN_USER=${ADMIN_USER:-kyeongmi}
- ADMIN_PASS=${ADMIN_PASS:-kyeongmi}
- ACCESS_SECRET=${ACCESS_SECRET:?ACCESS_SECRET이 .env에 설정되어야 합니다}
- REFRESH_SECRET=${REFRESH_SECRET:?REFRESH_SECRET이 .env에 설정되어야 합니다}
- ADMIN_USER=${ADMIN_USER:?ADMIN_USER가 .env에 설정되어야 합니다}
- ADMIN_PASS=${ADMIN_PASS:?ADMIN_PASS가 .env에 설정되어야 합니다}
- JEMINI_KEY=${JEMINI_KEY}
depends_on:
postgres:
db:
condition: service_healthy
volumes:
- ./backend/img:/app/img
networks:
- report-network
- app-network
- proxy
frontend:
build: ./frontend
container_name: report-frontend
restart: always
ports:
- "${FRONTEND_PORT:-55110}:80"
expose:
- "80"
depends_on:
- backend
networks:
- report-network
- app-network
- proxy
networks:
report-network:
app-network:
driver: bridge
volumes:
postgres-data:
# npm(Nginx Proxy Manager)이 컨테이너 이름으로 라우팅하는 공용 네트워크
proxy:
external: true