diff --git a/.env.development b/.env.development index 4e91dc5..b2cfcf8 100644 --- a/.env.development +++ b/.env.development @@ -9,47 +9,47 @@ TZ=Asia/Seoul NEXT_PUBLIC_API_URL=http://localhost:3001 NEXT_PUBLIC_MQTT_URL=ws://localhost:1883 NEXTAUTH_URL=http://localhost:3000 -NEXTAUTH_SECRET=your-development-secret +NEXTAUTH_SECRET=wacefems_secret_work_in_progress_PPw09!keep # Backend API API_PORT=3001 API_PREFIX=/api/v1 CORS_ORIGIN=http://localhost:3000 -JWT_SECRET=your-jwt-secret-dev +JWT_SECRET=wacefems_secret_work_in_progress_PPw09!keep JWT_EXPIRES_IN=1d # Database POSTGRES_HOST=postgres POSTGRES_PORT=5432 -POSTGRES_DB=fems_dev -POSTGRES_USER=fems_user -POSTGRES_PASSWORD=fems_password +POSTGRES_DB=wacefems_database +POSTGRES_USER=wacefems_database_user +POSTGRES_PASSWORD=wacefems_pg_password_PPw09!keep # TimescaleDB TIMESCALEDB_HOST=timescaledb TIMESCALEDB_PORT=5432 -TIMESCALEDB_DB=fems_timeseries_dev -TIMESCALEDB_USER=fems_tsdb_user -TIMESCALEDB_PASSWORD=fems_tsdb_password +TIMESCALEDB_DB=wacefems_timeseries_database +TIMESCALEDB_USER=wacefems_tsdb_user +TIMESCALEDB_PASSWORD=wacefems_tsdb_password_PPw09!keep # Redis REDIS_HOST=redis REDIS_PORT=6379 -REDIS_PASSWORD=redis_password_dev +REDIS_PASSWORD=wacefems_redis_password_PPw09!keep # MQTT Broker MQTT_PORT=1883 MQTT_WS_PORT=9001 MQTT_USERNAME=mqtt_user -MQTT_PASSWORD=mqtt_password_dev +MQTT_PASSWORD=mqtt_password_PPw09!keep # Kafka KAFKA_BROKER=kafka:9092 -KAFKA_TOPIC_PREFIX=fems_dev +KAFKA_TOPIC_PREFIX=wacefems_data # Node-RED NODERED_PORT=1880 -NODERED_CREDENTIAL_SECRET=nodered_secret_dev +NODERED_CREDENTIAL_SECRET=wacefems_nodered_secret_PPw09!keep # Monitoring PROMETHEUS_PORT=9090 diff --git a/.env.production b/.env.production index 3610fa8..1979698 100644 --- a/.env.production +++ b/.env.production @@ -18,31 +18,31 @@ GRAFANA_SUBDOMAIN=grafana.${DOMAIN} KIBANA_SUBDOMAIN=kibana.${DOMAIN} # Frontend -NEXT_PUBLIC_API_URL=https://api.fems.com -NEXT_PUBLIC_MQTT_URL=wss://mqtt.fems.com -NEXTAUTH_URL=https://fems.com -NEXTAUTH_SECRET=your-production-secret +NEXT_PUBLIC_API_URL=https://api.${DOMAIN} +NEXT_PUBLIC_MQTT_URL=wss://mqtt.${DOMAIN} +NEXTAUTH_URL=https://${DOMAIN} +NEXTAUTH_SECRET=wacefems_secret_work_in_progress_PPw09!keep # Backend API API_PORT=3001 API_PREFIX=/api/v1 -CORS_ORIGIN=https://fems.com -JWT_SECRET=your-jwt-secret-prod +CORS_ORIGIN=https://${DOMAIN} +JWT_SECRET=wacefems_secret_work_in_progress_professional! JWT_EXPIRES_IN=1d # Database POSTGRES_HOST=postgres POSTGRES_PORT=5432 -POSTGRES_DB=fems_prod -POSTGRES_USER=fems_user -POSTGRES_PASSWORD=your-secure-password +POSTGRES_DB=wacefems_database +POSTGRES_USER=wacefems_database_user +POSTGRES_PASSWORD=wacefems_pg_password_PPw09!keep # TimescaleDB TIMESCALEDB_HOST=timescaledb TIMESCALEDB_PORT=5432 -TIMESCALEDB_DB=fems_timeseries_prod -TIMESCALEDB_USER=fems_tsdb_user -TIMESCALEDB_PASSWORD=your-secure-tsdb-password +TIMESCALEDB_DB=wacefems_timeseries_database +TIMESCALEDB_USER=wacefems_tsdb_user +TIMESCALEDB_PASSWORD=wacefems_tsdb_password_PPw09!keep # Redis REDIS_HOST=redis @@ -53,15 +53,15 @@ REDIS_PASSWORD=your-secure-redis-password MQTT_PORT=1883 MQTT_WS_PORT=9001 MQTT_USERNAME=mqtt_user -MQTT_PASSWORD=your-secure-mqtt-password +MQTT_PASSWORD=mqtt_password_PPw09!keep # Kafka KAFKA_BROKER=kafka:9092 -KAFKA_TOPIC_PREFIX=fems_prod +KAFKA_TOPIC_PREFIX=wacefems_data # Node-RED NODERED_PORT=1880 -NODERED_CREDENTIAL_SECRET=your-secure-nodered-secret +NODERED_CREDENTIAL_SECRET=wacefems_nodered_secret_PPw09!keep # Monitoring PROMETHEUS_PORT=9090 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..54f395d --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.env* +!.env.example +backups/ +logs/ +node_modules/ +.DS_Store diff --git a/README.md b/README.md index 00692f3..f20f729 100644 --- a/README.md +++ b/README.md @@ -117,7 +117,11 @@ wacefems/ │ ├── shared/ # 공통 코드 ├── .env # 환경 변수 -└── docker-compose.yml # 도커 구성 +├── docker-compose.base.yml # 기본 설정 +├── docker-compose.dev.yml # 개발 환경 설정 +├── docker-compose.full.yml # 전체 시스템 설정 +└── docker-compose.prod.yml # 개발 환경 설정 + ``` ### 2.2 기술 스택 diff --git a/backup.sh b/backup.sh new file mode 100755 index 0000000..0256b28 --- /dev/null +++ b/backup.sh @@ -0,0 +1,23 @@ +# backup.sh +#!/bin/bash + +# 백업 디렉토리 생성 +BACKUP_DIR="./backups/$(date +%Y%m%d_%H%M%S)" +mkdir -p "$BACKUP_DIR" + +# PostgreSQL 백업 +echo "Backing up PostgreSQL..." +docker-compose exec -T postgres pg_dump -U ${POSTGRES_USER} ${POSTGRES_DB} > "$BACKUP_DIR/postgres_backup.sql" + +# Redis 백업 +echo "Backing up Redis..." +docker-compose exec -T redis redis-cli -a ${REDIS_PASSWORD} SAVE +docker cp $(docker-compose ps -q redis):/data/dump.rdb "$BACKUP_DIR/redis_backup.rdb" + +# TimescaleDB 백업 (full stack 환경인 경우) +if [ -f "docker-compose.full.yml" ]; then + echo "Backing up TimescaleDB..." + docker-compose exec -T timescaledb pg_dump -U ${TIMESCALEDB_USER} ${TIMESCALEDB_DB} > "$BACKUP_DIR/timescaledb_backup.sql" +fi + +echo "Backup completed at $BACKUP_DIR" \ No newline at end of file diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 13b4a62..5e84a9e 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -6,7 +6,6 @@ services: fems-admin: ports: - "3000:3000" - command: npm run dev environment: - NEXT_WEBPACK_USEPOLLING=1 - WATCHPACK_POLLING=true @@ -17,7 +16,6 @@ services: fems-app: ports: - "3002:3000" - command: npm run dev environment: - NEXT_WEBPACK_USEPOLLING=1 - WATCHPACK_POLLING=true @@ -25,7 +23,6 @@ services: fems-api: ports: - "3001:3001" - command: npm run dev postgres: ports: diff --git a/fems-admin/Dockerfile b/fems-admin/Dockerfile new file mode 100644 index 0000000..6d4ef8f --- /dev/null +++ b/fems-admin/Dockerfile @@ -0,0 +1,28 @@ +# fems-admin/Dockerfile +# Build stage +FROM node:18-alpine AS builder +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile +COPY . . +RUN yarn build + +# Development stage +FROM node:18-alpine AS development +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile +COPY . . +ENV NODE_ENV=development +CMD ["yarn", "dev"] + +# Production stage +FROM node:18-alpine AS production +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile --production +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/public ./public +COPY --from=builder /app/package.json ./package.json +ENV NODE_ENV=production +CMD ["yarn", "start"] \ No newline at end of file diff --git a/fems-api/Dockerfile b/fems-api/Dockerfile new file mode 100644 index 0000000..59804b0 --- /dev/null +++ b/fems-api/Dockerfile @@ -0,0 +1,27 @@ +# fems-api/Dockerfile +# Build stage +FROM node:18-alpine AS builder +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile +COPY . . +RUN yarn build + +# Development stage +FROM node:18-alpine AS development +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile +COPY . . +ENV NODE_ENV=development +CMD ["yarn", "dev"] + +# Production stage +FROM node:18-alpine AS production +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile --production +COPY --from=builder /app/dist ./dist +COPY --from=builder /app/package.json ./package.json +ENV NODE_ENV=production +CMD ["yarn", "start"] \ No newline at end of file diff --git a/fems-app/Dockerfile b/fems-app/Dockerfile new file mode 100644 index 0000000..90753ee --- /dev/null +++ b/fems-app/Dockerfile @@ -0,0 +1,28 @@ +# fems-app/Dockerfile +# Build stage +FROM node:18-alpine AS builder +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile +COPY . . +RUN yarn build + +# Development stage +FROM node:18-alpine AS development +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile +COPY . . +ENV NODE_ENV=development +CMD ["yarn", "dev"] + +# Production stage +FROM node:18-alpine AS production +WORKDIR /app +COPY package.json yarn.lock ./ +RUN yarn install --frozen-lockfile --production +COPY --from=builder /app/.next ./.next +COPY --from=builder /app/public ./public +COPY --from=builder /app/package.json ./package.json +ENV NODE_ENV=production +CMD ["yarn", "start"] \ No newline at end of file diff --git a/monitor.sh b/monitor.sh new file mode 100755 index 0000000..0d325af --- /dev/null +++ b/monitor.sh @@ -0,0 +1,21 @@ +# monitor.sh +#!/bin/bash + +# 시스템 상태 모니터링 +echo "=== FEMS System Status ===" +echo + +echo "=== Containers Status ===" +if [ "$NODE_ENV" = "production" ]; then + if [ -f "docker-compose.full.yml" ]; then + docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml -f docker-compose.full.yml ps + else + docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml ps + fi +else + docker-compose -f docker-compose.base.yml -f docker-compose.dev.yml ps +fi + +echo +echo "=== Container Resources ===" +docker stats --no-stream \ No newline at end of file diff --git a/restart.sh b/restart.sh index 6261b7e..db9507b 100755 --- a/restart.sh +++ b/restart.sh @@ -8,4 +8,20 @@ if [ -z "$SERVICE_NAME" ]; then echo "Usage: ./restart.sh [service_name]" echo "Available services:" if [ "$NODE_ENV" = "production" ]; then - docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml - \ No newline at end of file + docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml -f docker-compose.full.yml ps --services + else + docker-compose -f docker-compose.base.yml -f docker-compose.dev.yml ps --services + fi + exit 1 +fi + +# 환경에 따라 서비스 재시작 +if [ "$NODE_ENV" = "production" ]; then + if [ -f "docker-compose.full.yml" ]; then + docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml -f docker-compose.full.yml restart "$SERVICE_NAME" + else + docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml restart "$SERVICE_NAME" + fi +else + docker-compose -f docker-compose.base.yml -f docker-compose.dev.yml restart "$SERVICE_NAME" +fi \ No newline at end of file diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..5bfd642 --- /dev/null +++ b/setup.sh @@ -0,0 +1,31 @@ +# setup.sh +#!/bin/bash + +# 필요한 디렉토리 생성 +mkdir -p backups logs config/{prometheus,grafana,mosquitto} + +# 스크립트 실행 권한 부여 +chmod +x start-dev.sh start-prod.sh start-full.sh stop.sh logs.sh restart.sh backup.sh monitor.sh + +# .env 파일 생성 +# if [ ! -f .env.development ]; then +# cp .env.example .env.development +# echo "Created .env.development - please update with your settings" +# fi + +# if [ ! -f .env.production ]; then +# cp .env.example .env.production +# echo "Created .env.production - please update with your settings" +# fi + +# Git ignore 설정 +if [ ! -f .gitignore ]; then + echo ".env* +!.env.example +backups/ +logs/ +node_modules/ +.DS_Store" > .gitignore +fi + +echo "Setup completed!" \ No newline at end of file diff --git a/start-dev.sh b/start-dev.sh index 2f41c17..e087a67 100755 --- a/start-dev.sh +++ b/start-dev.sh @@ -9,6 +9,11 @@ export NODE_ENV=development # 이전 컨테이너 정리 docker-compose -f docker-compose.base.yml -f docker-compose.dev.yml down +# 컨테이너 정리 +docker system prune -af +docker image prune -af +docker volume prune -f + # 컨테이너 시작 docker-compose -f docker-compose.base.yml -f docker-compose.dev.yml up -d diff --git a/start-full.sh b/start-full.sh index 24487e4..f26fdc8 100755 --- a/start-full.sh +++ b/start-full.sh @@ -9,6 +9,11 @@ export NODE_ENV=production # 이전 컨테이너 정리 docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml -f docker-compose.full.yml down +# 컨테이너 정리 +docker system prune -af +docker image prune -af +docker volume prune -f + # 컨테이너 시작 docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml -f docker-compose.full.yml up -d diff --git a/start-prod.sh b/start-prod.sh index 746b227..5c05799 100755 --- a/start-prod.sh +++ b/start-prod.sh @@ -9,6 +9,11 @@ export NODE_ENV=production # 이전 컨테이너 정리 docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml down +# 컨테이너 정리 +docker system prune -af +docker image prune -af +docker volume prune -f + # 컨테이너 시작 docker-compose -f docker-compose.base.yml -f docker-compose.prod.yml up -d