Compare commits
4 Commits
dd5031ae3a
...
feat/train
| Author | SHA1 | Date | |
|---|---|---|---|
| 265813e6f7 | |||
| 8190a6e9c8 | |||
| e9f8bb37fa | |||
| f3c822587f |
6
.gitignore
vendored
6
.gitignore
vendored
@@ -72,9 +72,3 @@ docker-compose.override.yml
|
|||||||
*.swo
|
*.swo
|
||||||
*~
|
*~
|
||||||
!/CLAUDE.md
|
!/CLAUDE.md
|
||||||
|
|
||||||
### SSL Certificates ###
|
|
||||||
nginx/ssl/
|
|
||||||
*.crt
|
|
||||||
*.key
|
|
||||||
*.pem
|
|
||||||
|
|||||||
415
DEPLOY.md
415
DEPLOY.md
@@ -1,415 +0,0 @@
|
|||||||
# KAMCO Training API 배포 가이드 (RedHat 9.6)
|
|
||||||
|
|
||||||
## 빠른 배포 (Quick Start)
|
|
||||||
|
|
||||||
이 문서는 RedHat 9.6 환경에서 HTTPS로 KAMCO Training API를 배포하는 방법을 설명합니다.
|
|
||||||
|
|
||||||
**접속 URL**:
|
|
||||||
- `https://api.train-kamco.com`
|
|
||||||
- `https://train-kamco.com`
|
|
||||||
|
|
||||||
## 사전 요구사항
|
|
||||||
|
|
||||||
- [x] Docker & Docker Compose 설치
|
|
||||||
- [x] Git 설치
|
|
||||||
- [x] sudo 권한
|
|
||||||
- [x] 포트 80, 443 사용 가능
|
|
||||||
|
|
||||||
## 1단계: /etc/hosts 설정
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# root 권한으로 도메인 추가
|
|
||||||
echo "127.0.0.1 api.train-kamco.com train-kamco.com" | sudo tee -a /etc/hosts
|
|
||||||
|
|
||||||
# 확인
|
|
||||||
cat /etc/hosts | grep train-kamco
|
|
||||||
```
|
|
||||||
|
|
||||||
**예상 결과**:
|
|
||||||
```
|
|
||||||
127.0.0.1 api.train-kamco.com train-kamco.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## 2단계: 방화벽 설정 (필요시)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 방화벽 상태 확인
|
|
||||||
sudo firewall-cmd --state
|
|
||||||
|
|
||||||
# HTTP/HTTPS 포트 개방
|
|
||||||
sudo firewall-cmd --permanent --add-port=80/tcp
|
|
||||||
sudo firewall-cmd --permanent --add-port=443/tcp
|
|
||||||
|
|
||||||
# 방화벽 재로드
|
|
||||||
sudo firewall-cmd --reload
|
|
||||||
|
|
||||||
# 확인
|
|
||||||
sudo firewall-cmd --list-ports
|
|
||||||
```
|
|
||||||
|
|
||||||
**예상 결과**: `80/tcp 443/tcp`
|
|
||||||
|
|
||||||
## 3단계: 프로젝트 디렉토리로 이동
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /path/to/kamco-train-api
|
|
||||||
|
|
||||||
# 현재 위치 확인
|
|
||||||
pwd
|
|
||||||
# 예상: /home/username/kamco-train-api
|
|
||||||
```
|
|
||||||
|
|
||||||
## 4단계: 파일 구조 확인
|
|
||||||
|
|
||||||
배포 전 필수 파일이 모두 있는지 확인하세요:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# SSL 인증서 확인
|
|
||||||
ls -la nginx/ssl/
|
|
||||||
|
|
||||||
# 예상 결과:
|
|
||||||
# train-kamco.com.crt (인증서)
|
|
||||||
# train-kamco.com.key (개인 키)
|
|
||||||
# openssl.cnf (설정 파일)
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Docker Compose 파일 확인
|
|
||||||
ls -la docker-compose-prod.yml nginx/nginx.conf
|
|
||||||
|
|
||||||
# 예상: 두 파일 모두 존재
|
|
||||||
```
|
|
||||||
|
|
||||||
## 5단계: Docker 네트워크 생성 (최초 1회)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# kamco-cds 네트워크가 있는지 확인
|
|
||||||
docker network ls | grep kamco-cds
|
|
||||||
|
|
||||||
# 없으면 생성
|
|
||||||
docker network create kamco-cds
|
|
||||||
```
|
|
||||||
|
|
||||||
## 6단계: Docker Compose 배포
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 기존 컨테이너 중지 (있는 경우)
|
|
||||||
docker-compose -f docker-compose-prod.yml down
|
|
||||||
|
|
||||||
# 새로운 이미지 빌드 및 실행
|
|
||||||
docker-compose -f docker-compose-prod.yml up -d --build
|
|
||||||
|
|
||||||
# 컨테이너 상태 확인
|
|
||||||
docker-compose -f docker-compose-prod.yml ps
|
|
||||||
```
|
|
||||||
|
|
||||||
**예상 결과**:
|
|
||||||
```
|
|
||||||
NAME STATUS
|
|
||||||
kamco-cd-nginx Up (healthy)
|
|
||||||
kamco-cd-training-api Up (healthy)
|
|
||||||
```
|
|
||||||
|
|
||||||
## 7단계: 배포 확인
|
|
||||||
|
|
||||||
### 컨테이너 로그 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Nginx 로그
|
|
||||||
docker logs kamco-cd-nginx --tail 50
|
|
||||||
|
|
||||||
# API 로그
|
|
||||||
docker logs kamco-cd-training-api --tail 50
|
|
||||||
|
|
||||||
# 실시간 로그 (Ctrl+C로 종료)
|
|
||||||
docker-compose -f docker-compose-prod.yml logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTTP → HTTPS 리다이렉트 테스트
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# HTTP 접속 시 HTTPS로 리다이렉트되는지 확인
|
|
||||||
curl -I http://api.train-kamco.com
|
|
||||||
curl -I http://train-kamco.com
|
|
||||||
|
|
||||||
# 예상 결과: 301 Moved Permanently
|
|
||||||
# Location: https://api.train-kamco.com/ 또는 https://train-kamco.com/
|
|
||||||
```
|
|
||||||
|
|
||||||
### HTTPS 헬스체크
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# -k 플래그: 사설 인증서 경고 무시
|
|
||||||
curl -k https://api.train-kamco.com/monitor/health
|
|
||||||
curl -k https://train-kamco.com/monitor/health
|
|
||||||
|
|
||||||
# 예상 결과: {"status":"UP","components":{...}}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 브라우저 테스트
|
|
||||||
|
|
||||||
브라우저에서 다음 URL에 접속:
|
|
||||||
|
|
||||||
- `https://api.train-kamco.com/monitor/health`
|
|
||||||
- `https://train-kamco.com/monitor/health`
|
|
||||||
|
|
||||||
**사설 인증서 경고**:
|
|
||||||
- "안전하지 않음" 경고가 표시되면 **"고급"** → **"계속 진행"** 클릭
|
|
||||||
|
|
||||||
## 8단계: SSL 인증서 확인 (선택사항)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 인증서 정보 확인
|
|
||||||
openssl x509 -in nginx/ssl/train-kamco.com.crt -text -noout | head -30
|
|
||||||
|
|
||||||
# 유효 기간 확인 (100년)
|
|
||||||
openssl x509 -in nginx/ssl/train-kamco.com.crt -noout -dates
|
|
||||||
|
|
||||||
# SAN (멀티 도메인) 확인
|
|
||||||
openssl x509 -in nginx/ssl/train-kamco.com.crt -text -noout | grep -A1 "Subject Alternative Name"
|
|
||||||
|
|
||||||
# 예상 결과:
|
|
||||||
# X509v3 Subject Alternative Name:
|
|
||||||
# DNS:api.train-kamco.com, DNS:train-kamco.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## 트러블슈팅
|
|
||||||
|
|
||||||
### 문제 1: "Connection refused"
|
|
||||||
|
|
||||||
**원인**: 컨테이너가 실행되지 않음
|
|
||||||
|
|
||||||
**해결**:
|
|
||||||
```bash
|
|
||||||
# 컨테이너 상태 확인
|
|
||||||
docker ps -a | grep kamco-cd
|
|
||||||
|
|
||||||
# 컨테이너 재시작
|
|
||||||
docker-compose -f docker-compose-prod.yml restart
|
|
||||||
|
|
||||||
# 로그 확인
|
|
||||||
docker logs kamco-cd-nginx
|
|
||||||
docker logs kamco-cd-training-api
|
|
||||||
```
|
|
||||||
|
|
||||||
### 문제 2: "502 Bad Gateway"
|
|
||||||
|
|
||||||
**원인**: Nginx는 실행 중이지만 API 컨테이너가 준비되지 않음
|
|
||||||
|
|
||||||
**해결**:
|
|
||||||
```bash
|
|
||||||
# API 컨테이너 상태 확인
|
|
||||||
docker logs kamco-cd-training-api
|
|
||||||
|
|
||||||
# API 헬스체크 (컨테이너 내부에서)
|
|
||||||
docker exec kamco-cd-nginx wget -qO- http://kamco-changedetection-api:8080/monitor/health
|
|
||||||
|
|
||||||
# API 컨테이너 재시작
|
|
||||||
docker-compose -f docker-compose-prod.yml restart kamco-changedetection-api
|
|
||||||
```
|
|
||||||
|
|
||||||
### 문제 3: "Name or service not known"
|
|
||||||
|
|
||||||
**원인**: /etc/hosts에 도메인이 설정되지 않음
|
|
||||||
|
|
||||||
**해결**:
|
|
||||||
```bash
|
|
||||||
# /etc/hosts 확인
|
|
||||||
cat /etc/hosts | grep train-kamco
|
|
||||||
|
|
||||||
# 없으면 추가
|
|
||||||
echo "127.0.0.1 api.train-kamco.com train-kamco.com" | sudo tee -a /etc/hosts
|
|
||||||
```
|
|
||||||
|
|
||||||
### 문제 4: 포트 80 또는 443이 이미 사용 중
|
|
||||||
|
|
||||||
**원인**: 다른 프로세스가 포트를 사용 중
|
|
||||||
|
|
||||||
**해결**:
|
|
||||||
```bash
|
|
||||||
# 포트 사용 확인
|
|
||||||
sudo lsof -i :80
|
|
||||||
sudo lsof -i :443
|
|
||||||
|
|
||||||
# 사용 중인 프로세스 종료 (예: httpd, nginx)
|
|
||||||
sudo systemctl stop httpd
|
|
||||||
sudo systemctl stop nginx
|
|
||||||
|
|
||||||
# Docker Compose 재시작
|
|
||||||
docker-compose -f docker-compose-prod.yml restart
|
|
||||||
```
|
|
||||||
|
|
||||||
### 문제 5: SELinux 권한 오류
|
|
||||||
|
|
||||||
**원인**: SELinux가 Docker 볼륨 마운트를 차단
|
|
||||||
|
|
||||||
**해결**:
|
|
||||||
```bash
|
|
||||||
# SELinux 상태 확인
|
|
||||||
getenforce
|
|
||||||
|
|
||||||
# Permissive 모드로 임시 변경 (재부팅 시 초기화됨)
|
|
||||||
sudo setenforce 0
|
|
||||||
|
|
||||||
# 영구 변경 (권장하지 않음)
|
|
||||||
sudo vi /etc/selinux/config
|
|
||||||
# SELINUX=permissive 또는 SELINUX=disabled로 변경
|
|
||||||
```
|
|
||||||
|
|
||||||
## 컨테이너 관리 명령어
|
|
||||||
|
|
||||||
### 시작/중지/재시작
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 시작
|
|
||||||
docker-compose -f docker-compose-prod.yml up -d
|
|
||||||
|
|
||||||
# 중지
|
|
||||||
docker-compose -f docker-compose-prod.yml down
|
|
||||||
|
|
||||||
# 재시작
|
|
||||||
docker-compose -f docker-compose-prod.yml restart
|
|
||||||
|
|
||||||
# 특정 서비스만 재시작
|
|
||||||
docker-compose -f docker-compose-prod.yml restart nginx
|
|
||||||
docker-compose -f docker-compose-prod.yml restart kamco-changedetection-api
|
|
||||||
```
|
|
||||||
|
|
||||||
### 로그 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 전체 로그
|
|
||||||
docker-compose -f docker-compose-prod.yml logs
|
|
||||||
|
|
||||||
# 특정 서비스 로그
|
|
||||||
docker-compose -f docker-compose-prod.yml logs nginx
|
|
||||||
docker-compose -f docker-compose-prod.yml logs kamco-changedetection-api
|
|
||||||
|
|
||||||
# 실시간 로그
|
|
||||||
docker-compose -f docker-compose-prod.yml logs -f
|
|
||||||
|
|
||||||
# 마지막 N줄만 보기
|
|
||||||
docker logs kamco-cd-nginx --tail 100
|
|
||||||
```
|
|
||||||
|
|
||||||
### 컨테이너 상태 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 실행 중인 컨테이너
|
|
||||||
docker-compose -f docker-compose-prod.yml ps
|
|
||||||
|
|
||||||
# 상세 정보
|
|
||||||
docker inspect kamco-cd-nginx
|
|
||||||
docker inspect kamco-cd-training-api
|
|
||||||
|
|
||||||
# 리소스 사용량
|
|
||||||
docker stats kamco-cd-nginx kamco-cd-training-api
|
|
||||||
```
|
|
||||||
|
|
||||||
### 컨테이너 내부 접속
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Nginx 컨테이너 내부 접속
|
|
||||||
docker exec -it kamco-cd-nginx sh
|
|
||||||
|
|
||||||
# API 컨테이너 내부 접속
|
|
||||||
docker exec -it kamco-cd-training-api sh
|
|
||||||
|
|
||||||
# 내부에서 빠져나오기
|
|
||||||
exit
|
|
||||||
```
|
|
||||||
|
|
||||||
## 업데이트 및 재배포
|
|
||||||
|
|
||||||
### 코드 업데이트 후 재배포
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Git pull (코드 업데이트)
|
|
||||||
git pull origin develop
|
|
||||||
|
|
||||||
# 2. JAR 파일 빌드 (Jenkins에서 수행하는 경우 생략)
|
|
||||||
./gradlew clean build -x test
|
|
||||||
|
|
||||||
# 3. 컨테이너 재빌드 및 재시작
|
|
||||||
docker-compose -f docker-compose-prod.yml down
|
|
||||||
docker-compose -f docker-compose-prod.yml up -d --build
|
|
||||||
|
|
||||||
# 4. 로그 확인
|
|
||||||
docker-compose -f docker-compose-prod.yml logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
### 설정 파일만 변경한 경우
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# nginx.conf 또는 docker-compose-prod.yml 변경 시
|
|
||||||
docker-compose -f docker-compose-prod.yml down
|
|
||||||
docker-compose -f docker-compose-prod.yml up -d
|
|
||||||
|
|
||||||
# 또는
|
|
||||||
docker-compose -f docker-compose-prod.yml restart nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
## 모니터링
|
|
||||||
|
|
||||||
### 헬스체크 엔드포인트
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# API 헬스체크
|
|
||||||
curl -k https://api.train-kamco.com/monitor/health
|
|
||||||
|
|
||||||
# 예상 결과:
|
|
||||||
# {
|
|
||||||
# "status": "UP",
|
|
||||||
# "components": {
|
|
||||||
# "db": {"status": "UP"},
|
|
||||||
# "diskSpace": {"status": "UP"}
|
|
||||||
# }
|
|
||||||
# }
|
|
||||||
```
|
|
||||||
|
|
||||||
### 시스템 리소스
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 디스크 사용량
|
|
||||||
df -h
|
|
||||||
|
|
||||||
# 메모리 사용량
|
|
||||||
free -h
|
|
||||||
|
|
||||||
# Docker 이미지 및 컨테이너 용량
|
|
||||||
docker system df
|
|
||||||
```
|
|
||||||
|
|
||||||
## 보안 권장 사항
|
|
||||||
|
|
||||||
1. **사설 인증서**: 현재 사설 인증서를 사용 중입니다. 프로덕션 환경에서는 **Let's Encrypt** 또는 **GlobalSign** 같은 공인 인증서 사용을 권장합니다.
|
|
||||||
|
|
||||||
2. **방화벽**: 필요한 포트(80, 443)만 개방하고, 불필요한 포트는 차단하세요.
|
|
||||||
|
|
||||||
3. **정기 업데이트**: Docker 이미지와 시스템 패키지를 정기적으로 업데이트하세요.
|
|
||||||
|
|
||||||
4. **로그 모니터링**: 정기적으로 로그를 확인하여 비정상적인 활동을 감지하세요.
|
|
||||||
|
|
||||||
5. **백업**: SSL 인증서 키 파일(`train-kamco.com.key`)과 데이터베이스를 정기적으로 백업하세요.
|
|
||||||
|
|
||||||
## 참고 문서
|
|
||||||
|
|
||||||
- **SSL 인증서 설정**: [nginx/SSL_SETUP.md](nginx/SSL_SETUP.md)
|
|
||||||
- **프로젝트 개요**: [README.md](README.md)
|
|
||||||
- **CLAUDE.md**: [CLAUDE.md](CLAUDE.md)
|
|
||||||
|
|
||||||
## 지원
|
|
||||||
|
|
||||||
문제가 발생하면 다음을 확인하세요:
|
|
||||||
1. 컨테이너 로그: `docker-compose -f docker-compose-prod.yml logs`
|
|
||||||
2. 컨테이너 상태: `docker-compose -f docker-compose-prod.yml ps`
|
|
||||||
3. /etc/hosts 설정: `cat /etc/hosts | grep train-kamco`
|
|
||||||
4. 방화벽 상태: `sudo firewall-cmd --list-ports`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**배포 완료!** 🎉
|
|
||||||
|
|
||||||
접속 URL:
|
|
||||||
- `https://api.train-kamco.com`
|
|
||||||
- `https://train-kamco.com`
|
|
||||||
20
Dockerfile
20
Dockerfile
@@ -1,20 +0,0 @@
|
|||||||
# Stage 1: Build stage (gradle build는 Jenkins에서 이미 수행)
|
|
||||||
FROM eclipse-temurin:21-jre-jammy
|
|
||||||
|
|
||||||
# docker CLI 설치 (컨테이너에서 호스트 Docker 제어용) 260212 추가
|
|
||||||
RUN apt-get update && \
|
|
||||||
apt-get install -y --no-install-recommends docker.io ca-certificates && \
|
|
||||||
rm -rf /var/lib/apt/lists/*
|
|
||||||
|
|
||||||
# 작업 디렉토리 설정
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
# JAR 파일 복사 (Jenkins에서 빌드된 ROOT.jar)
|
|
||||||
COPY build/libs/ROOT.jar app.jar
|
|
||||||
|
|
||||||
# 포트 노출
|
|
||||||
EXPOSE 8080
|
|
||||||
|
|
||||||
# 애플리케이션 실행
|
|
||||||
# dev 프로파일로 실행
|
|
||||||
ENTRYPOINT ["java", "-jar", "-Dspring.profiles.active=prod", "app.jar"]
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
services:
|
|
||||||
nginx:
|
|
||||||
image: nginx:alpine
|
|
||||||
container_name: kamco-cd-nginx
|
|
||||||
ports:
|
|
||||||
- "80:80"
|
|
||||||
- "443:443"
|
|
||||||
volumes:
|
|
||||||
- ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
|
|
||||||
- ./nginx/ssl:/etc/nginx/ssl:ro
|
|
||||||
- nginx-logs:/var/log/nginx
|
|
||||||
depends_on:
|
|
||||||
kamco-changedetection-api:
|
|
||||||
condition: service_healthy
|
|
||||||
networks:
|
|
||||||
- kamco-cds
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "--no-check-certificate", "https://localhost/monitor/health"]
|
|
||||||
interval: 30s
|
|
||||||
timeout: 10s
|
|
||||||
retries: 3
|
|
||||||
start_period: 10s
|
|
||||||
|
|
||||||
kamco-changedetection-api:
|
|
||||||
build:
|
|
||||||
context: .
|
|
||||||
dockerfile: Dockerfile
|
|
||||||
image: kamco-cd-training-api:${IMAGE_TAG:-latest}
|
|
||||||
container_name: kamco-cd-training-api
|
|
||||||
expose:
|
|
||||||
- "8080"
|
|
||||||
environment:
|
|
||||||
- SPRING_PROFILES_ACTIVE=prod
|
|
||||||
- TZ=Asia/Seoul
|
|
||||||
volumes:
|
|
||||||
- ./app/model_output:/app/model-outputs
|
|
||||||
- ./app/train_dataset:/app/train-dataset
|
|
||||||
- /var/run/docker.sock:/var/run/docker.sock
|
|
||||||
networks:
|
|
||||||
- kamco-cds
|
|
||||||
restart: unless-stopped
|
|
||||||
healthcheck:
|
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:8080/monitor/health"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
start_period: 40s
|
|
||||||
|
|
||||||
networks:
|
|
||||||
kamco-cds:
|
|
||||||
external: true
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
nginx-logs:
|
|
||||||
driver: local
|
|
||||||
@@ -1,397 +0,0 @@
|
|||||||
# SSL 사설 인증서 설정 가이드 (RedHat 9.6)
|
|
||||||
|
|
||||||
## 개요
|
|
||||||
|
|
||||||
이 문서는 RedHat 9.6 환경에서 `https://api.train-kamco.com` 및 `https://train-kamco.com` 도메인을 위한 100년 유효한 사설 SSL 인증서 설정 방법을 설명합니다.
|
|
||||||
|
|
||||||
## 디렉토리 구조
|
|
||||||
|
|
||||||
```
|
|
||||||
nginx/
|
|
||||||
├── nginx.conf # Nginx 설정 파일
|
|
||||||
├── ssl/
|
|
||||||
│ ├── openssl.cnf # OpenSSL 설정 파일 (SAN 포함)
|
|
||||||
│ ├── train-kamco.com.crt # 사설 SSL 인증서 (멀티 도메인)
|
|
||||||
│ └── train-kamco.com.key # 개인 키 (비공개)
|
|
||||||
└── SSL_SETUP.md # 이 문서
|
|
||||||
```
|
|
||||||
|
|
||||||
## 인증서 정보
|
|
||||||
|
|
||||||
- **도메인**: api.train-kamco.com, train-kamco.com (멀티 도메인)
|
|
||||||
- **유효 기간**: 100년 (36500일)
|
|
||||||
- **알고리즘**: RSA 4096-bit
|
|
||||||
- **CN (Common Name)**: api.train-kamco.com
|
|
||||||
- **SAN (Subject Alternative Names)**: api.train-kamco.com, train-kamco.com
|
|
||||||
|
|
||||||
## 사설 SSL 인증서 생성 (이미 생성됨)
|
|
||||||
|
|
||||||
인증서가 이미 생성되어 있습니다. 재생성이 필요한 경우 아래 단계를 따르세요.
|
|
||||||
|
|
||||||
### 1. OpenSSL 설정 파일 생성
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /path/to/kamco-train-api
|
|
||||||
|
|
||||||
cat > nginx/ssl/openssl.cnf << 'EOF'
|
|
||||||
[req]
|
|
||||||
default_bits = 4096
|
|
||||||
prompt = no
|
|
||||||
default_md = sha256
|
|
||||||
distinguished_name = dn
|
|
||||||
req_extensions = v3_req
|
|
||||||
|
|
||||||
[dn]
|
|
||||||
C=KR
|
|
||||||
ST=Seoul
|
|
||||||
L=Seoul
|
|
||||||
O=KAMCO
|
|
||||||
OU=Training
|
|
||||||
CN=api.train-kamco.com
|
|
||||||
|
|
||||||
[v3_req]
|
|
||||||
subjectAltName = @alt_names
|
|
||||||
|
|
||||||
[alt_names]
|
|
||||||
DNS.1 = api.train-kamco.com
|
|
||||||
DNS.2 = train-kamco.com
|
|
||||||
EOF
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. SSL 인증서 및 개인 키 생성
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# nginx/ssl 디렉토리 생성 (없는 경우)
|
|
||||||
mkdir -p nginx/ssl
|
|
||||||
chmod 700 nginx/ssl
|
|
||||||
|
|
||||||
# 인증서 및 개인 키 생성 (100년 유효)
|
|
||||||
openssl req -new -x509 -newkey rsa:4096 -sha256 -nodes \
|
|
||||||
-keyout nginx/ssl/train-kamco.com.key \
|
|
||||||
-out nginx/ssl/train-kamco.com.crt \
|
|
||||||
-days 36500 \
|
|
||||||
-config nginx/ssl/openssl.cnf \
|
|
||||||
-extensions v3_req
|
|
||||||
|
|
||||||
# 파일 권한 설정
|
|
||||||
chmod 600 nginx/ssl/train-kamco.com.key
|
|
||||||
chmod 644 nginx/ssl/train-kamco.com.crt
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 인증서 검증
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 인증서 정보 확인
|
|
||||||
openssl x509 -in nginx/ssl/train-kamco.com.crt -text -noout
|
|
||||||
|
|
||||||
# 유효 기간 확인
|
|
||||||
openssl x509 -in nginx/ssl/train-kamco.com.crt -text -noout | grep -A2 "Validity"
|
|
||||||
|
|
||||||
# SAN (멀티 도메인) 확인
|
|
||||||
openssl x509 -in nginx/ssl/train-kamco.com.crt -text -noout | grep -A1 "Subject Alternative Name"
|
|
||||||
|
|
||||||
# CN 확인
|
|
||||||
openssl x509 -in nginx/ssl/train-kamco.com.crt -noout -subject
|
|
||||||
|
|
||||||
# 개인 키 확인
|
|
||||||
openssl rsa -in nginx/ssl/train-kamco.com.key -check
|
|
||||||
```
|
|
||||||
|
|
||||||
**예상 결과**:
|
|
||||||
```
|
|
||||||
X509v3 Subject Alternative Name:
|
|
||||||
DNS:api.train-kamco.com, DNS:train-kamco.com
|
|
||||||
|
|
||||||
Validity
|
|
||||||
Not Before: Mar 2 23:39:XX 2026 GMT
|
|
||||||
Not After : Feb 6 23:39:XX 2126 GMT
|
|
||||||
```
|
|
||||||
|
|
||||||
## /etc/hosts 설정 (RedHat 9.6)
|
|
||||||
|
|
||||||
### 1. hosts 파일에 도메인 추가
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# root 권한으로 실행
|
|
||||||
echo "127.0.0.1 api.train-kamco.com train-kamco.com" | sudo tee -a /etc/hosts
|
|
||||||
|
|
||||||
# 확인
|
|
||||||
cat /etc/hosts | grep train-kamco
|
|
||||||
```
|
|
||||||
|
|
||||||
**예상 결과**:
|
|
||||||
```
|
|
||||||
127.0.0.1 api.train-kamco.com train-kamco.com
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. 도메인 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# ping 테스트
|
|
||||||
ping -c 2 api.train-kamco.com
|
|
||||||
ping -c 2 train-kamco.com
|
|
||||||
```
|
|
||||||
|
|
||||||
## Docker Compose 배포
|
|
||||||
|
|
||||||
### 1. 기존 컨테이너 중지 (실행 중인 경우)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /path/to/kamco-train-api
|
|
||||||
docker-compose -f docker-compose-prod.yml down
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. Production 환경 실행
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# IMAGE_TAG 환경 변수 설정 (선택사항)
|
|
||||||
export IMAGE_TAG=latest
|
|
||||||
|
|
||||||
# Docker Compose 실행
|
|
||||||
docker-compose -f docker-compose-prod.yml up -d
|
|
||||||
|
|
||||||
# 컨테이너 상태 확인
|
|
||||||
docker-compose -f docker-compose-prod.yml ps
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. 로그 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Nginx 로그
|
|
||||||
docker logs kamco-cd-nginx
|
|
||||||
|
|
||||||
# API 로그
|
|
||||||
docker logs kamco-cd-training-api
|
|
||||||
|
|
||||||
# 실시간 로그 확인
|
|
||||||
docker-compose -f docker-compose-prod.yml logs -f
|
|
||||||
```
|
|
||||||
|
|
||||||
## HTTPS 접속 테스트
|
|
||||||
|
|
||||||
### 1. HTTP → HTTPS 리다이렉트 테스트
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# api.train-kamco.com
|
|
||||||
curl -I http://api.train-kamco.com
|
|
||||||
|
|
||||||
# train-kamco.com
|
|
||||||
curl -I http://train-kamco.com
|
|
||||||
|
|
||||||
# 예상 결과: 301 Moved Permanently
|
|
||||||
# Location: https://api.train-kamco.com/ 또는 https://train-kamco.com/
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. HTTPS 헬스체크 (-k: 사설 인증서 경고 무시)
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# api.train-kamco.com
|
|
||||||
curl -k https://api.train-kamco.com/monitor/health
|
|
||||||
|
|
||||||
# train-kamco.com
|
|
||||||
curl -k https://train-kamco.com/monitor/health
|
|
||||||
|
|
||||||
# 예상 결과: {"status":"UP","components":{...}}
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. SSL 인증서 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# api.train-kamco.com
|
|
||||||
openssl s_client -connect api.train-kamco.com:443 -showcerts
|
|
||||||
|
|
||||||
# train-kamco.com
|
|
||||||
openssl s_client -connect train-kamco.com:443 -showcerts
|
|
||||||
|
|
||||||
# CN 및 SAN 확인
|
|
||||||
```
|
|
||||||
|
|
||||||
### 4. 브라우저 테스트
|
|
||||||
|
|
||||||
브라우저에서 다음 URL에 접속:
|
|
||||||
|
|
||||||
- `https://api.train-kamco.com/monitor/health`
|
|
||||||
- `https://train-kamco.com/monitor/health`
|
|
||||||
|
|
||||||
**주의**: 사설 인증서이므로 "안전하지 않음" 경고가 표시됩니다.
|
|
||||||
- **Chrome/Edge**: "고급" → "계속 진행" 클릭
|
|
||||||
- **Firefox**: "위험 감수 및 계속" 클릭
|
|
||||||
|
|
||||||
## 브라우저에서 사설 인증서 신뢰 설정 (선택사항)
|
|
||||||
|
|
||||||
사설 인증서를 브라우저에 등록하면 경고 없이 접속 가능합니다.
|
|
||||||
|
|
||||||
### Chrome/Edge (RedHat Desktop)
|
|
||||||
|
|
||||||
1. `chrome://settings/certificates` 접속
|
|
||||||
2. **Authorities** 탭 선택
|
|
||||||
3. **Import** 클릭
|
|
||||||
4. `nginx/ssl/train-kamco.com.crt` 선택
|
|
||||||
5. **Trust this certificate for identifying websites** 체크
|
|
||||||
6. **OK** 클릭
|
|
||||||
|
|
||||||
### Firefox
|
|
||||||
|
|
||||||
1. `about:preferences#privacy` 접속
|
|
||||||
2. **Certificates** → **View Certificates** 클릭
|
|
||||||
3. **Authorities** 탭 선택
|
|
||||||
4. **Import** 클릭
|
|
||||||
5. `nginx/ssl/train-kamco.com.crt` 선택
|
|
||||||
6. **Trust this CA to identify websites** 체크
|
|
||||||
7. **OK** 클릭
|
|
||||||
|
|
||||||
## 방화벽 설정 (RedHat 9.6)
|
|
||||||
|
|
||||||
### 1. 방화벽 상태 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
sudo firewall-cmd --state
|
|
||||||
```
|
|
||||||
|
|
||||||
### 2. HTTP (80) 및 HTTPS (443) 포트 개방
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# HTTP 포트 개방
|
|
||||||
sudo firewall-cmd --permanent --add-port=80/tcp
|
|
||||||
|
|
||||||
# HTTPS 포트 개방
|
|
||||||
sudo firewall-cmd --permanent --add-port=443/tcp
|
|
||||||
|
|
||||||
# 방화벽 재로드
|
|
||||||
sudo firewall-cmd --reload
|
|
||||||
|
|
||||||
# 확인
|
|
||||||
sudo firewall-cmd --list-ports
|
|
||||||
```
|
|
||||||
|
|
||||||
**예상 결과**:
|
|
||||||
```
|
|
||||||
80/tcp 443/tcp
|
|
||||||
```
|
|
||||||
|
|
||||||
## 보안 체크리스트
|
|
||||||
|
|
||||||
- [x] `train-kamco.com.key` 파일 권한이 600으로 설정됨
|
|
||||||
- [x] ssl 디렉토리가 버전 관리에서 제외됨 (.gitignore 확인)
|
|
||||||
- [x] 두 도메인(api.train-kamco.com, train-kamco.com) 모두 SAN에 포함됨
|
|
||||||
- [ ] 방화벽에서 80, 443 포트 개방 확인
|
|
||||||
- [x] HSTS 헤더 활성화 확인
|
|
||||||
- [x] TLS 1.2 이상만 허용 확인
|
|
||||||
- [ ] /etc/hosts에 도메인 매핑 확인
|
|
||||||
|
|
||||||
## 트러블슈팅
|
|
||||||
|
|
||||||
### 인증서 관련 오류
|
|
||||||
|
|
||||||
**"certificate verify failed"**
|
|
||||||
```bash
|
|
||||||
# 해결: -k 플래그 사용 (사설 인증서 경고 무시)
|
|
||||||
curl -k https://api.train-kamco.com/monitor/health
|
|
||||||
```
|
|
||||||
|
|
||||||
**"NET::ERR_CERT_AUTHORITY_INVALID" (브라우저)**
|
|
||||||
- 정상 동작: 사설 인증서이므로 브라우저 경고는 예상된 동작입니다
|
|
||||||
- 해결: 브라우저에 인증서 등록 (위 "브라우저에서 사설 인증서 신뢰 설정" 참조)
|
|
||||||
|
|
||||||
### 연결 오류
|
|
||||||
|
|
||||||
**"Connection refused"**
|
|
||||||
```bash
|
|
||||||
# 컨테이너 상태 확인
|
|
||||||
docker ps | grep kamco-cd
|
|
||||||
|
|
||||||
# 포트 바인딩 확인
|
|
||||||
docker port kamco-cd-nginx
|
|
||||||
|
|
||||||
# 예상 결과:
|
|
||||||
# 80/tcp -> 0.0.0.0:80
|
|
||||||
# 443/tcp -> 0.0.0.0:443
|
|
||||||
```
|
|
||||||
|
|
||||||
**"502 Bad Gateway"**
|
|
||||||
```bash
|
|
||||||
# API 컨테이너 상태 확인
|
|
||||||
docker logs kamco-cd-training-api
|
|
||||||
|
|
||||||
# nginx → API 연결 확인
|
|
||||||
docker exec kamco-cd-nginx wget -qO- http://kamco-changedetection-api:8080/monitor/health
|
|
||||||
```
|
|
||||||
|
|
||||||
**"Name or service not known" (도메인 해석 실패)**
|
|
||||||
```bash
|
|
||||||
# /etc/hosts 확인
|
|
||||||
cat /etc/hosts | grep train-kamco
|
|
||||||
|
|
||||||
# 없으면 추가
|
|
||||||
echo "127.0.0.1 api.train-kamco.com train-kamco.com" | sudo tee -a /etc/hosts
|
|
||||||
```
|
|
||||||
|
|
||||||
### 방화벽 관련 오류
|
|
||||||
|
|
||||||
**외부에서 접속 안 됨**
|
|
||||||
```bash
|
|
||||||
# 방화벽 확인
|
|
||||||
sudo firewall-cmd --list-ports
|
|
||||||
|
|
||||||
# 포트 개방
|
|
||||||
sudo firewall-cmd --permanent --add-port=80/tcp
|
|
||||||
sudo firewall-cmd --permanent --add-port=443/tcp
|
|
||||||
sudo firewall-cmd --reload
|
|
||||||
```
|
|
||||||
|
|
||||||
## 인증서 만료 및 갱신
|
|
||||||
|
|
||||||
### 만료 확인
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 인증서 만료일 확인
|
|
||||||
openssl x509 -in nginx/ssl/train-kamco.com.crt -noout -enddate
|
|
||||||
|
|
||||||
# 예상 결과: notAfter=Feb 6 23:39:XX 2126 GMT (100년 후)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 갱신 방법 (필요시)
|
|
||||||
|
|
||||||
100년 유효한 인증서이므로 갱신이 필요하지 않지만, 재생성이 필요한 경우:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 기존 인증서 백업
|
|
||||||
cp nginx/ssl/train-kamco.com.crt nginx/ssl/train-kamco.com.crt.bak
|
|
||||||
cp nginx/ssl/train-kamco.com.key nginx/ssl/train-kamco.com.key.bak
|
|
||||||
|
|
||||||
# 위의 "사설 SSL 인증서 생성" 단계 재실행
|
|
||||||
|
|
||||||
# nginx 재시작
|
|
||||||
docker-compose -f docker-compose-prod.yml restart nginx
|
|
||||||
```
|
|
||||||
|
|
||||||
## 주의사항
|
|
||||||
|
|
||||||
1. **사설 인증서 경고**: 브라우저에서 "안전하지 않음" 경고가 표시됩니다. 프로덕션 환경에서는 **공인 인증서(Let's Encrypt, GlobalSign 등) 사용을 권장**합니다.
|
|
||||||
|
|
||||||
2. **포트 80/443**: Docker가 자동으로 처리하지만, 이미 사용 중인 프로세스가 있으면 충돌할 수 있습니다.
|
|
||||||
```bash
|
|
||||||
# 포트 사용 확인
|
|
||||||
sudo lsof -i :80
|
|
||||||
sudo lsof -i :443
|
|
||||||
```
|
|
||||||
|
|
||||||
3. **대용량 파일 업로드**: `client_max_body_size`를 10GB로 설정했으므로, 서버 메모리 및 디스크 용량을 충분히 확보하세요.
|
|
||||||
|
|
||||||
4. **인증서 백업**: `train-kamco.com.key` 파일은 매우 중요합니다. 안전한 곳에 백업하세요.
|
|
||||||
|
|
||||||
5. **SELinux**: RedHat 9.6에서 SELinux가 활성화된 경우, Docker 볼륨 마운트 권한 문제가 발생할 수 있습니다.
|
|
||||||
```bash
|
|
||||||
# SELinux 상태 확인
|
|
||||||
getenforce
|
|
||||||
|
|
||||||
# 필요시 permissive 모드로 변경
|
|
||||||
sudo setenforce 0
|
|
||||||
```
|
|
||||||
|
|
||||||
## 참고 자료
|
|
||||||
|
|
||||||
- [OpenSSL Documentation](https://www.openssl.org/docs/)
|
|
||||||
- [Nginx SSL Configuration](https://nginx.org/en/docs/http/configuring_https_servers.html)
|
|
||||||
- [Docker Compose Documentation](https://docs.docker.com/compose/)
|
|
||||||
- [Let's Encrypt (공인 인증서)](https://letsencrypt.org/)
|
|
||||||
@@ -1,93 +0,0 @@
|
|||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
|
|
||||||
http {
|
|
||||||
include /etc/nginx/mime.types;
|
|
||||||
default_type application/octet-stream;
|
|
||||||
|
|
||||||
# 로그 설정
|
|
||||||
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
|
|
||||||
access_log /var/log/nginx/access.log main;
|
|
||||||
error_log /var/log/nginx/error.log warn;
|
|
||||||
|
|
||||||
sendfile on;
|
|
||||||
keepalive_timeout 65;
|
|
||||||
|
|
||||||
# 업로드 파일 크기 제한 (10GB)
|
|
||||||
client_max_body_size 10G;
|
|
||||||
|
|
||||||
# Upstream 설정
|
|
||||||
upstream api_backend {
|
|
||||||
server kamco-changedetection-api:8080;
|
|
||||||
}
|
|
||||||
|
|
||||||
# HTTP → HTTPS 리다이렉트 서버
|
|
||||||
server {
|
|
||||||
listen 80;
|
|
||||||
server_name api.train-kamco.com train-kamco.com;
|
|
||||||
|
|
||||||
# 모든 HTTP 요청을 HTTPS로 리다이렉트
|
|
||||||
return 301 https://$server_name$request_uri;
|
|
||||||
}
|
|
||||||
|
|
||||||
# HTTPS 서버 설정
|
|
||||||
server {
|
|
||||||
listen 443 ssl http2;
|
|
||||||
server_name api.train-kamco.com train-kamco.com;
|
|
||||||
|
|
||||||
# SSL 인증서 설정 (사설 인증서 - 멀티 도메인)
|
|
||||||
ssl_certificate /etc/nginx/ssl/train-kamco.com.crt;
|
|
||||||
ssl_certificate_key /etc/nginx/ssl/train-kamco.com.key;
|
|
||||||
|
|
||||||
# SSL 프로토콜 및 암호화 설정
|
|
||||||
ssl_protocols TLSv1.2 TLSv1.3;
|
|
||||||
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384';
|
|
||||||
ssl_prefer_server_ciphers off;
|
|
||||||
|
|
||||||
# SSL 세션 캐시
|
|
||||||
ssl_session_cache shared:SSL:10m;
|
|
||||||
ssl_session_timeout 10m;
|
|
||||||
|
|
||||||
# HSTS (HTTP Strict Transport Security)
|
|
||||||
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
|
|
||||||
|
|
||||||
# 보안 헤더
|
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
|
||||||
add_header X-Content-Type-Options "nosniff" always;
|
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
|
||||||
|
|
||||||
# 프록시 설정
|
|
||||||
location / {
|
|
||||||
proxy_pass http://api_backend;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
|
|
||||||
# 프록시 헤더 설정
|
|
||||||
proxy_set_header Host $host;
|
|
||||||
proxy_set_header X-Real-IP $remote_addr;
|
|
||||||
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
|
||||||
proxy_set_header X-Forwarded-Proto $scheme;
|
|
||||||
proxy_set_header X-Forwarded-Host $server_name;
|
|
||||||
|
|
||||||
# 타임아웃 설정 (대용량 파일 업로드 지원)
|
|
||||||
proxy_connect_timeout 300s;
|
|
||||||
proxy_send_timeout 300s;
|
|
||||||
proxy_read_timeout 300s;
|
|
||||||
|
|
||||||
# 버퍼 설정
|
|
||||||
proxy_buffering on;
|
|
||||||
proxy_buffer_size 4k;
|
|
||||||
proxy_buffers 8 4k;
|
|
||||||
proxy_busy_buffers_size 8k;
|
|
||||||
}
|
|
||||||
|
|
||||||
# 헬스체크 엔드포인트
|
|
||||||
location /monitor/health {
|
|
||||||
proxy_pass http://api_backend/monitor/health;
|
|
||||||
access_log off;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -719,18 +719,26 @@ public class FIleChecker {
|
|||||||
public static void unzip(String fileName, String destDirectory) throws IOException {
|
public static void unzip(String fileName, String destDirectory) throws IOException {
|
||||||
String zipFilePath = destDirectory + File.separator + fileName;
|
String zipFilePath = destDirectory + File.separator + fileName;
|
||||||
|
|
||||||
|
log.info("fileName : {}", fileName);
|
||||||
|
log.info("destDirectory : {}", destDirectory);
|
||||||
|
log.info("zipFilePath : {}", zipFilePath);
|
||||||
// zip 이름으로 폴더 생성 (확장자 제거)
|
// zip 이름으로 폴더 생성 (확장자 제거)
|
||||||
String folderName =
|
String folderName =
|
||||||
fileName.endsWith(".zip") ? fileName.substring(0, fileName.length() - 4) : fileName;
|
fileName.endsWith(".zip") ? fileName.substring(0, fileName.length() - 4) : fileName;
|
||||||
|
log.info("folderName : {}", folderName);
|
||||||
|
|
||||||
File destDir = new File(destDirectory, folderName);
|
File destDir = new File(destDirectory, folderName);
|
||||||
|
log.info("destDir : {}", destDir);
|
||||||
|
|
||||||
// 동일 폴더가 이미 있으면 삭제
|
// 동일 폴더가 이미 있으면 삭제
|
||||||
|
log.info("111 destDir.exists() : {}", destDir.exists());
|
||||||
if (destDir.exists()) {
|
if (destDir.exists()) {
|
||||||
deleteDirectoryRecursively(destDir.toPath());
|
deleteDirectoryRecursively(destDir.toPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.info("222 destDir.exists() : {}", destDir.exists());
|
||||||
if (!destDir.exists()) {
|
if (!destDir.exists()) {
|
||||||
|
log.info("mkdirs : {}", destDir.exists());
|
||||||
destDir.mkdirs();
|
destDir.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -398,6 +398,24 @@ public class DatasetService {
|
|||||||
return datasetCoreService.getFilePathByUUIDPathType(uuid, pathType);
|
return datasetCoreService.getFilePathByUUIDPathType(uuid, pathType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String readRemoteFileAsString(String remoteFilePath) {
|
||||||
|
|
||||||
|
String command = "cat " + escape(remoteFilePath);
|
||||||
|
|
||||||
|
List<String> lines = FIleChecker.execCommandAndReadLines(command);
|
||||||
|
|
||||||
|
return String.join("\n", lines);
|
||||||
|
}
|
||||||
|
|
||||||
|
private JsonNode parseJson(String json) {
|
||||||
|
try {
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
return mapper.readTree(json);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException("JSON 파싱 실패", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String escape(String path) {
|
private String escape(String path) {
|
||||||
// 쉘 커맨드에서 안전하게 사용할 수 있도록 문자열을 작은따옴표로 감싸면서, 내부의 작은따옴표를 이스케이프 처리
|
// 쉘 커맨드에서 안전하게 사용할 수 있도록 문자열을 작은따옴표로 감싸면서, 내부의 작은따옴표를 이스케이프 처리
|
||||||
return "'" + path.replace("'", "'\"'\"'") + "'";
|
return "'" + path.replace("'", "'\"'\"'") + "'";
|
||||||
|
|||||||
@@ -222,9 +222,7 @@ public class DataSetCountersService {
|
|||||||
log.info("missing = {}", missing.size());
|
log.info("missing = {}", missing.size());
|
||||||
log.info("extra = {}", extra.size());
|
log.info("extra = {}", extra.size());
|
||||||
|
|
||||||
log.info("[MISSING] total = {}", missing.size());
|
|
||||||
missing.stream().sorted().limit(50).forEach(f -> log.warn("[MISSING] {}", f));
|
missing.stream().sorted().limit(50).forEach(f -> log.warn("[MISSING] {}", f));
|
||||||
log.info("[EXTRA] total = {}", extra.size());
|
|
||||||
extra.stream().sorted().limit(50).forEach(f -> log.warn("[EXTRA] {}", f));
|
extra.stream().sorted().limit(50).forEach(f -> log.warn("[EXTRA] {}", f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -268,19 +268,13 @@ public class TrainJobService {
|
|||||||
try {
|
try {
|
||||||
// 데이터셋 심볼링크 생성
|
// 데이터셋 심볼링크 생성
|
||||||
// String pathUid = tmpDatasetService.buildTmpDatasetSymlink(raw, uids);
|
// String pathUid = tmpDatasetService.buildTmpDatasetSymlink(raw, uids);
|
||||||
// train path 모델 클래스별 조회
|
// train path
|
||||||
List<ModelTrainLinkDto> trainList = modelTrainMngCoreService.findDatasetTrainPath(modelId);
|
List<ModelTrainLinkDto> trainList = modelTrainMngCoreService.findDatasetTrainPath(modelId);
|
||||||
// validation path 모델 클래스별 조회
|
// validation path
|
||||||
List<ModelTrainLinkDto> valList = modelTrainMngCoreService.findDatasetValPath(modelId);
|
List<ModelTrainLinkDto> valList = modelTrainMngCoreService.findDatasetValPath(modelId);
|
||||||
// test path 모델 클래스별 조회
|
// test path
|
||||||
List<ModelTrainLinkDto> testList = modelTrainMngCoreService.findDatasetTestPath(modelId);
|
List<ModelTrainLinkDto> testList = modelTrainMngCoreService.findDatasetTestPath(modelId);
|
||||||
|
|
||||||
log.info(
|
|
||||||
"createTmpFile class list trainList = {} valList = {} testList = {}",
|
|
||||||
trainList.size(),
|
|
||||||
valList.size(),
|
|
||||||
testList.size());
|
|
||||||
|
|
||||||
// train 데이터셋 심볼링크 생성
|
// train 데이터셋 심볼링크 생성
|
||||||
tmpDatasetService.buildTmpDatasetHardlink(raw, "train", trainList);
|
tmpDatasetService.buildTmpDatasetHardlink(raw, "train", trainList);
|
||||||
// val 데이터셋 심볼링크 생성
|
// val 데이터셋 심볼링크 생성
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ spring:
|
|||||||
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
|
format_sql: true # ⚠️ 선택 - SQL 포맷팅 (가독성)
|
||||||
|
|
||||||
datasource:
|
datasource:
|
||||||
url: jdbc:postgresql://kamco-cd-train-db:5432/kamco_training_db
|
url: jdbc:postgresql://127.0.01:15432/kamco_training_db
|
||||||
# url: jdbc:postgresql://localhost:15432/kamco_training_db
|
# url: jdbc:postgresql://localhost:15432/kamco_training_db
|
||||||
username: kamco_training_user
|
username: kamco_training_user
|
||||||
password: kamco_training_user_2025_!@#
|
password: kamco_training_user_2025_!@#
|
||||||
|
|||||||
Reference in New Issue
Block a user