Files
tk-factory-services/DEPLOY-GUIDE.md
2026-02-12 15:54:02 +09:00

10 KiB

TK Factory Services - NAS 배포 가이드

최종 업데이트: 2026-02-12

아키텍처 개요

                    Cloudflare Tunnel
                         |
          +--------------+--------------+
          |              |              |
  tkfb.techni..    tkreport.techni..   tkqc.techni..
          |              |              |
    tk-gateway:80   tk-system2-web:80  tk-system3-web:80
     (포털+S1)         (S2 신고)       (S3 부적합)
          |              |              |
    system1-api:3005  system2-api:3005  system3-api:8000
          |              |              |
          +--- MariaDB --+       PostgreSQL
               (공유)

서브도메인 라우팅

서브도메인 Cloudflare Tunnel 대상 역할
tkfb.technicalkorea.net http://tk-gateway:80 통합 포털 + System 1 (공장관리)
tkreport.technicalkorea.net http://tk-system2-web:80 System 2 (신고)
tkqc.technicalkorea.net http://tk-system3-web:80 System 3 (부적합관리)
tkuser.technicalkorea.net http://tk-tkuser-web:80 통합 관리 (사용자/부서/프로젝트/이슈유형)

SSO 인증 방식

  • 로그인: tkfb.technicalkorea.net/login에서 통합 로그인
  • 토큰 저장: 쿠키 (domain=.technicalkorea.net, 7일 만료) + localStorage 이중 저장
  • 시스템 간 이동: 쿠키가 서브도메인 간 자동 공유되므로 재로그인 불필요

Docker 서비스 (13개)

서비스 컨테이너명 포트
MariaDB tk-mariadb 30306:3306
PostgreSQL tk-postgres 30432:5432
Redis tk-redis -
SSO Auth tk-sso-auth 30050:3000
System 1 API tk-system1-api 30005:3005
System 1 Web tk-system1-web 30080:80
System 1 FastAPI tk-system1-fastapi 30008:8000
System 2 API tk-system2-api 30105:3005
System 2 Web tk-system2-web 30180:80
System 3 API tk-system3-api 30200:8000
System 3 Web tk-system3-web 30280:80
phpMyAdmin tk-phpmyadmin 30880:80
Cloudflared tk-cloudflared -
TKUser API tk-tkuser-api 30300:3000
TKUser Web tk-tkuser-web 30380:80
Gateway tk-gateway 30000:80

배포 전 준비 (로컬)

1. .env 파일 생성

cp .env.example .env
vi .env

필수 설정값:

# NAS 기존 TK-FB의 DB 패스워드와 동일하게 설정
MYSQL_ROOT_PASSWORD=<기존 tkfb_db root 패스워드>
MYSQL_PASSWORD=<기존 tkfb_db hyungi_user 패스워드>

# 새로 생성할 SSO 시크릿 (32자 이상 랜덤 문자열)
SSO_JWT_SECRET=<openssl rand -hex 32 로 생성>
SSO_JWT_REFRESH_SECRET=<openssl rand -hex 32 로 생성>

# NAS 기존 TKQC의 DB 패스워드와 동일하게 설정
POSTGRES_PASSWORD=<기존 tkqc-db mproject 패스워드>

# System 3 관리자 (기존 TKQC 관리자)
SYSTEM3_ADMIN_USERNAME=hyungi
SYSTEM3_ADMIN_PASSWORD=<기존 TKQC 관리자 비밀번호>

# Cloudflare Tunnel 토큰
CLOUDFLARE_TUNNEL_TOKEN=<Cloudflare Zero Trust 대시보드에서 확인>

기존 패스워드 확인 방법 (NAS SSH):

# TK-FB MariaDB 패스워드
cat "/volume1/Technicalkorea Document/tkfb-package/.env" | grep MYSQL

# TKQC PostgreSQL 패스워드
cat /volume1/docker/tkqc/tkqc-package/.env | grep POSTGRES

# Cloudflare Tunnel 토큰
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker inspect tkfb_cloudflared | grep TUNNEL_TOKEN

NAS 배포 절차

Step 1: 기존 서비스 백업

# NAS SSH 접속
ssh hyungi@192.168.0.3

# 백업 디렉토리 생성
mkdir -p /volume1/docker/backups/$(date +%Y%m%d)

# MariaDB 백업
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker exec tkfb_db \
  mysqldump -u root -p<ROOT_PASSWORD> --all-databases > \
  /volume1/docker/backups/$(date +%Y%m%d)/mariadb-all.sql

# PostgreSQL 백업
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker exec tkqc-db \
  pg_dumpall -U mproject > \
  /volume1/docker/backups/$(date +%Y%m%d)/postgres-all.sql

# uploads 백업
cp -r "/volume1/Technicalkorea Document/tkfb-package/uploads" \
  /volume1/docker/backups/$(date +%Y%m%d)/tkfb-uploads
cp -r /volume1/docker/tkqc/tkqc-package/uploads \
  /volume1/docker/backups/$(date +%Y%m%d)/tkqc-uploads

Step 2: 프로젝트 NAS 전송

# 로컬 Mac에서 실행
# node_modules 제외하여 전송
rsync -avz --exclude='node_modules' --exclude='.env' --exclude='__pycache__' \
  -e ssh /Users/hyungiahn/Documents/code/tk-factory-services/ \
  hyungi@192.168.0.3:/volume1/docker/tk-factory-services/

# .env 파일 별도 전송
scp -O /Users/hyungiahn/Documents/code/tk-factory-services/.env \
  hyungi@192.168.0.3:/volume1/docker/tk-factory-services/.env

참고: Synology에서 scp-O 옵션 필수 (레거시 프로토콜)

Step 3: 기존 서비스 중지

# NAS SSH
# TK-FB 중지
cd "/volume1/Technicalkorea Document/tkfb-package"
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose down

# TKQC 중지
cd /volume1/docker/tkqc/tkqc-package
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose down

Step 4: 통합 서비스 기동

cd /volume1/docker/tk-factory-services

# Docker 이미지 빌드 + 서비스 기동
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose up --build -d

# 로그 확인
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose logs -f --tail=50

Step 5: DB 마이그레이션

# SSO 유저 테이블은 docker-compose.yml에 의해 자동 실행됨
# (scripts/migrate-users.sql → MariaDB init)

# PostgreSQL 마이그레이션도 자동 실행됨
# (system3-nonconformance/api/migrations/ → PostgreSQL init)

# 헬스체크 확인
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose ps

Step 6: Cloudflare Tunnel 설정

Cloudflare Zero Trust 대시보드 (https://one.dash.cloudflare.com/)에서:

  1. Networks → Tunnels → 기존 터널 선택
  2. Public Hostname 탭에서 3개 서브도메인 설정:
Subdomain Domain Service
tkfb technicalkorea.net http://tk-gateway:80
tkreport technicalkorea.net http://tk-system2-web:80
tkqc technicalkorea.net http://tk-system3-web:80

기존 tkfb.technicalkorea.nettkqc.technicalkorea.net은 대상 서비스만 변경

Step 7: 테스트

# 1. 헬스체크
curl -s http://localhost:30005/api/health  # System 1 API
curl -s http://localhost:30105/api/health  # System 2 API
curl -s http://localhost:30200/api/health  # System 3 API
curl -s http://localhost:30050/api/health  # SSO Auth

# 2. 웹 접속 테스트 (브라우저)
# - https://tkfb.technicalkorea.net/ → 포털 표시
# - https://tkfb.technicalkorea.net/login → 로그인 페이지
# - 로그인 후 → 대시보드 이동
# - https://tkreport.technicalkorea.net/ → System 2 (재로그인 없이)
# - https://tkqc.technicalkorea.net/ → System 3 (재로그인 없이)

# 3. SSO 쿠키 확인 (브라우저 개발자 도구)
# - Application → Cookies에서 sso_token, sso_user 확인
# - domain이 .technicalkorea.net인지 확인

롤백 방법

문제 발생 시 기존 서비스로 복원:

# 통합 서비스 중지
cd /volume1/docker/tk-factory-services
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose down

# TK-FB 복원
cd "/volume1/Technicalkorea Document/tkfb-package"
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose up -d

# TKQC 복원
cd /volume1/docker/tkqc/tkqc-package
echo 'fukdon-riwbaq-fiQfy2' | sudo -S /usr/local/bin/docker compose up -d

시스템 간 연동

tkreport → tkqc 부적합 자동 전달

부적합 유형으로 신고 시 system2-api가 system3-api로 자동 전달:

  • 인증: SSO 토큰 그대로 전달 (원래 신고자 유지)
  • fallback 인증: api_service 계정 (system3 users 테이블에 등록 필요)
  • 사진: system2에 저장된 파일을 base64로 읽어서 system3에 전달
  • 프로젝트: 같은 MariaDB projects 테이블 공유, project_id 그대로 전달
  • 환경변수: M_PROJECT_API_URL=http://system3-api:8000

system2-web nginx 프록시 라우팅

tkreport의 nginx는 여러 백엔드로 프록시:

경로 대상 용도
/api/workplaces/ system1-api:3005 공장/작업장
/api/projects/ system1-api:3005 프로젝트 목록
/api/tbm/ system1-api:3005 TBM 세션
/api/workplace-visits/ system1-api:3005 출입관리
/api/ (catch-all) system2-api:3005 신고(work-issues)

신고 페이지 (tkreport) 흐름

모바일 최적화 5단계 위자드:

  1. 유형 — 부적합 / 시설설비 / 안전
  2. 위치 — 지도에서 작업장 터치 선택
  3. 프로젝트 — TBM등록 / 활성프로젝트 / 모름 (아코디언)
  4. 항목 — 카테고리 → 세부항목 또는 직접입력
  5. 사진 — 최대 5장 (클라이언트 1280px 리사이징), 추가설명

트러블슈팅

증상 원인 해결
403 Forbidden (nginx) Docker 내부 IP 차단 nginx.conf에 allow 172.16.0.0/12 추가
SSO 로그인 후 다른 시스템에서 미인증 쿠키 domain 설정 오류 브라우저 쿠키에서 domain이 .technicalkorea.net인지 확인
DB 연결 실패 패스워드 불일치 .env의 DB 패스워드가 기존과 동일한지 확인
Cloudflare 502 컨테이너 미기동 docker compose ps로 상태 확인, docker compose logs <서비스>
SCP 실패 Synology subsystem scp -O 옵션 사용
sudo 파이프 실패 Synology 제한 echo 'password' | sudo -S 패턴 사용
신고 사진 업로드 느림/실패 nginx body size 제한 client_max_body_size 50m; 확인
tkqc 부적합 연동 실패 api_service 계정 미등록 system3 DB에 api_service 사용자 생성
신고 사진 컨테이너 재빌드 후 유실 uploads 경로 불일치 imageUploadService 경로가 Docker 볼륨과 일치하는지 확인