You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署FastAPI时如何限制仅同网络serviceA容器可访问serviceB

问题原因

你对TrustedHostMiddleware的作用存在误解,这是配置不生效的核心原因:

  • TrustedHostMiddleware的校验对象是HTTP请求头中的Host字段,该字段标识的是请求要访问的目标主机地址,而非请求的来源地址。你从serviceA向serviceB发请求时,Host字段值为serviceB的服务名/IP,所以你配置允许的Host为serviceA相关值时,所有请求都会命中拦截规则。
  • 你的配置写法存在错误:Host字段本身不携带http://这类协议前缀,哪怕是按该中间件的正确用法,填写带协议的地址也属于无效配置。
解决方案

推荐优先选择Docker网络层面的控制方案,无需修改业务代码,安全性更高:

方案1:Docker网络隔离(推荐)

利用Docker的bridge网络实现访问限制,公网完全无法触达serviceB,仅同网络内的serviceA可访问:

  1. 先创建专属内部网络:
docker network create --driver bridge internal-only
  1. 启动容器时,仅给serviceA配置公网端口映射,serviceB不配置任何端口映射,两个服务都接入上述内部网络即可。
    如果使用docker-compose部署,参考配置如下:
version: '3.8'
services:
  serviceA:
    build: ./serviceA
    ports:
      - "8000:8000" # 仅serviceA暴露公网端口
    networks:
      - internal-net
  serviceB:
    build: ./serviceB
    # 不配置ports字段,公网无访问入口
    networks:
      - internal-net
networks:
  internal-net:
    driver: bridge

方案2:代码层来源校验

如果确实需要将serviceB暴露到公网,仅允许serviceA的请求访问,可以自定义中间件校验请求来源IP:

from fastapi import FastAPI, Request, HTTPException
import socket

# 预解析serviceA的容器IP列表,Docker内部网络中serviceA的IP变更时可以定时刷新该列表
ALLOWED_CLIENT_IPS = set(socket.gethostbyname_ex('serviceA')[2])

async def check_origin_middleware(request: Request, call_next):
    client_ip = request.client.host
    if client_ip not in ALLOWED_CLIENT_IPS:
        raise HTTPException(status_code=403, detail="Forbidden")
    return await call_next(request)

def get_application():
    app = FastAPI(title=server_config.PROJECT_NAME, version=server_config.VERSION)
    # 移除原来的TrustedHostMiddleware配置,替换为自定义的来源校验中间件
    app.middleware("http")(check_origin_middleware)
    return app

app = get_application()

如果serviceA有固定公网出口IP,也可以直接将ALLOWED_CLIENT_IPS配置为固定的公网IP值。

内容的提问来源于stack exchange,提问作者Pepo。

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 09:54:04