# 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 파일 생성 ```bash 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= SSO_JWT_REFRESH_SECRET= # NAS 기존 TKQC의 DB 패스워드와 동일하게 설정 POSTGRES_PASSWORD=<기존 tkqc-db mproject 패스워드> # System 3 관리자 (기존 TKQC 관리자) SYSTEM3_ADMIN_USERNAME=hyungi SYSTEM3_ADMIN_PASSWORD=<기존 TKQC 관리자 비밀번호> # Cloudflare Tunnel 토큰 CLOUDFLARE_TUNNEL_TOKEN= ``` 기존 패스워드 확인 방법 (NAS SSH): ```bash # 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: 기존 서비스 백업 ```bash # 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 --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 전송 ```bash # 로컬 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: 기존 서비스 중지 ```bash # 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: 통합 서비스 기동 ```bash 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 마이그레이션 ```bash # 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.net`과 `tkqc.technicalkorea.net`은 대상 서비스만 변경 ### Step 7: 테스트 ```bash # 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인지 확인 ``` --- ## 롤백 방법 문제 발생 시 기존 서비스로 복원: ```bash # 통합 서비스 중지 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 볼륨과 일치하는지 확인 |