Dev

YOLOv5 Custom Training : Docker to AWS EC2 deploy #3

너굴먹 2025. 6. 20. 13:40

웹캠 동작 확인

먼저 배포하기 전에 친구한테 웹캠이 있다고 해서 빌려서 모델 테스트를 해봤는데 스마트폰으로 꽃 사진들을 검색해서 인식시켜 봤다,
신기하게도 잘 인식하는 것을 확인 - 뿌듯하다


API 명세서

저번에 flask로 yolov5 모델을 API화 했는데 간단한 API 명세서를 작성해 봤다.

크게 3가지 기능[ 상태확인, 이미지요청, 이미지를 분석한 json 데이터요청 ]

ID 기능 요청방식 URL body response 설명
F1 서버 상태 확인 GET / 없음 JSON 서버 동작 여부 확인
F2 이미지 예측 POST /predict multipart/form-data, image 필드 image/jpeg 추론된 결과 이미지 반환
F3 이미지 예측 (JSON) POST /predict-json multipart/form-data, image 필드 JSON 클래스, 신뢰도, 바운딩 박스

요청 예시 (curl)

curl -X POST <http://localhost:5000/predict> \\
  -F image=@sample.jpg --output result.jpg
curl -X POST <http://localhost:5000/predict-json> \\
  -F image=@sample.jpg

백엔드 스프링 서버랑 프런트엔드 쪽 코드를 배포해 본 경험은 많았는데 

AI모델과 백엔드 서버를 같이 묶어서 도커 컨테이너화 한 다음 AWS에 배포해 본 적은 없어 여러 번 헤맸다..!


🌶️ Flask Code, (app.py) (2025-04-30)

import sys

from flask import Flask, request, jsonify, send_file
import sys
import os
import uuid
import torch
from pathlib import Path
from yolov5.detect import run

sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

app = Flask(__name__)

# 기본 설정
BASE_DIR = Path(__file__).resolve().parent.parent  # Hanamory/
MODEL_PATH = BASE_DIR / 'yolov5/runs/train/flower2_yolov5_640_b16_ep100/weights/best_linux.pt'
UPLOAD_DIR = Path(__file__).resolve().parent / 'static/uploads'
RESULT_DIR = Path(__file__).resolve().parent / 'static/detect'
IMGSZ = 640

# 디렉토리 미리 생성
UPLOAD_DIR.mkdir(parents=True, exist_ok=True)
RESULT_DIR.mkdir(parents=True, exist_ok=True)

@app.route('/', methods=['GET'])
def home():
    return jsonify({"message": "YOLOv5 Flask API is running"}), 200

@app.route('/predict', methods=['POST'])
def predict_image():
    if 'image' not in request.files:
        return jsonify({'error': '이미지가 필요합니다.'}), 400

    file = request.files['image']
    filename = f"{uuid.uuid4().hex}.jpg"
    input_path = UPLOAD_DIR / filename
    file.save(str(input_path))

    # YOLO 추론
    run(
        weights=str(MODEL_PATH),
        source=str(input_path),
        imgsz=(IMGSZ, IMGSZ),
        conf_thres=0.4,
        save_txt=False,
        save_conf=False,
        project=str(RESULT_DIR.parent),  # static/
        name='detect',
        exist_ok=True
    )

    result_path = RESULT_DIR / filename
    if not result_path.exists():
        return jsonify({'error': '예측 실패'}), 500

    return send_file(result_path, mimetype='image/jpeg')

@app.route('/predict-json', methods=['POST'])
def predict_json():
    if 'image' not in request.files:
        return jsonify({'error': '이미지가 필요합니다.'}), 400

    file = request.files['image']
    filename = f"{uuid.uuid4().hex}.jpg"
    input_path = UPLOAD_DIR / filename
    file.save(str(input_path))

    model = torch.hub.load('ultralytics/yolov5', 'custom', path=str(MODEL_PATH), force_reload=True)
    model.to('cpu')  # CPU 추론
    results = model(str(input_path))

    predictions = []
    for *box, conf, cls in results.xyxy[0]:
        predictions.append({
            'class': model.names[int(cls)],
            'confidence': round(float(conf), 4),
            'bbox': [round(float(x), 2) for x in box]
        })

    return jsonify({'predictions': predictions})

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

🐳 Dockerfile

FROM python:3.8-slim

RUN apt-get update && apt-get install -y git ffmpeg libgl1 wget

WORKDIR /app

# YOLOv5 코드 복사
COPY yolov5 /app/yolov5
COPY yolov5/requirements.txt /app/yolov5/requirements.txt

# 종속성 설치
RUN pip install --upgrade pip
RUN pip install -r /app/yolov5/requirements.tx
RUN pip install flask

# Flask 백엔드 복사
COPY backend /app/backend

# PYTHONPATH 등록
ENV PYTHONPATH="${PYTHONPATH}:/app"

CMD ["python", "backend/app.py"]

# docker build -t yolov5-flask-api .
# docker run -p 5000:5000 yolov5-flask-api

 

 

도커 이미지

CPU 및 GPU 환경, 볼륨 마운트, 디스플레이 서버 사용에 대한 단계별 지침을 통해 Docker 컨테이너에서 YOLOv5 설정하고 실행하는 방법을 알아보세요.

docs.ultralytics.com

yolo 공식문서를 참고해서 dockerfile을 만들어줬고 빌드까지 해줬다.

pytorch같이 용량이 큰 라이브러리까지 설치하면서 빌드하다 보니 도커 이미지 만드는데도 시간이 5분? 조금 더 걸린 것 같다.

근데 에러가 났는데.. 내 데스크톱 개발환경이 windows 기반으로 yolo모델을 설정해 둬서 그런 듯했다. 여기저기 찾아보다가 yolo 공식 깃허브에서 비슷한 사례를 통해 해결할 수 있었다!! 


⚙️ TroubleShooting

  • 문제: 윈도에서 학습하고 빌드한 모델을 linux 기반 Docker에 올리려고 하니 WindowsPath 관련 error 발생..
    from pathlib import Path
    
    plt = platform.system()
    if plt == 'Windows':
        pathlib.PosixPath = pathlib.WindowsPath
    pathlib.WindowsPath = pathlib.PosixPath
    https://github.com/ultralytics/yolov5/issues/12911
  • 해결: detect.py에 pathlib.PosixPath = pathlib.WindowsPath 우회코드를 삽입해 windows환경 파일경로와 linux환경 파일경로를 핸들링

이제 AWS 프리티어 계정을 만들고 EC2 인스턴스를 만들어준다!! 보안그룹이나 생성 디테일은 나중에 aws 전용으로 글을 하나 정리해 두는 게 좋겠다.

이제 ssh로 인스턴스에 접속해서 dockerhub에 도커 이미지를 push 하고 ec2 인스턴스에서 pull로 가져온다

# 1. 패키지 업데이트
sudo apt update

# 2. Docker 설치
sudo apt install docker.io -y

# 3. Docker 실행 권한 부여
sudo usermod -aG docker $USER

# 4. 설정 적용
newgrp docker
**로컬에서 도커 이미지 태그 설정**
> docker tag yolov5-flask-api neogul02/yolov5-flask-api

**Docker Hub에 push(로그인 필요):**
> docker login
> docker push neogul02/yolov5-flask-api

**EC2에서 Pull** 
> docker pull neogul02/yolov5-flask-api
> docker run -p 5000:5000 neogul02/yolov5-flask-api

docker push (Local)
docker pull (ec2)


배포 테스트 ( http://[EC2 퍼블릭 IP]:5000 )

임시 퍼블릭 ip 포트로 접속해 보면 성공적으로 배포가 된 걸 볼 수 있다!!

이미지 처리도 잘 될까?


참고자료들

 

 

도커 이미지

CPU 및 GPU 환경, 볼륨 마운트, 디스플레이 서버 사용에 대한 단계별 지침을 통해 Docker 컨테이너에서 YOLOv5 설정하고 실행하는 방법을 알아보세요.

docs.ultralytics.com

 

 

Troubleshoot and diagnose

Understand how to diagnose and troubleshoot Docker Desktop, and how to check the logs.

docs.docker.com

 

 

Docker | IntelliJ IDEA

 

www.jetbrains.com

 

 

[AWS] EC2 인스턴스에 Docker 컨테이너 배포하기

이전에 Google Cloud Platform (GCP)를 이용하여 Docker 컨테이너를 배포하는 방법을 포스팅한 적 있다.이번에는 AWS를 사용하여 배포하는 방법을 살펴보도록 하자. AWS 인스턴스에, Docker 컨테이너를 실행

sjh9708.tistory.com

 

 

[INFRA] AWS EC2 프리티어 인스턴스 생성하기

AWS (Amazon Web Services) AWS는 Amazon이 제공하는 클라우드 컴퓨팅 플랫폼 및 인프라 서비스 모음이다. 2006년에 시작된 AWS는 가상 컴퓨터, 스토리지, 데이터베이스, 네트워킹, 분석, 머신 러닝, 모바일,

olrlobt.tistory.com