feat: add Docker support with private registry
- Add Dockerfile with vim, Korean locale, visual mode disabled - Add docker-compose.yml with build/push support for reg.firstgarden.co.kr - Add docker-entrypoint.sh for multi-service support - Add .dockerignore - Update README.md with Docker deployment guide - Consolidate SERVICE_KEY into DATA_API_SERVICE_KEY
This commit is contained in:
55
.dockerignore
Normal file
55
.dockerignore
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Git
|
||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Python
|
||||||
|
__pycache__
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
*.egg-info
|
||||||
|
.eggs
|
||||||
|
*.egg
|
||||||
|
.pytest_cache
|
||||||
|
.coverage
|
||||||
|
htmlcov
|
||||||
|
|
||||||
|
# 가상환경
|
||||||
|
venv/
|
||||||
|
.venv/
|
||||||
|
ENV/
|
||||||
|
env/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.idea/
|
||||||
|
.vscode/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# 로그 및 데이터 (컨테이너에서 볼륨으로 마운트)
|
||||||
|
logs/
|
||||||
|
data/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# 환경 파일 (docker-compose에서 env_file로 마운트)
|
||||||
|
.env
|
||||||
|
|
||||||
|
# 임시 파일
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
*.tmp
|
||||||
|
*.bak
|
||||||
|
|
||||||
|
# Docker 관련
|
||||||
|
Dockerfile
|
||||||
|
docker-compose*.yml
|
||||||
|
.dockerignore
|
||||||
|
|
||||||
|
# 문서
|
||||||
|
*.md
|
||||||
|
!README.md
|
||||||
|
|
||||||
|
# 기타
|
||||||
|
*.sqlite
|
||||||
|
*.db
|
||||||
72
Dockerfile
Normal file
72
Dockerfile
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
# ###################################################################
|
||||||
|
# Dockerfile - FGTools
|
||||||
|
# ###################################################################
|
||||||
|
# 퍼스트가든 통합 도구 Docker 이미지
|
||||||
|
# ###################################################################
|
||||||
|
|
||||||
|
FROM python:3.11-slim
|
||||||
|
|
||||||
|
LABEL maintainer="dev@firstgarden.co.kr"
|
||||||
|
LABEL description="FGTools - First Garden 통합 도구"
|
||||||
|
|
||||||
|
# 환경변수 설정
|
||||||
|
ENV PYTHONDONTWRITEBYTECODE=1
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
ENV PYTHONIOENCODING=utf-8
|
||||||
|
ENV LANG=C.UTF-8
|
||||||
|
ENV LC_ALL=C.UTF-8
|
||||||
|
ENV TZ=Asia/Seoul
|
||||||
|
|
||||||
|
# 작업 디렉토리 설정
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 시스템 패키지 설치 (vim + 한글 지원 + 타임존)
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
vim \
|
||||||
|
locales \
|
||||||
|
tzdata \
|
||||||
|
curl \
|
||||||
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
|
&& ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \
|
||||||
|
&& echo $TZ > /etc/timezone
|
||||||
|
|
||||||
|
# 한글 로케일 설정
|
||||||
|
RUN sed -i '/ko_KR.UTF-8/s/^# //g' /etc/locale.gen && \
|
||||||
|
locale-gen ko_KR.UTF-8
|
||||||
|
ENV LANG=ko_KR.UTF-8
|
||||||
|
ENV LC_ALL=ko_KR.UTF-8
|
||||||
|
|
||||||
|
# vim 설정 (visual mode 비활성화 + 한글 지원)
|
||||||
|
RUN echo 'set mouse-=a' >> /etc/vim/vimrc.local && \
|
||||||
|
echo 'set encoding=utf-8' >> /etc/vim/vimrc.local && \
|
||||||
|
echo 'set fileencodings=utf-8,cp949,euc-kr' >> /etc/vim/vimrc.local && \
|
||||||
|
echo 'set termencoding=utf-8' >> /etc/vim/vimrc.local
|
||||||
|
|
||||||
|
# Python 의존성 설치
|
||||||
|
COPY requirements.txt .
|
||||||
|
RUN pip install --no-cache-dir --upgrade pip && \
|
||||||
|
pip install --no-cache-dir -r requirements.txt && \
|
||||||
|
pip install --no-cache-dir gunicorn
|
||||||
|
|
||||||
|
# 애플리케이션 코드 복사
|
||||||
|
COPY core/ ./core/
|
||||||
|
COPY services/ ./services/
|
||||||
|
COPY apps/ ./apps/
|
||||||
|
COPY *.py ./
|
||||||
|
|
||||||
|
# 로그 및 데이터 디렉토리 생성
|
||||||
|
RUN mkdir -p /app/logs /app/data /app/conf
|
||||||
|
|
||||||
|
# 헬스체크
|
||||||
|
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
|
||||||
|
CMD curl -f http://localhost:${FLASK_PORT:-5000}/api/dashboard/health || exit 1
|
||||||
|
|
||||||
|
# 기본 포트 노출
|
||||||
|
EXPOSE 5000 5001 5002
|
||||||
|
|
||||||
|
# 엔트리포인트
|
||||||
|
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||||
|
RUN chmod +x /docker-entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||||
|
CMD ["dashboard"]
|
||||||
175
README.md
175
README.md
@ -96,7 +96,7 @@ python -m apps.weather_api.app
|
|||||||
python -m apps.webhook.app
|
python -m apps.webhook.app
|
||||||
```
|
```
|
||||||
|
|
||||||
### 4. Docker로 실행
|
### 4. Docker로 실행 (개발용)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Docker Compose로 모든 서비스 실행
|
# Docker Compose로 모든 서비스 실행
|
||||||
@ -106,6 +106,179 @@ docker-compose up -d
|
|||||||
docker-compose logs -f
|
docker-compose logs -f
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 🐳 Docker 배포 (운영 서버)
|
||||||
|
|
||||||
|
운영 서버에서는 `docker-compose.yml`과 `.env` 파일만으로 서비스를 실행할 수 있습니다.
|
||||||
|
|
||||||
|
### 1. 디렉토리 및 파일 준비
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 작업 디렉토리 생성
|
||||||
|
mkdir -p /opt/fgtools
|
||||||
|
cd /opt/fgtools
|
||||||
|
|
||||||
|
# 필요한 디렉토리 생성
|
||||||
|
mkdir -p logs data conf
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. docker-compose.yml 다운로드
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# docker-compose.yml 다운로드
|
||||||
|
curl -o docker-compose.yml https://git.siane.kr/firstgarden/fgtools/raw/branch/main/docker-compose.yml
|
||||||
|
```
|
||||||
|
|
||||||
|
또는 아래 내용으로 `docker-compose.yml` 파일을 직접 생성:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
x-common: &common
|
||||||
|
image: reg.firstgarden.co.kr/fgtools:latest
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Seoul
|
||||||
|
- PYTHONIOENCODING=utf-8
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- fgtools-network
|
||||||
|
|
||||||
|
services:
|
||||||
|
dashboard:
|
||||||
|
<<: *common
|
||||||
|
container_name: fgtools-dashboard
|
||||||
|
command: ["dashboard"]
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
environment:
|
||||||
|
- FLASK_PORT=5000
|
||||||
|
volumes:
|
||||||
|
- ./logs:/app/logs
|
||||||
|
- ./data:/app/data
|
||||||
|
- ./conf:/app/conf:ro
|
||||||
|
|
||||||
|
weather-api:
|
||||||
|
<<: *common
|
||||||
|
container_name: fgtools-weather
|
||||||
|
command: ["weather"]
|
||||||
|
ports:
|
||||||
|
- "5001:5001"
|
||||||
|
environment:
|
||||||
|
- FLASK_PORT=5001
|
||||||
|
volumes:
|
||||||
|
- ./logs:/app/logs
|
||||||
|
- ./data:/app/data
|
||||||
|
- ./conf:/app/conf:ro
|
||||||
|
|
||||||
|
webhook:
|
||||||
|
<<: *common
|
||||||
|
container_name: fgtools-webhook
|
||||||
|
command: ["webhook"]
|
||||||
|
ports:
|
||||||
|
- "5002:5002"
|
||||||
|
environment:
|
||||||
|
- FLASK_PORT=5002
|
||||||
|
volumes:
|
||||||
|
- ./logs:/app/logs
|
||||||
|
- ./data:/app/data
|
||||||
|
- ./conf:/app/conf:ro
|
||||||
|
|
||||||
|
networks:
|
||||||
|
fgtools-network:
|
||||||
|
driver: bridge
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 환경 설정 파일 생성
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# .env 파일 생성 (아래 내용 참고하여 편집)
|
||||||
|
cat > .env << 'EOF'
|
||||||
|
# 공공데이터포털 API 키
|
||||||
|
DATA_API_SERVICE_KEY=your_api_key_here
|
||||||
|
|
||||||
|
# 데이터베이스
|
||||||
|
DB_HOST=your_db_host
|
||||||
|
DB_USER=your_db_user
|
||||||
|
DB_PASSWORD=your_db_password
|
||||||
|
DB_NAME=your_db_name
|
||||||
|
DB_CHARSET=utf8mb4
|
||||||
|
|
||||||
|
# Mattermost 알림
|
||||||
|
MATTERMOST_ENABLED=true
|
||||||
|
MATTERMOST_URL=https://your-mattermost.com
|
||||||
|
MATTERMOST_TOKEN=your_token
|
||||||
|
MATTERMOST_CHANNEL_ID=your_channel_id
|
||||||
|
|
||||||
|
# 기타 설정은 필요에 따라 추가
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# .env 파일 편집
|
||||||
|
vi .env
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. 사설 레지스트리 로그인
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 사설 레지스트리 로그인
|
||||||
|
docker login reg.firstgarden.co.kr
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. 서비스 실행
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 이미지 다운로드 및 서비스 시작
|
||||||
|
docker-compose pull
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 상태 확인
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
# 로그 확인
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. 서비스 관리
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 전체 서비스 중지
|
||||||
|
docker-compose down
|
||||||
|
|
||||||
|
# 특정 서비스만 재시작
|
||||||
|
docker-compose restart dashboard
|
||||||
|
|
||||||
|
# 서비스 업데이트 (새 이미지 배포 시)
|
||||||
|
docker-compose pull
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 컨테이너 쉘 접속
|
||||||
|
docker exec -it fgtools-dashboard /bin/bash
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. 포트 및 서비스 정보
|
||||||
|
|
||||||
|
| 서비스 | 컨테이너명 | 포트 | 헬스체크 URL |
|
||||||
|
|--------|-----------|------|--------------|
|
||||||
|
| Dashboard | fgtools-dashboard | 5000 | http://localhost:5000/api/dashboard/health |
|
||||||
|
| Weather API | fgtools-weather | 5001 | http://localhost:5001/api/weather/health |
|
||||||
|
| Webhook | fgtools-webhook | 5002 | http://localhost:5002/webhook/health |
|
||||||
|
|
||||||
|
### 8. 이미지 빌드 및 푸시 (개발자용)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 소스 디렉토리에서 실행
|
||||||
|
cd /path/to/fgtools
|
||||||
|
|
||||||
|
# 이미지 빌드
|
||||||
|
docker-compose build
|
||||||
|
|
||||||
|
# 사설 레지스트리에 푸시
|
||||||
|
docker-compose push
|
||||||
|
|
||||||
|
# 빌드와 푸시 한번에
|
||||||
|
docker-compose build && docker-compose push
|
||||||
|
```
|
||||||
|
|
||||||
## 📖 API 문서
|
## 📖 API 문서
|
||||||
|
|
||||||
### Dashboard API (포트 5000)
|
### Dashboard API (포트 5000)
|
||||||
|
|||||||
@ -160,9 +160,9 @@ class Config:
|
|||||||
|
|
||||||
self.force_update = self._get_bool('FORCE_UPDATE', False)
|
self.force_update = self._get_bool('FORCE_UPDATE', False)
|
||||||
|
|
||||||
# Weather 서비스 설정
|
# Weather 서비스 설정 (DATA_API_SERVICE_KEY 사용)
|
||||||
self.weather_service = {
|
self.weather_service = {
|
||||||
'service_key': self._get_env('SERVICE_KEY', ''),
|
'service_key': self._get_env('DATA_API_SERVICE_KEY', ''),
|
||||||
}
|
}
|
||||||
|
|
||||||
# FTP 설정
|
# FTP 설정
|
||||||
|
|||||||
102
docker-compose.yml
Normal file
102
docker-compose.yml
Normal file
@ -0,0 +1,102 @@
|
|||||||
|
# ###################################################################
|
||||||
|
# docker-compose.yml - FGTools 서비스 구성
|
||||||
|
# ###################################################################
|
||||||
|
# 사설 레지스트리: reg.firstgarden.co.kr
|
||||||
|
#
|
||||||
|
# 사용법:
|
||||||
|
# 빌드: docker-compose build
|
||||||
|
# 푸시: docker-compose push
|
||||||
|
# 실행: docker-compose up -d
|
||||||
|
# 중지: docker-compose down
|
||||||
|
# 로그: docker-compose logs -f
|
||||||
|
# ###################################################################
|
||||||
|
|
||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
x-common: &common
|
||||||
|
image: reg.firstgarden.co.kr/fgtools:latest
|
||||||
|
build:
|
||||||
|
context: .
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
env_file:
|
||||||
|
- .env
|
||||||
|
environment:
|
||||||
|
- TZ=Asia/Seoul
|
||||||
|
- PYTHONIOENCODING=utf-8
|
||||||
|
restart: unless-stopped
|
||||||
|
networks:
|
||||||
|
- fgtools-network
|
||||||
|
|
||||||
|
services:
|
||||||
|
# =================================================================
|
||||||
|
# Dashboard API - 대시보드 및 통계 API
|
||||||
|
# =================================================================
|
||||||
|
dashboard:
|
||||||
|
<<: *common
|
||||||
|
container_name: fgtools-dashboard
|
||||||
|
command: ["dashboard"]
|
||||||
|
ports:
|
||||||
|
- "5000:5000"
|
||||||
|
environment:
|
||||||
|
- FLASK_PORT=5000
|
||||||
|
- GUNICORN_WORKERS=2
|
||||||
|
volumes:
|
||||||
|
- ./logs:/app/logs
|
||||||
|
- ./data:/app/data
|
||||||
|
- ./conf:/app/conf:ro
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:5000/api/dashboard/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Weather API - 날씨 정보 API
|
||||||
|
# =================================================================
|
||||||
|
weather-api:
|
||||||
|
<<: *common
|
||||||
|
container_name: fgtools-weather
|
||||||
|
command: ["weather"]
|
||||||
|
ports:
|
||||||
|
- "5001:5001"
|
||||||
|
environment:
|
||||||
|
- FLASK_PORT=5001
|
||||||
|
- GUNICORN_WORKERS=2
|
||||||
|
volumes:
|
||||||
|
- ./logs:/app/logs
|
||||||
|
- ./data:/app/data
|
||||||
|
- ./conf:/app/conf:ro
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:5001/api/weather/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
# =================================================================
|
||||||
|
# Webhook Server - 웹훅 수신 서버 (Notion 등)
|
||||||
|
# =================================================================
|
||||||
|
webhook:
|
||||||
|
<<: *common
|
||||||
|
container_name: fgtools-webhook
|
||||||
|
command: ["webhook"]
|
||||||
|
ports:
|
||||||
|
- "5002:5002"
|
||||||
|
environment:
|
||||||
|
- FLASK_PORT=5002
|
||||||
|
- GUNICORN_WORKERS=2
|
||||||
|
volumes:
|
||||||
|
- ./logs:/app/logs
|
||||||
|
- ./data:/app/data
|
||||||
|
- ./conf:/app/conf:ro
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "curl", "-f", "http://localhost:5002/webhook/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
|
||||||
|
networks:
|
||||||
|
fgtools-network:
|
||||||
|
driver: bridge
|
||||||
52
docker-entrypoint.sh
Normal file
52
docker-entrypoint.sh
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ###################################################################
|
||||||
|
# docker-entrypoint.sh - FGTools 컨테이너 시작 스크립트
|
||||||
|
# ###################################################################
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# PYTHONPATH 설정
|
||||||
|
export PYTHONPATH=/app:$PYTHONPATH
|
||||||
|
|
||||||
|
# 서비스별 실행
|
||||||
|
case "$1" in
|
||||||
|
dashboard)
|
||||||
|
echo "[FGTools] Starting Dashboard API on port ${FLASK_PORT:-5000}..."
|
||||||
|
exec gunicorn \
|
||||||
|
--bind 0.0.0.0:${FLASK_PORT:-5000} \
|
||||||
|
--workers ${GUNICORN_WORKERS:-2} \
|
||||||
|
--timeout 120 \
|
||||||
|
--access-logfile - \
|
||||||
|
--error-logfile - \
|
||||||
|
"apps.dashboard.app:create_app()"
|
||||||
|
;;
|
||||||
|
weather)
|
||||||
|
echo "[FGTools] Starting Weather API on port ${FLASK_PORT:-5001}..."
|
||||||
|
exec gunicorn \
|
||||||
|
--bind 0.0.0.0:${FLASK_PORT:-5001} \
|
||||||
|
--workers ${GUNICORN_WORKERS:-2} \
|
||||||
|
--timeout 120 \
|
||||||
|
--access-logfile - \
|
||||||
|
--error-logfile - \
|
||||||
|
"apps.weather_api.app:create_app()"
|
||||||
|
;;
|
||||||
|
webhook)
|
||||||
|
echo "[FGTools] Starting Webhook Server on port ${FLASK_PORT:-5002}..."
|
||||||
|
exec gunicorn \
|
||||||
|
--bind 0.0.0.0:${FLASK_PORT:-5002} \
|
||||||
|
--workers ${GUNICORN_WORKERS:-2} \
|
||||||
|
--timeout 120 \
|
||||||
|
--access-logfile - \
|
||||||
|
--error-logfile - \
|
||||||
|
"apps.webhook.app:create_app()"
|
||||||
|
;;
|
||||||
|
shell)
|
||||||
|
echo "[FGTools] Starting interactive shell..."
|
||||||
|
exec /bin/bash
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "[FGTools] Unknown service: $1"
|
||||||
|
echo "Available services: dashboard, weather, webhook, shell"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
Reference in New Issue
Block a user