Docker容器内运行FastAPI接口单元测试请求无响应问题排查
问题根因及解决方案
1. 核心问题:FastAPI服务未在容器运行阶段启动
- 原
toto/fastapi:1.0.0镜像默认启动命令是启动FastAPI服务,但你编写的Dockerfile里最后生效的CMD只有CMD python3 /home/ubuntu/script.py,完全没有启动FastAPI的逻辑,容器运行时仅执行测试脚本,接口根本没启动,自然请求不到。 - 修复方法:需要同时启动FastAPI服务和测试脚本,最简单的方案是把启动逻辑整合到CMD指令中,先后台启动FastAPI,再运行测试脚本。
2. Dockerfile语法&逻辑错误
- Dockerfile中多个CMD指令仅最后一个生效,你前面写的
CMD ["Bash"]全部无效,可直接删除。 RUN python3 /home/ubuntu/script.py &是构建阶段执行的命令,构建完成后进程就会终止,不会保留到容器运行阶段,可删除。- ENV定义语法错误,
ENV address = '0.0.0.0'等号两边不能有空格,正确写法是ENV address=0.0.0.0、ENV port=8000。 - ADD和COPY指令重复了,保留一个COPY即可:
COPY script.py /home/ubuntu/script.py。
3. 测试脚本逻辑错误
- URL字符串没有占位符,你写的
'http://0.0.0.0:8000/permissions'.format(...)完全无效,format的参数没有地方填充,想要用变量的话改成'http://{address}:{port}/permissions'.format(address=api_address, port=api_port)。 - 导入错误:你写的是
from time import sleep,但后面调用了time.sleep(5),会抛出NameError异常直接进入捕获逻辑,改成直接调用sleep(5)即可。 - 请求异常捕获太宽泛,建议打印异常信息方便排查,比如
except Exception as e: print(e)。
最终修复后的文件参考
修复后的Dockerfile
FROM toto/fastapi:1.0.0 # 定义环境变量 ENV address=0.0.0.0 ENV port=8000 # 复制测试脚本 COPY script.py /home/ubuntu/script.py WORKDIR /home/ubuntu # 启动命令:先后台启动FastAPI,再跑测试脚本 # 注:如果原镜像FastAPI默认启动命令不是uvicorn,可执行docker inspect toto/fastapi:1.0.0查看原Cmd配置替换即可 CMD ["sh", "-c", "uvicorn main:app --host $address --port $port & python3 /home/ubuntu/script.py"]
修复后的测试脚本关键部分
import os import requests import json from requests.adapters import HTTPAdapter from requests.packages.urllib3.util.retry import Retry from time import sleep api_port = os.environ.get('port', '8000') print("api_port",api_port) api_address = os.environ.get('address', '0.0.0.0') print("api_address",api_address) pwd = os.environ.get('PWD') print ( 'le path actuel ssssssssss',pwd) # requête authentication r = '' while r == '': try: # 补全URL占位符 url = f'http://{api_address}:{api_port}/permissions' r = requests.get(url=url,params= {'username': 'XX','password': '****'}) print("request rrrrrrrr",r) break except Exception as e: print("Connection refused by the server, error: ", e) print("Let me sleep for 5 seconds") print("ZZzzzz...") print("r is rrrrrrrrr ",r) # 直接调用sleep无需加time前缀 sleep(5) print("Was a nice sleep, now let me continue...") continue
构建运行验证
# 重新构建镜像 docker build -t toto_image_test1:latest . # 运行容器 docker run -d toto_image_test1:latest # 查看容器日志确认运行情况 docker logs <容器ID>
内容的提问来源于stack exchange,提问作者sarra
相关产品推荐
相关产品推荐

