Не удалось заставить приложение Flask взаимодействовать с сервировкой Tensorflow при работе с docker-compose

#python-3.x #docker #flask #tensorflow-serving

Вопрос:

У меня есть очень простое приложение Flask, и я обучил модель делать выводы на изображениях, поэтому я хочу иметь возможность запускать их оба одновременно через docker-compose. Вот как docker-compose.yml выглядит мой файл

 version: "2"
services:
  molo:
    build:
      context: ./
      dockerfile: molo/Dockerfile
    ports:
      - 8003:8003
  tensorflow-serving:
    image: tensorflow/serving
    ports:
      - 8500:8500
      - 8501:8501
    volumes:
      - './models:/models'
    command:
      - '--model_config_file=/models/models.config'
      - '--model_config_file_poll_wait_seconds=60'
      - '--allow_version_labels_for_unavailable_models=true'
 

molo это глупое название, которое я дал сервису приложений Flask. Также здесь находится файл Dockerfile для приложения Flask.

 FROM python:3.8-slim-buster

COPY ./molo/ /molo
COPY ./requirements.txt requirements.txt
COPY ./utilities /utilities

RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install -r requirements.txt
RUN python3 -m pip install utilities/

ENV FLASK_DEBUG=False
EXPOSE 8003

RUN ["chmod", " x", "/molo/entrypoint.sh"]
ENTRYPOINT ["/molo/entrypoint.sh"]
 

Вот в чем дело. Когда я запускаю docker-compose up --build обе службы, они запускаются без проблем. Я могу получить доступ к приложению flask и отправлять запросы через gRPC в службу обслуживания TensorFlow через консоль python. Однако, когда я пытаюсь попасть в конечную точку в приложении Flask, которое должно делать то же самое, что я делаю в консоли, я получаю кучу InactiveRPC ошибок и не могу понять, почему это не сработает. Я предполагаю, что, возможно, я указываю неправильный адрес, но это всего лишь предположение.

Вот содержимое приложения Flask (на данный момент это всего один файл).

 import os
import grpc
import simplejson as json

from dotenv import load_dotenv
from flask import Flask
from tensorflow_serving.apis import predict_pb2, get_model_metadata_pb2, prediction_service_pb2_grpc
from tensorflow_serving.apis.model_pb2 import ModelSpec
from google.protobuf.json_format import MessageToJson

from utilities.route_decorators import status_code_decorator

load_dotenv()
app = Flask(__name__)
MODEL_URI = "0.0.0.0:8500"


@app.route("/", methods=['GET'])
@status_code_decorator
def home():
    return "Welcome to Molo!"


@app.route("/molo/info/<model_name>", defaults={"model_name": "dense_net"}, methods=["GET"])
@status_code_decorator
def molo_info(
        model_name: str
):
    channel = grpc.insecure_channel(MODEL_URI)
    stub = prediction_service_pb2_grpc.PredictionServiceStub(channel)
    model_spec = ModelSpec(name=model_name, signature_name="serving_default")
    request = get_model_metadata_pb2.GetModelMetadataRequest(model_spec=model_spec)
    request.metadata_field.append("signature_def")

    result = stub.GetModelMetadata(request, 5.0)
    metadata = json.loads(MessageToJson(result))

    return metadata


@app.route("/molo/predict", methods=["GET"])
@status_code_decorator
def molo_predict():
    return {"prediction": "some label"}


if __name__ == "__main__":
    app.run(
        host=os.environ.get("FLASK_HOST", "0.0.0.0"),
        port=os.environ.get("FLASK_PORT", 8003),
        debug=os.environ.get("FLASK_DEBUG", True)
    )
 

Если кто-нибудь испытывал что-то подобное или, возможно, знает, что я делаю не так, я был бы очень благодарен, так как я провел целый день, вероятно, просто пытаясь понять это.

Редактировать

Вот пример ошибки, которую я получаю.

 grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
molo_1                |         status = StatusCode.UNAVAILABLE
molo_1                |         details = "failed to connect to all addresses"
molo_1                |         debug_error_string = "{"created":"@1621306525.139840351","description":"Failed to pick subchannel","file":"src/core/ext/filters/client_channel/client_channel.cc","file_line":4133,"referenced_errors":[{"created":"@1621306525.139835546","description":"failed to connect to all addresses","file":"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc","file_line":397,"grpc_status":14}]}"
 

Комментарии:

1. Когда вы устанавливаете MODEL_URI='0.0.0.0:8500' , вы говорите своему приложению попытаться подключиться к «везде», чтобы найти сервер модели; на самом деле это не имеет смысла. Вы читали такие материалы, как Создание сетей в Compose , в документации Docker, в которой описывается, какие имена хостов необходимы для подключения между контейнерами?