Docker容器中Uvicorn进程已运行但未监听8001端口求助
问题:Uvicorn进程已启动但未监听指定端口
现象详情
1. 容器内进程状态
root@chat-server-service-594dc96485-rpphl:~/chat-server# ps aux USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 0.2 97084 17560 ? Ssl 17:19 0:01 python3 -m uvicorn main:app --port 8001 --host 0.0.0.0 --reload root 8 0.0 0.0 12224 5920 ? S 17:19 0:00 /usr/local/bin/python3 -c from multiprocessing.resource_tracker import main;main(4) root 9 0.0 0.0 0 0 ? Z 17:19 0:01 [python3] <defunct> root 14 0.0 0.0 4292 1504 pts/0 Ss 17:47 0:00 bash root 65 0.0 0.0 6752 1536 pts/0 R+ 17:54 0:00 ps aux
可见PID为1的进程是Uvicorn启动命令,但存在僵尸进程[python3] <defunct>。
2. 端口连接测试失败
root@chat-server-service-594dc96485-rpphl:~/chat-server# curl http://0.0.0.0:8001 curl: (7) Failed to connect to 0.0.0.0 port 8001: Connection refused
3. 手动执行命令正常运行
root@chat-server-service-594dc96485-rpphl:~/chat-server# python3 -m uvicorn main:app --port 8001 --host 0.0.0.0 --reload INFO: Will watch for changes in these directories: ['/root/chat-server'] INFO: Uvicorn running on http://0.0.0.0:8001 (Press CTRL+C to quit) INFO: Started reloader process [58] using WatchFiles ^CINFO: Stopping reloader process [58]
4. 端口监听检查
root@chat-server-service-6f59d77848-wcj6c:~/chat-server# ps aux|grep python root 1 0.1 0.2 97084 17784 ? Ssl 17:27 0:00 python3 -m uvicorn main:app --port 8001 --host 0.0.0.0 --reload root 7 0.0 0.0 12224 6852 ? S 17:27 0:00 /usr/local/bin/python3 -c from multiprocessing.resource_tracker import main;main(4) root 8 0.9 0.0 0 0 ? Z 17:27 0:02 [python3] <defunct> root 27 0.0 0.0 3236 720 pts/0 S+ 17:31 0:00 grep python root@chat-server-service-6f59d77848-wcj6c:~/chat-server# lsof -i:8001 # 无输出,说明无进程监听8001端口
当前使用的Dockerfile
FROM python:3.8 LABEL example (example@gmail.com) ENV LANG=en_US.UTF-8 \ LC_ALL=en_US.UTF-8 \ TZ=Asia/Shanghai RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \ && echo $TZ > /etc/timezone \ && mkdir -p /root/chat-server ADD . /root/chat-server/ EXPOSE 8001 RUN pip3 install -r /root/chat-server/requirements.txt WORKDIR /root/chat-server/ ENTRYPOINT exec python3 -m uvicorn main:app --port 8001 --host 0.0.0.0 --reload
解决方法
核心原因
Uvicorn的--reload模式会启动两个进程:负责监听文件变化的reloader主进程,以及实际处理请求的worker子进程。当该命令作为Docker容器的PID1进程运行时,子进程退出后会变成僵尸进程,且reloader无法正确重启worker,导致无进程监听端口。而手动执行命令时,进程不是PID1,信号处理和进程管理逻辑正常,因此能正常运行。
方案1:生产环境禁用热重载(推荐)
直接移除--reload参数,这是生产环境的标准做法,可避免不必要的进程开销和稳定性问题。修改Dockerfile的ENTRYPOINT:
WORKDIR /root/chat-server/ ENTRYPOINT exec python3 -m uvicorn main:app --port 8001 --host 0.0.0.0
重新构建镜像后运行,即可正常监听8001端口。
方案2:开发环境需热重载的处理方式
如果开发环境必须使用热重载,可通过以下方式修复:
- 使用
tini管理进程:
在Dockerfile中安装tini,让它作为PID1进程管理Uvicorn,确保信号正确传递给子进程:FROM python:3.8 LABEL example (example@gmail.com) ENV LANG=en_US.UTF-8 \ LC_ALL=en_US.UTF-8 \ TZ=Asia/Shanghai # 安装tini RUN apt-get update && apt-get install -y --no-install-recommends tini \ && ln -snf /usr/share/zoneinfo/$TZ /etc/localtime \ && echo $TZ > /etc/timezone \ && mkdir -p /root/chat-server ADD . /root/chat-server/ EXPOSE 8001 RUN pip3 install -r /root/chat-server/requirements.txt WORKDIR /root/chat-server/ # 用tini启动命令 ENTRYPOINT ["tini", "--", "python3", "-m", "uvicorn", "main:app", "--port", "8001", "--host", "0.0.0.0", "--reload"] - 手动执行启动命令:
不将带--reload的命令写入Dockerfile的ENTRYPOINT,而是启动容器后进入终端手动执行,或通过docker exec运行,此时进程不是PID1,可正常工作。
内容的提问来源于stack exchange,提问作者spark
相关产品推荐
相关产品推荐

