如何将 docker 快速 api 与 mqtt 代理连接?

How to connect the docker fast api with mqtt broker?

没有 docker,我可以将我的 fastapi 应用程序与 mqtt 代理连接。但是,对于 docker,我无法将我的 fastapi 应用程序与 docker mqtt 代理连接。我收到错误 -

{"log":"    ', '.join(str(exc) for exc in exceptions)))\n","stream":"stderr","time":"2022-02-21T04:42:21.137558005Z"}
{"log":"OSError: Multiple exceptions: [Errno 111] Connect call failed ('127.0.0.1', 1883), [Errno 99] Cannot assign requested address\n","stream":"stderr","time":"2022-02-21T04:42:21.137562299Z"}
{"log":"\n","stream":"stderr","time":"2022-02-21T04:42:21.137566492Z"}
{"log":"ERROR:    Application startup failed. Exiting.\n","stream":"stderr","time":"2022-02-21T04:42:21.137570669Z"}

这是我的main.app

from fastapi import FastAPI
from fastapi_mqtt import FastMQTT, MQTTConfig
from pydantic import BaseModel
from ipaddress import IPv4Address
import jsonpickle

app = FastAPI()


class Nmap(BaseModel):
    host: IPv4Address
    portRange: str

    class Config:
        schema_extra = {
            "example" : {
                "host": "10.0.2.15",
                 "portRange": "22-80",
                 "description": "Scan the port from 22 to 80 of the ip address 10.0.2.15"
            }
        }



mqtt_config = MQTTConfig()

mqtt = FastMQTT(config=mqtt_config)

mqtt.init_app(app)

@mqtt.on_connect()
def connect(client, flags, rc, properties):
    mqtt.client.subscribe("/mqtt/toModel/#") # subscribing mqtt topic wildcard- multi-level
    print("connected: ", client, flags, rc, properties)

@mqtt.on_message()
async def message(client, topic, payload, qos, properties):
    print("received message: ", topic, jsonpickle.decode(payload.decode()), qos, properties)
    return 0 


@mqtt.on_disconnect()
def disconnect(client, packet, exc=None):
    print("Disconnected")

@mqtt.on_subscribe()
def subscribe(client, mid, qos, properties):
    print("subscribed", client, mid, qos, properties)

@app.get("/")
async def func():
    mqtt.client.publish("/mqtt", "Hello from fastApi") 
    return {"result": True, "message": "Published"}

@app.post("/scan/{host}")
async def scan_host_port(nmap_details : Nmap):
    results = {"got_val" : nmap_details}
    print(type(nmap_details))
    mqtt.client.publish("/mqtt/fromModel/nmap", jsonpickle.encode(nmap_details)) 
    return results

这是我的应用 docker 文件 -

FROM python:3.7

WORKDIR /code 


COPY ./requirements.txt /code/requirements.txt


RUN pip install -r /code/requirements.txt


COPY ./app /code/app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]

对于 MQTT,我使用 -

docker-compose.yml

version: "3"
services:
 mqtt:
      image: toke/mosquitto
      network_mode: bridge
      container_name: mqtt
      expose:
        - 1883
      ports:
        - 1883:1883
      restart: unless-stopped

我确定这与我的 docker 有关,但我不知道如何部署 it.My 我的理解是 docker 旨在 运行 单个过程。因此,一个过程用于代理,另一个 docker 简单地 运行 我的快速 api 另一个 docker 用于 nginx

127.0.0.1 始终指向当前代码绑定到的 TCP/IP 堆栈。

每个 Docker 容器都有自己的 TCP/IP 堆栈。因此,如果您尝试从 python 容器连接到 127.0.0.1,则在它自己的 TCP/IP 堆栈的端口 1883 上将没有 MQTT 代理 运行。

你应该让两个容器在同一个 docker compose 文件中使用相同的网络(如果需要,容器可以绑定到多个网络)然后你可以用代理的三个服务名称替换 IP 地址例如mqtt

version: '3.5'

services:
 mqtt:
      image: toke/mosquitto
      container_name: mqtt
      expose:
        - 1883
      ports:
        - 1883:1883
      restart: unless-stopped

      networks:
        - my_network

 fast:
     container_name: fast
     expose:
        - 8000
     networks:
       - my_network
    
     ports:
        - 8000:8000
     restart: unless-stopped
     build:
      context: .
      dockerfile: Dockerfile

     depends_on:
        - mqtt

networks:
  my_network:
    driver: bridge