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

FastAPI调用Unix Socket获取本地Docker容器列表失败求助

错误原因及解决方法

核心错误原因

  1. httpx不支持直接使用http+unix://协议:你代码里用的http+unix://%2Fvar%2Frun%2Fdocker.sock格式,httpx默认无法识别,直接触发UnsupportedProtocol错误。
  2. FastAPI容器未挂载宿主机Docker Socket:即便解决协议问题,容器内部默认没有访问宿主机/var/run/docker.sock的权限,无法调用Docker API。
  3. 代码与配置不统一:Dockerfile里定义了DOCKER_API_URL环境变量,但代码里硬编码了Socket路径,没有利用该变量。

解决方法(推荐方案:Unix Socket挂载,安全可靠)

1. 修改main.py代码,适配httpx访问Unix Socket

httpx需要通过UnixSocketTransport来支持Unix Socket访问,调整代码如下:

from fastapi import FastAPI, HTTPException
from httpx import ConnectError, AsyncClient, UnixSocketTransport
import logging
import os

app = FastAPI()

# 优先从环境变量获取,默认值为宿主机Socket路径
DOCKER_SOCKET_PATH = os.getenv("DOCKER_SOCKET_PATH", "/var/run/docker.sock")
DOCKER_API_VERSION = "v1.41"

async def get_containers():
    # 指定UnixSocketTransport访问Docker API
    async with AsyncClient(transport=UnixSocketTransport(DOCKER_SOCKET_PATH)) as client:
        response = await client.get(f"http://localhost/{DOCKER_API_VERSION}/containers/json")
        response.raise_for_status()
        return response.json()

@app.get("/containers")
async def list_containers():
    try:
        containers = await get_containers()
        return containers
    except ConnectError as e:
        logging.error(f"连接Docker API失败: {str(e)}")
        raise HTTPException(status_code=500, detail="内部服务器错误")

if __name__ == '__main__':
    import uvicorn
    uvicorn.run(app, host="127.0.0.1", port=8000, reload=True)

2. 调整Docker运行命令,挂载宿主机Socket

运行FastAPI容器时,需要将宿主机的/var/run/docker.sock挂载到容器内相同路径,同时确保容器有访问权限:

docker run -d -p 8000:8000 -v /var/run/docker.sock:/var/run/docker.sock your-image-name

注意:如果容器内用户非root,可能需要添加--user $(id -u):$(id -g)或者调整Socket权限,但测试阶段可以直接用root运行。

3. 可选:更新Dockerfile(配置统一优化)

可以在Dockerfile里添加环境变量默认值,保持配置统一:

# 原内容不变,新增环境变量
ENV DOCKER_SOCKET_PATH /var/run/docker.sock

备选方案:TCP连接(仅测试用,不安全)

如果不想挂载Socket,可通过TCP访问宿主机Docker API(需宿主机开启TCP端口,不推荐生产环境):

1. 宿主机开启Docker TCP端口

修改Docker配置文件(如/etc/docker/daemon.json):

{
  "hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
}

重启Docker服务:systemctl restart docker

2. 修改main.py使用环境变量

# 替换原DOCKER_API_UNIX_SOCKET定义
DOCKER_API_URL = os.getenv("DOCKER_API_URL", "http://host.docker.internal:2375")

async def get_containers():
    async with AsyncClient() as client:
        response = await client.get(f"{DOCKER_API_URL}/v1.41/containers/json")
        response.raise_for_status()
        return response.json()

3. 运行容器

直接运行即可,无需挂载Socket:

docker run -d -p 8000:8000 your-image-name

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 10:57:24