FastAPI через Docker не работает

У меня есть следующие два файла, но я не могу заставить сервер FastAPI работать через Docker.

Я использую команду docker build -t my_project . для его сборки и docker run -it -p 8080:8080 my_project для запуска сервера. Наконец, я использую следующую команду Curl для вызова API, но получаю следующую ошибку: curl: (56) Recv failure: Connection reset by peer.

curl -X POST "http://127.0.0.1:8080/predict/" -H "Content-Type: application/json" -d '{"image_sha": "example_sha"}'

Локальный запуск этого через Python работает отлично.

сервер.py

import base64
import io

from fastapi import FastAPI
from typing import Any
import uvicorn
from PIL import Image
import pydantic

class ImageModelInput(pydantic.BaseModel):
    image_sha: str
    
    def get_base64_encoded_image(self) -> str:
        return "dummy_base64_image"

    def decode_image(self) -> Image.Image:
        image_data = base64.b64decode(self.image_base64)
        return Image.open(io.BytesIO(image_data))
        
class ImageModelOutput(pydantic.BaseModel):
    attributes: list[str]

class ImageModel:
    def __init__(self, model: Any):
        self.model = model
        self.app = FastAPI()
        
        @self.app.post("/predict/", response_model=ImageModelOutput)
        async def predict(input: ImageModelInput):
            image = input.get_base64_encoded_image()
            prediction = self.model_predict(image)
            return ImageModelOutput(attributes=prediction)
        
        @self.app.get("/readyz")
        async def readyz():
            return {"status": "ready"}

    def model_predict(self, image: Image.Image) -> list[str]:
        # Replace this method with actual model prediction logic
        return ["dummy_attribute_1", "dummy_attribute_2"]

    def run(self, host: str = "127.0.0.1", port: int = 8080):
        uvicorn.run(self.app, host=host, port=port)

# Example usage
if __name__ == "__main__":
    # Replace with your actual model loading logic
    dummy_model = "Your_Model_Here"
    image_model = ImageModel(model=dummy_model)
    image_model.run()

Докерфайл:

FROM python:3.12.4-slim@sha256:2fba8e70a87bcc9f6edd20dda0a1d4adb32046d2acbca7361bc61da5a106a914

WORKDIR /app

RUN --mount=type=cache,target=/root/.cache/pip \
    pip install -U pip poetry wheel

RUN addgroup --system somebody && \
    adduser --system --home /app --ingroup somebody somebody && \
    chown -R somebody:somebody /app

USER somebody

COPY requirements.txt /app/requirements.txt
RUN pip install --no-cache-dir -r requirements.txt
COPY my_project /app/my_project

ENV PYTHONUNBUFFERED=1

EXPOSE 8080
CMD python3 cx_ai_lightbox/server.py

Вместо этого попробуйте использовать 0.0.0.0 для хоста uvicorn. Localhost / 127.0.0.1 будет доступен только внутри контейнера. У вас должен быть доступ с 127.0.0.1 сейчас.

InsertCheesyLine 24.06.2024 08:47
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
1
88
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вам не хватает следующей части в вашем файле докеров

# (change flask to what you use)
#     |||||
#     |||||             add this part
#     |||||          ~~~~~~~~  ~~~~~~~~~  
CMD ["flask", "run", "--host", "0.0.0.0"]

Без этого сопоставление IP-адресов не будет работать корректно. Вам также придется настроить часть host, так как в настоящее время она жестко запрограммирована в вашем файле Python.

ОП передает порт напрямую uvicorn, это не обязательно должен быть CMD

InsertCheesyLine 24.06.2024 08:48
Ответ принят как подходящий

Передача 127.0.0.1 в качестве хоста uvicorn делает его доступным только внутри контейнера.

Вместо этого просто замените его на 0.0.0.0. Теперь вы можете получить доступ к своей конечной точке по адресу http://127.0.0.1:8080/predict/

curl http://127.0.0.1:8080

{"detail":"Not Found"}

Другие вопросы по теме