feat: Flask 애플리케이션 모듈화 및 웹 대시보드 구현
- Flask Blueprint 아키텍처로 전환 (dashboard, upload, backup, status) - app.py 681줄 95줄로 축소 (86% 감소) - HTML 템플릿 모듈화 (base.html + 기능별 templates) - CSS/JS 파일 분리 (common + 기능별 파일) - 대시보드 기능 추가 (통계, 주간 예보, 방문객 추이) - 파일 업로드 웹 인터페이스 구현 - 백업/복구 관리 UI 구현 - Docker 배포 환경 개선 - .gitignore 업데이트 (uploads, backups, cache 등)
This commit is contained in:
138
build/Dockerfile
138
build/Dockerfile
@ -1,47 +1,129 @@
|
||||
FROM python:3.10-slim
|
||||
# Dockerfile - First Garden Static Analysis Service
|
||||
# Python 3.11 기반의 가벼운 이미지 사용
|
||||
|
||||
FROM python:3.11-slim-bullseye
|
||||
|
||||
# 메타데이터 설정
|
||||
LABEL maintainer="First Garden Team"
|
||||
LABEL description="First Garden Static Analysis - Data Collection & Visitor Forecasting Service"
|
||||
|
||||
# 작업 디렉토리 설정
|
||||
WORKDIR /app
|
||||
|
||||
# 시스템 패키지 설치
|
||||
# 타임존 설정
|
||||
ENV TZ=Asia/Seoul
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
|
||||
# 시스템 패키지 업데이트 및 필수 도구 설치
|
||||
# mysqldump 및 mysql 클라이언트 추가 (DB 백업/복구 용)
|
||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
build-essential \
|
||||
gcc \
|
||||
libsqlite3-dev \
|
||||
g++ \
|
||||
build-essential \
|
||||
libmysqlclient-dev \
|
||||
libssl-dev \
|
||||
libffi-dev \
|
||||
libbz2-dev \
|
||||
libreadline-dev \
|
||||
libncurses5-dev \
|
||||
libgdbm-dev \
|
||||
liblzma-dev \
|
||||
libtk8.6 \
|
||||
tk8.6-dev \
|
||||
tcl8.6-dev \
|
||||
wget \
|
||||
curl \
|
||||
unzip \
|
||||
wget \
|
||||
git \
|
||||
cron \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
mariadb-client \
|
||||
&& rm -rf /var/lib/apt/lists/* \
|
||||
&& apt-get clean
|
||||
|
||||
# requirements 설치
|
||||
# Python 의존성 설치
|
||||
COPY requirements.txt ./
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
RUN pip install --no-cache-dir --upgrade pip setuptools wheel && \
|
||||
pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
# 앱 전체 복사
|
||||
# 앱 코드 복사
|
||||
COPY . .
|
||||
|
||||
# 환경 변수 설정
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
# 로그 디렉토리 생성
|
||||
RUN mkdir -p /app/logs /app/data /app/output /app/uploads /app/dbbackup && \
|
||||
chmod 755 /app/logs /app/data /app/output /app/uploads /app/dbbackup
|
||||
|
||||
# 크론 작업 등록: 매일 11시에 daily_run.py 실행
|
||||
RUN echo "0 11 * * * python /app/daily_run.py >> /var/log/cron.log 2>&1" > /etc/cron.d/daily-cron \
|
||||
&& chmod 0644 /etc/cron.d/daily-cron \
|
||||
&& crontab /etc/cron.d/daily-cron
|
||||
# 크론 작업 설정: 매일 11시 UTC (서울 시간 20시)에 daily_run.py 실행
|
||||
RUN echo "0 11 * * * cd /app && python daily_run.py >> /app/logs/daily_run.log 2>&1" > /etc/cron.d/daily-forecast && \
|
||||
chmod 0644 /etc/cron.d/daily-forecast && \
|
||||
crontab /etc/cron.d/daily-forecast
|
||||
|
||||
# 로그 파일 생성
|
||||
RUN touch /var/log/cron.log
|
||||
# 헬스체크 스크립트 생성
|
||||
RUN cat > /app/healthcheck.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
# 컨테이너 시작 시 cron 실행 + file_watch.py 실행 + 로그 출력 유지
|
||||
CMD cron && python lib/file_watch.py & tail -f /var/log/cron.log
|
||||
# DB 연결 확인
|
||||
python -c "
|
||||
import sys
|
||||
sys.path.insert(0, '/app')
|
||||
from conf import db
|
||||
try:
|
||||
session = db.get_session()
|
||||
session.execute('SELECT 1')
|
||||
session.close()
|
||||
print('DB Connection OK')
|
||||
except Exception as e:
|
||||
print(f'DB Connection Failed: {e}')
|
||||
sys.exit(1)
|
||||
" && exit 0 || exit 1
|
||||
EOF
|
||||
chmod +x /app/healthcheck.sh
|
||||
|
||||
# 컨테이너 시작 스크립트 생성
|
||||
# Flask 웹 서버(포트 8889) + 크론 + 파일 감시 서비스 병렬 실행
|
||||
RUN cat > /app/docker-entrypoint.sh << 'EOF'
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] ========================================="
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Starting First Garden Static Service"
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] ========================================="
|
||||
|
||||
# 크론 데몬 시작 (백그라운드)
|
||||
# 일정 시간에 daily_run.py 자동 실행
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Starting cron daemon..."
|
||||
cron -f > /app/logs/cron.log 2>&1 &
|
||||
CRON_PID=$!
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Cron daemon started (PID: $CRON_PID)"
|
||||
|
||||
# file_watch.py 실행 (백그라운드)
|
||||
# 로컬 파일 시스템 감시 및 자동 처리
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Starting file watch service..."
|
||||
cd /app
|
||||
python lib/file_watch.py > /app/logs/file_watch.log 2>&1 &
|
||||
WATCH_PID=$!
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] File watch service started (PID: $WATCH_PID)"
|
||||
|
||||
# Flask 웹 서버 시작 (포트 8889)
|
||||
# 파일 업로드, DB 백업/복구 API 제공
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Starting Flask file upload server (port 8889)..."
|
||||
cd /app
|
||||
python -c "from app.app import run_app; run_app()" > /app/logs/flask_app.log 2>&1 &
|
||||
FLASK_PID=$!
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Flask server started (PID: $FLASK_PID)"
|
||||
|
||||
# 신호 처리: 컨테이너 종료 시 모든 하위 프로세스 정리
|
||||
trap "
|
||||
echo '[$(date +\"%Y-%m-%d %H:%M:%S\")] Shutting down services...'
|
||||
kill $CRON_PID $WATCH_PID $FLASK_PID 2>/dev/null || true
|
||||
exit 0
|
||||
" SIGTERM SIGINT
|
||||
|
||||
# 프로세스 모니터링
|
||||
# 하위 프로세스 상태 확인
|
||||
echo "[$(date +'%Y-%m-%d %H:%M:%S')] Service monitoring started"
|
||||
while true; do
|
||||
wait
|
||||
done
|
||||
EOF
|
||||
chmod +x /app/docker-entrypoint.sh
|
||||
|
||||
# 포트 노출 선언
|
||||
# 8889: Flask 파일 업로드 서버
|
||||
# 5000: 기타 서비스 포트
|
||||
EXPOSE 8889 5000
|
||||
|
||||
# 엔트리포인트 설정
|
||||
ENTRYPOINT ["/app/docker-entrypoint.sh"]
|
||||
|
||||
Reference in New Issue
Block a user