如何在公开端口的 docker 容器中运行 uvicorn?

San*_*333 1 python docker fastapi uvicorn

我正在 windows/ubuntu 中的 docker 容器内开发 fastapi (代码如下)。当我通过在终端中运行python -m uvicorn app:app --reload测试容器外部的应用程序时,然后导航到127.0.0.1:8000/home一切正常:

{
  Data: "Test"
}
Run Code Online (Sandbox Code Playgroud)

但是,当我docker-compose up时,我既无法在容器中运行python -m uvicorn app:app --reload(由于端口已被使用),也无法在浏览器中看到任何返回的内容。我尝试过 127.0.0.1:8000/home、host.docker.internal:8000/home 和 localhost:8000/home 并且我总是收到:

{
   detail: "Not Found"
}
Run Code Online (Sandbox Code Playgroud)

我缺少哪一步?

Dockerfile:

FROM python:3.8-slim

EXPOSE 8000

ENV PYTHONDONTWRITEBYTECODE=1

ENV PYTHONUNBUFFERED=1

COPY requirements.txt .
RUN python -m pip install -r requirements.txt

WORKDIR /app
COPY . /app

RUN adduser -u nnnn --disabled-password --gecos "" appuser && chown -R appuser /app
USER appuser

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "-k", "uvicorn.workers.UvicornWorker", "app:app"]
Run Code Online (Sandbox Code Playgroud)

Docker 组合:

version: '3.9'

services:
  fastapitest:
    image: fastapitest
    build:
      context: .
      dockerfile: ./Dockerfile
    ports:
      - 8000:8000
    extra_hosts:
      - "host.docker.internal:host-gateway"
Run Code Online (Sandbox Code Playgroud)

应用程序.py:

from fastapi import FastAPI

app = FastAPI()

@app.get("/home") #must be one line above the function fro the route
def home():
    return {"Data": "Test"}

if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000)
Run Code Online (Sandbox Code Playgroud)

M.O*_*.O. 6

这里的问题是,当您指定host="127.0.0.1"to时uvicorn,这意味着您只能从同一台计算机访问该端口。现在,当您在 docker 外部运行时,您位于同一台机器上,因此一切正常。但由于 docker 容器(至少在某种程度上)是一台不同的计算机,因此您需要告诉它也允许来自容器外部的连接。为此,请切换到host="0.0.0.0",然后您应该能够访问 上的 dockerized API http://localhost:8000