Multi staging / Poetry

임정민·2024년 11월 11일

메모장

목록 보기
19/33
post-thumbnail
# 프로젝트 구조
iris_classifier/
├── Dockerfile           # Docker 빌드 파일
├── pyproject.toml       # Poetry 프로젝트 설정 파일
├── poetry.lock         # Poetry 의존성 잠금 파일
├── src/
│   ├── main.py         # 메인 애플리케이션 코드
│   └── model.joblib    # 저장된 모델 파일
└── README.md           # 프로젝트 설명 파일

# main.py
from flask import Flask, request, jsonify
import joblib
import numpy as np
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier

app = Flask(__name__)

# 모델 학습 함수
def train_model():
    # iris 데이터셋 로드
    iris = load_iris()
    # RandomForest 모델 학습
    model = RandomForestClassifier(n_estimators=100)
    model.fit(iris.data, iris.target)
    # 모델 저장
    joblib.dump(model, 'model.joblib')
    return model

# 저장된 모델 로드 또는 새로 학습
try:
    model = joblib.load('model.joblib')
except:
    model = train_model()

@app.route('/predict', methods=['POST'])
def predict():
    # JSON 요청 데이터 받기
    data = request.json
    
    # 입력 데이터를 numpy 배열로 변환
    features = np.array(data['features']).reshape(1, -1)
    
    # 예측 수행
    prediction = model.predict(features)
    
    # 결과 반환
    return jsonify({
        'prediction': int(prediction[0]),
        'class_name': iris.target_names[prediction[0]]
    })

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080)
# pyproject.toml
[tool.poetry]
name = "iris-classifier"              # 프로젝트 이름
version = "0.1.0"                     # 프로젝트 버전
description = "Iris classification service"  # 프로젝트 설명
authors = ["Your Name <your@email.com>"]    # 작성자 정보

[tool.poetry.dependencies]
python = "^3.9"                       # Python 버전 요구사항
flask = "^2.0.1"                      # Web 서버 프레임워크
scikit-learn = "^1.0.2"              # 머신러닝 라이브러리
numpy = "^1.21.0"                     # 수치 계산 라이브러리
joblib = "^1.1.0"                     # 모델 저장/로드 라이브러리

[build-system]
requires = ["poetry-core>=1.0.0"]     # 빌드 시스템 요구사항
build-backend = "poetry.core.masonry.api"  # 빌드 백엔드 설정
# Dockerfile
# 첫 번째 스테이지: 빌더 이미지
FROM python:3.9-slim as builder

# Poetry 설치
ENV POETRY_HOME=/opt/poetry
ENV POETRY_VERSION=1.7.1
RUN python3 -m pip install poetry==${POETRY_VERSION}

# 작업 디렉토리 설정
WORKDIR /app

# Poetry 설정 파일 복사
COPY pyproject.toml poetry.lock ./

# Poetry를 사용하여 의존성 설치
RUN poetry config virtualenvs.create false \
    && poetry install --no-interaction --no-ansi

# 소스 코드 복사
COPY src/ ./src/

# 두 번째 스테이지: 최종 이미지
FROM python:3.9-slim

# 작업 디렉토리 설정
WORKDIR /app

# 빌더에서 필요한 파일들만 복사
COPY --from=builder /usr/local/lib/python3.9/site-packages/ /usr/local/lib/python3.9/site-packages/
COPY --from=builder /app/src/ ./src/

# 비root 사용자 생성 및 전환
RUN useradd -m appuser && chown -R appuser /app
USER appuser

# 서비스 포트 설정
EXPOSE 8080

# 애플리케이션 실행
CMD ["python", "src/main.py"]
# Poetry 설치
curl -sSL https://install.python-poetry.org | python3 -

# 새 프로젝트 생성
poetry new iris-classifier

# 프로젝트 디렉토리로 이동
cd iris-classifier

# 의존성 추가
poetry add flask scikit-learn numpy joblib

# 의존성 설치
poetry install

# 가상환경에서 실행
poetry run python src/main.py
# Docker 이미지 빌드
docker build -t iris-classifier .

# Docker 컨테이너 실행
docker run -p 8080:8080 iris-classifier
# 예측 요청 예시
curl -X POST http://localhost:8080/predict \
-H "Content-Type: application/json" \
-d '{"features": [5.1, 3.5, 1.4, 0.2]}'

# 예상 응답
{"prediction": 0, "class_name": "setosa"}
# pip.conf 설정이 이렇다면:
[global]
index-url = https://your-company-pypi.com/simple
trusted-host = your-company-pypi.com
find-links = https://your-company-packages.com/links

# poetry config.toml은 이렇게 됩니다:
[repositories]
company = "https://your-company-pypi.com/simple"

[certificates.company]
cert = false

# pyproject.toml은 이렇게 됩니다:
[[tool.poetry.source]]
name = "company"
url = "https://your-company-pypi.com/simple"
default = true

[[tool.poetry.source]]
name = "package-links"
url = "https://your-company-packages.com/links"
# config.toml
[certificates.custom]
cert = "/path/to/your/certificate.pem"  # 실제 인증서 경로
curl -X POST http://localhost:8080/predict \
-H "Content-Type: application/json" \
-d '{"features": [5.1, 3.5, 1.4, 0.2]}'
profile
https://github.com/min731

0개의 댓글