Files
news-project/SYNOLOGY_SETUP.md
hyungi 2fb0637ad1 📚 Add comprehensive setup documentation
- TECH_STACK.md: Complete technology stack overview
- HOMEBREW_SETUP.md: macOS development environment setup guide
- SYNOLOGY_SETUP.md: General Synology NAS installation guide
- DS1525_OPTIMIZED_SETUP.md: DS1525+ 32GB RAM optimized configuration

Features:
 Multi-platform deployment options (Mac/NAS)
 Performance optimization for different hardware specs
 Docker-based containerization
 Monitoring and logging setup
 Automated backup and maintenance scripts
 SSD optimization for longevity
2025-09-14 12:23:35 +09:00

17 KiB

🏠 시놀로지 NAS 설치 가이드

📋 개요

시놀로지 NAS에서 산업 전문 정보 수집 시스템을 Docker 기반으로 설치하는 가이드입니다. 24시간 안정적인 서비스 운영이 가능하며, 480GB SSD 환경에 최적화된 설정을 제공합니다.


🔧 사전 요구사항

하드웨어 요구사항

  • 시놀로지 NAS: DS220+, DS720+, DS920+ 이상 (Docker 지원 모델)
  • 메모리: 4GB 이상 (8GB 권장)
  • 저장공간: 480GB SSD (충분함)
  • 네트워크: 기가비트 이더넷

소프트웨어 요구사항

  • DSM: 7.0 이상
  • Docker: Container Manager 패키지
  • Git Server: Git 저장소 관리용 (선택사항)

🐳 1단계: Docker 환경 설정

Container Manager 설치

1. 패키지 센터 → Container Manager 검색 및 설치
2. Container Manager 실행
3. 레지스트리 탭에서 필요한 이미지 다운로드 준비

필요한 Docker 이미지 다운로드

# SSH로 NAS 접속 후 실행
docker pull python:3.11-slim
docker pull postgres:15-alpine
docker pull redis:7-alpine
docker pull elasticsearch:8.11.0
docker pull nginx:alpine

볼륨 및 네트워크 설정

# 전용 네트워크 생성
docker network create industrial-net

# 데이터 볼륨 생성
docker volume create postgres-data
docker volume create elasticsearch-data
docker volume create redis-data
docker volume create app-logs

📁 2단계: 디렉토리 구조 설정

NAS 내 프로젝트 디렉토리 생성

# SSH 접속 후 디렉토리 생성
mkdir -p /volume1/docker/industrial-info/{
    app,
    data/{postgres,elasticsearch,redis,logs},
    config,
    backup
}

# 권한 설정
chown -R 1000:1000 /volume1/docker/industrial-info

디렉토리 구조

/volume1/docker/industrial-info/
├── app/                    # 애플리케이션 코드
├── data/                   # 데이터 저장소
│   ├── postgres/          # PostgreSQL 데이터
│   ├── elasticsearch/     # Elasticsearch 데이터
│   ├── redis/            # Redis 데이터
│   └── logs/             # 애플리케이션 로그
├── config/               # 설정 파일들
└── backup/              # 백업 파일들

🐘 3단계: PostgreSQL 설정

PostgreSQL 컨테이너 생성

# docker-compose.yml의 PostgreSQL 부분
version: '3.8'
services:
  postgres:
    image: postgres:15-alpine
    container_name: industrial-postgres
    environment:
      POSTGRES_DB: industrial_info
      POSTGRES_USER: industrial_user
      POSTGRES_PASSWORD: secure_password_here
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"
    volumes:
      - /volume1/docker/industrial-info/data/postgres:/var/lib/postgresql/data
      - /volume1/docker/industrial-info/config/postgres.conf:/etc/postgresql/postgresql.conf
    ports:
      - "5432:5432"
    networks:
      - industrial-net
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M

PostgreSQL 최적화 설정

# /volume1/docker/industrial-info/config/postgres.conf 생성
cat > /volume1/docker/industrial-info/config/postgres.conf << EOF
# 시놀로지 NAS 최적화 설정
shared_buffers = 256MB
effective_cache_size = 1GB
maintenance_work_mem = 64MB
checkpoint_completion_target = 0.9
wal_buffers = 16MB
default_statistics_target = 100
random_page_cost = 1.1
effective_io_concurrency = 200

# 로그 설정
log_destination = 'stderr'
logging_collector = on
log_directory = '/var/log/postgresql'
log_filename = 'postgresql-%Y-%m-%d_%H%M%S.log'
log_rotation_age = 1d
log_rotation_size = 100MB
EOF

🔍 4단계: Elasticsearch 설정

Elasticsearch 컨테이너 (경량화 버전)

# docker-compose.yml의 Elasticsearch 부분
  elasticsearch:
    image: elasticsearch:8.11.0
    container_name: industrial-elasticsearch
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx1g"  # NAS 메모리 고려
      - xpack.security.enabled=false
      - xpack.security.enrollment.enabled=false
    volumes:
      - /volume1/docker/industrial-info/data/elasticsearch:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
    networks:
      - industrial-net
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1.5G
        reservations:
          memory: 1G
    ulimits:
      memlock:
        soft: -1
        hard: -1

Elasticsearch 한국어 분석기 설정

# 컨테이너 실행 후 nori 플러그인 설치
docker exec industrial-elasticsearch elasticsearch-plugin install analysis-nori
docker restart industrial-elasticsearch

🔴 5단계: Redis 설정

Redis 컨테이너

# docker-compose.yml의 Redis 부분
  redis:
    image: redis:7-alpine
    container_name: industrial-redis
    command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - /volume1/docker/industrial-info/data/redis:/data
    ports:
      - "6379:6379"
    networks:
      - industrial-net
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 512M
        reservations:
          memory: 256M

🐍 6단계: 애플리케이션 설정

애플리케이션 Dockerfile

# /volume1/docker/industrial-info/app/Dockerfile
FROM python:3.11-slim

WORKDIR /app

# 시스템 패키지 설치
RUN apt-get update && apt-get install -y \
    gcc \
    g++ \
    curl \
    && rm -rf /var/lib/apt/lists/*

# Python 의존성 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 애플리케이션 코드 복사
COPY . .

# 포트 노출
EXPOSE 8000

# 애플리케이션 실행
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

애플리케이션 컨테이너

# docker-compose.yml의 애플리케이션 부분
  app:
    build: ./app
    container_name: industrial-app
    environment:
      - DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
      - REDIS_URL=redis://redis:6379/0
      - ELASTICSEARCH_URL=http://elasticsearch:9200
    volumes:
      - /volume1/docker/industrial-info/app:/app
      - /volume1/docker/industrial-info/data/logs:/app/logs
    ports:
      - "8000:8000"
    networks:
      - industrial-net
    depends_on:
      - postgres
      - redis
      - elasticsearch
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1G
        reservations:
          memory: 512M

🌐 7단계: Nginx 리버스 프록시

Nginx 설정

# docker-compose.yml의 Nginx 부분
  nginx:
    image: nginx:alpine
    container_name: industrial-nginx
    volumes:
      - /volume1/docker/industrial-info/config/nginx.conf:/etc/nginx/nginx.conf
      - /volume1/docker/industrial-info/data/logs:/var/log/nginx
    ports:
      - "80:80"
      - "443:443"
    networks:
      - industrial-net
    depends_on:
      - app
    restart: unless-stopped

Nginx 설정 파일

# /volume1/docker/industrial-info/config/nginx.conf
events {
    worker_connections 1024;
}

http {
    upstream app {
        server app:8000;
    }

    server {
        listen 80;
        server_name _;

        client_max_body_size 100M;

        location / {
            proxy_pass http://app;
            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;
        }

        location /api/ {
            proxy_pass http://app;
            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;
        }
    }
}

📦 8단계: 통합 Docker Compose

완전한 docker-compose.yml

# /volume1/docker/industrial-info/docker-compose.yml
version: '3.8'

networks:
  industrial-net:
    driver: bridge

services:
  postgres:
    image: postgres:15-alpine
    container_name: industrial-postgres
    environment:
      POSTGRES_DB: industrial_info
      POSTGRES_USER: industrial_user
      POSTGRES_PASSWORD: secure_password_here
      POSTGRES_INITDB_ARGS: "--encoding=UTF-8 --locale=C"
    volumes:
      - /volume1/docker/industrial-info/data/postgres:/var/lib/postgresql/data
    ports:
      - "5432:5432"
    networks:
      - industrial-net
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1G

  redis:
    image: redis:7-alpine
    container_name: industrial-redis
    command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
    volumes:
      - /volume1/docker/industrial-info/data/redis:/data
    ports:
      - "6379:6379"
    networks:
      - industrial-net
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 512M

  elasticsearch:
    image: elasticsearch:8.11.0
    container_name: industrial-elasticsearch
    environment:
      - discovery.type=single-node
      - "ES_JAVA_OPTS=-Xms512m -Xmx1g"
      - xpack.security.enabled=false
      - xpack.security.enrollment.enabled=false
    volumes:
      - /volume1/docker/industrial-info/data/elasticsearch:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"
    networks:
      - industrial-net
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1.5G
    ulimits:
      memlock:
        soft: -1
        hard: -1

  app:
    build: ./app
    container_name: industrial-app
    environment:
      - DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
      - REDIS_URL=redis://redis:6379/0
      - ELASTICSEARCH_URL=http://elasticsearch:9200
      - PYTHONPATH=/app
    volumes:
      - /volume1/docker/industrial-info/app:/app
      - /volume1/docker/industrial-info/data/logs:/app/logs
    ports:
      - "8000:8000"
    networks:
      - industrial-net
    depends_on:
      - postgres
      - redis
      - elasticsearch
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 1G

  nginx:
    image: nginx:alpine
    container_name: industrial-nginx
    volumes:
      - /volume1/docker/industrial-info/config/nginx.conf:/etc/nginx/nginx.conf
      - /volume1/docker/industrial-info/data/logs:/var/log/nginx
    ports:
      - "80:80"
    networks:
      - industrial-net
    depends_on:
      - app
    restart: unless-stopped

  # 데이터 수집 워커 (Celery)
  worker:
    build: ./app
    container_name: industrial-worker
    command: celery -A main.celery worker --loglevel=info
    environment:
      - DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
      - REDIS_URL=redis://redis:6379/0
      - ELASTICSEARCH_URL=http://elasticsearch:9200
    volumes:
      - /volume1/docker/industrial-info/app:/app
      - /volume1/docker/industrial-info/data/logs:/app/logs
    networks:
      - industrial-net
    depends_on:
      - postgres
      - redis
      - elasticsearch
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 512M

  # 스케줄러 (Celery Beat)
  scheduler:
    build: ./app
    container_name: industrial-scheduler
    command: celery -A main.celery beat --loglevel=info
    environment:
      - DATABASE_URL=postgresql://industrial_user:secure_password_here@postgres:5432/industrial_info
      - REDIS_URL=redis://redis:6379/0
      - ELASTICSEARCH_URL=http://elasticsearch:9200
    volumes:
      - /volume1/docker/industrial-info/app:/app
      - /volume1/docker/industrial-info/data/logs:/app/logs
    networks:
      - industrial-net
    depends_on:
      - postgres
      - redis
      - elasticsearch
    restart: unless-stopped
    deploy:
      resources:
        limits:
          memory: 256M

🚀 9단계: 배포 및 실행

시스템 실행

# 프로젝트 디렉토리로 이동
cd /volume1/docker/industrial-info

# 컨테이너 빌드 및 실행
docker-compose up --build -d

# 로그 확인
docker-compose logs -f

# 서비스 상태 확인
docker-compose ps

데이터베이스 초기화

# 애플리케이션 컨테이너에서 마이그레이션 실행
docker exec industrial-app python manage.py migrate

# 슈퍼유저 생성
docker exec -it industrial-app python manage.py createsuperuser

📊 10단계: 모니터링 및 최적화

리소스 모니터링

# 컨테이너 리소스 사용량 확인
docker stats

# 디스크 사용량 확인
df -h /volume1

# 메모리 사용량 확인
free -h

로그 관리

# 로그 로테이션 설정 (crontab)
# 매일 자정에 로그 압축 및 정리
0 0 * * * find /volume1/docker/industrial-info/data/logs -name "*.log" -mtime +7 -exec gzip {} \;
0 0 * * * find /volume1/docker/industrial-info/data/logs -name "*.gz" -mtime +30 -delete

성능 최적화 설정

# 시놀로지 NAS 최적화
echo 'vm.swappiness=10' >> /etc/sysctl.conf
echo 'vm.vfs_cache_pressure=50' >> /etc/sysctl.conf

# Docker 로그 크기 제한
cat > /etc/docker/daemon.json << EOF
{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}
EOF

🔄 11단계: 백업 및 복원

자동 백업 스크립트

# /volume1/docker/industrial-info/backup/backup.sh
#!/bin/bash

BACKUP_DIR="/volume1/docker/industrial-info/backup"
DATE=$(date +%Y%m%d_%H%M%S)

# PostgreSQL 백업
docker exec industrial-postgres pg_dump -U industrial_user industrial_info > $BACKUP_DIR/postgres_$DATE.sql

# Elasticsearch 백업 (인덱스 설정만)
curl -X GET "localhost:9200/_cat/indices?v" > $BACKUP_DIR/elasticsearch_indices_$DATE.txt

# 애플리케이션 코드 백업
tar -czf $BACKUP_DIR/app_$DATE.tar.gz /volume1/docker/industrial-info/app

# 7일 이상 된 백업 파일 삭제
find $BACKUP_DIR -name "*.sql" -mtime +7 -delete
find $BACKUP_DIR -name "*.tar.gz" -mtime +7 -delete

echo "Backup completed: $DATE"

백업 스케줄 설정

# crontab 설정
# 매일 새벽 2시에 백업 실행
0 2 * * * /volume1/docker/industrial-info/backup/backup.sh >> /volume1/docker/industrial-info/data/logs/backup.log 2>&1

🌐 12단계: 외부 접근 설정

시놀로지 방화벽 설정

제어판 → 보안 → 방화벽 → 규칙 편집
- 포트 80 (HTTP) 허용
- 포트 443 (HTTPS) 허용 (SSL 인증서 설정 시)
- 포트 8000 (개발용, 선택사항)

DDNS 설정

제어판 → 외부 액세스 → DDNS
- Synology DDNS 서비스 활용
- 또는 외부 DDNS 서비스 연동

SSL 인증서 설정

제어판 → 보안 → 인증서
- Let's Encrypt 무료 인증서 발급
- 자동 갱신 설정

🚨 문제 해결

일반적인 문제들

1. 메모리 부족

# Elasticsearch 메모리 줄이기
# docker-compose.yml에서 ES_JAVA_OPTS 수정
- "ES_JAVA_OPTS=-Xms256m -Xmx512m"

# 불필요한 컨테이너 중지
docker-compose stop worker scheduler

2. 디스크 공간 부족

# Docker 이미지 정리
docker system prune -a

# 로그 파일 정리
docker-compose exec app find /app/logs -name "*.log" -mtime +3 -delete

# 백업 파일 정리
find /volume1/docker/industrial-info/backup -mtime +30 -delete

3. 네트워크 연결 문제

# 네트워크 재생성
docker network rm industrial-net
docker network create industrial-net

# 컨테이너 재시작
docker-compose restart

성능 튜닝

SSD 최적화

# SSD 수명 연장을 위한 설정
echo 'deadline' > /sys/block/sda/queue/scheduler
echo '1' > /sys/block/sda/queue/iosched/fifo_batch

네트워크 최적화

# TCP 버퍼 크기 조정
echo 'net.core.rmem_max = 16777216' >> /etc/sysctl.conf
echo 'net.core.wmem_max = 16777216' >> /etc/sysctl.conf

📈 시놀로지 vs Mac 비교

시놀로지 NAS 장점

  • 24시간 안정 운영: 전력 효율적, 저소음
  • 자동 백업: RAID 구성, 스냅샷 기능
  • 원격 접근: DDNS, VPN 지원
  • 비용 효율: 전력비 절약, 별도 서버 불필요
  • 확장성: 패키지 센터, Docker 지원

Mac 개발 환경 장점

  • 개발 편의성: 네이티브 도구, IDE 지원
  • 성능: 더 빠른 CPU, 메모리
  • 디버깅: 직접적인 로그 접근
  • 유연성: 패키지 관리 용이

권장 사용 시나리오

개발 단계: Mac (HOMEBREW_SETUP.md)
    ↓
테스트/스테이징: 시놀로지 NAS (현재 문서)
    ↓
프로덕션: 클라우드 또는 전용 서버

🎯 결론

시놀로지 NAS는 다음과 같은 경우에 최적입니다:

  1. 24시간 서비스 운영이 필요한 경우
  2. 전력 효율성을 중시하는 경우
  3. 자동 백업 및 데이터 보호가 중요한 경우
  4. 원격 접근이 필요한 경우
  5. 비용 절약을 원하는 경우

480GB SSD는 이 프로젝트에 충분하며, 적절한 로그 관리와 백업 정책으로 장기간 안정적인 운영이 가능합니다.


시놀로지 NAS로 더 안정적이고 효율적인 산업 정보 시스템을 구축해보세요! 🏠🚀