# Vexplor 온프레미스(공장) 배포용 Docker Compose # 사용법: docker compose up -d services: # ============================================ # 1. 데이터베이스 (PostgreSQL) # ============================================ database: image: postgres:15-alpine container_name: vexplor-db environment: POSTGRES_USER: ${DB_USER:-vexplor} POSTGRES_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required} POSTGRES_DB: ${DB_NAME:-vexplor} TZ: Asia/Seoul volumes: - postgres_data:/var/lib/postgresql/data - ./init-db:/docker-entrypoint-initdb.d # 초기화 스크립트 (선택) ports: - "${DB_PORT:-5432}:5432" restart: always healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-vexplor}"] interval: 10s timeout: 5s retries: 5 networks: - vexplor-network # ============================================ # 2. 백엔드 API (Node.js) # ============================================ backend: image: harbor.wace.me/speefox_vexplor/vexplor-backend:${IMAGE_TAG:-latest} container_name: vexplor-backend environment: NODE_ENV: production PORT: 3001 HOST: 0.0.0.0 TZ: Asia/Seoul # DB 연결 DB_HOST: database DB_PORT: 5432 DB_USER: ${DB_USER:-vexplor} DB_PASSWORD: ${DB_PASSWORD} DB_NAME: ${DB_NAME:-vexplor} # JWT JWT_SECRET: ${JWT_SECRET:?JWT_SECRET is required} JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-24h} # 암호화 키 (메일 등 민감정보 암호화용) ENCRYPTION_KEY: ${ENCRYPTION_KEY:-vexplor-encryption-key-32characters-secure} # 회사 코드 (온프레미스는 단일 회사) DEFAULT_COMPANY_CODE: ${COMPANY_CODE:-SPIFOX} # 로깅 LOG_LEVEL: ${LOG_LEVEL:-info} volumes: - backend_uploads:/app/uploads - backend_data:/app/data - backend_logs:/app/logs ports: - "${BACKEND_PORT:-3001}:3001" depends_on: database: condition: service_healthy restart: always healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/health"] interval: 30s timeout: 10s retries: 3 start_period: 40s networks: - vexplor-network labels: - "com.centurylinklabs.watchtower.enable=true" # ============================================ # 3. 프론트엔드 (Next.js) # ============================================ frontend: image: harbor.wace.me/speefox_vexplor/vexplor-frontend:${IMAGE_TAG:-latest} container_name: vexplor-frontend environment: NODE_ENV: production PORT: 3000 HOSTNAME: 0.0.0.0 TZ: Asia/Seoul # 백엔드 API URL (내부 통신) NEXT_PUBLIC_API_URL: http://${SERVER_IP:-localhost}:${BACKEND_PORT:-3001}/api ports: - "${FRONTEND_PORT:-80}:3000" depends_on: - backend restart: always healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3000"] interval: 30s timeout: 10s retries: 3 start_period: 30s networks: - vexplor-network labels: - "com.centurylinklabs.watchtower.enable=true" # ============================================ # 4. Watchtower (자동 업데이트) # ============================================ watchtower: image: containrrr/watchtower:latest container_name: vexplor-watchtower environment: TZ: Asia/Seoul DOCKER_API_VERSION: "1.44" # Harbor 레지스트리 인증 REPO_USER: ${HARBOR_USER} REPO_PASS: ${HARBOR_PASSWORD} # 업데이트 설정 # WATCHTOWER_POLL_INTERVAL: ${UPDATE_INTERVAL:-300} # 간격 기반 (비활성화) WATCHTOWER_SCHEDULE: "0 0 * * * *" # 매시 정각에 실행 (cron 형식) WATCHTOWER_CLEANUP: "true" # 이전 이미지 자동 삭제 WATCHTOWER_INCLUDE_STOPPED: "true" # 중지된 컨테이너도 업데이트 WATCHTOWER_ROLLING_RESTART: "true" # 순차 재시작 (다운타임 최소화) WATCHTOWER_LABEL_ENABLE: "true" # 라벨이 있는 컨테이너만 업데이트 # 알림 설정 (선택) # WATCHTOWER_NOTIFICATIONS: slack # WATCHTOWER_NOTIFICATION_SLACK_HOOK_URL: ${SLACK_WEBHOOK_URL} volumes: - /var/run/docker.sock:/var/run/docker.sock # Harbor 인증 정보 (docker login 후 생성됨) - ~/.docker/config.json:/config.json:ro restart: always networks: - vexplor-network # ============================================ # 볼륨 정의 # ============================================ volumes: postgres_data: driver: local backend_uploads: driver: local backend_data: driver: local backend_logs: driver: local # ============================================ # 네트워크 정의 # ============================================ networks: vexplor-network: driver: bridge