首页 > 解决方案 > 使用 docker-compose 运行时无法让 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 应用服务起的傻名字。这里还有 Flask 应用程序的 Dockerfile。

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这两个服务时,没有问题。我可以访问烧瓶应用程序,并且可以通过 gRPC 通过 python 控制台将请求发送到 TensorFlow 服务服务。但是,当我尝试访问 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}]}"

标签: python-3.xdockerflasktensorflow-serving

解决方案


推荐阅读