构建Dockerfile时uvicorn运行导致镜像构建卡住的解决方法
问题根因
构建卡死的核心原因是你把uvicorn启动命令写在了RUN指令里。Docker镜像构建阶段,每一条RUN都会启动临时容器执行对应命令,必须等命令执行的进程完全退出,才会提交当前层进入下一个构建步骤。uvicorn启动后是常驻前台的服务进程,不会主动退出,构建流程自然会无限挂起。
修复方案
把启动uvicorn的命令从RUN替换为CMD即可。CMD指令定义的是容器启动时才会执行的命令,不会在镜像构建阶段运行,正好匹配你「镜像启动后自动运行uvicorn服务」的要求。
修正后的Dockerfile
只需要替换最后一行即可,完整内容如下:
FROM python:3.9.2-buster ENV PYTHONDONTWRITEBYTECODEBYDEFAULT=1 ENV PYTHONUNBUFFERED=1 ENV PYTHONPATH "${PYTHONPATH}:/usr/src/" COPY requirements.txt . RUN python -m pip install --upgrade pip RUN python -m pip install -r requirements.txt WORKDIR /website COPY . /website RUN adduser -u 5678 --disabled-password --gecos "" webuser && chown -R webuser /website USER webuser EXPOSE 8000 # 原RUN指令替换为CMD,采用exec格式保证信号正常传递 CMD ["python", "-m", "uvicorn", "src.main:app", "--host", "0.0.0.0", "--port", "8000"]
这里用数组格式(exec形式)写CMD是官方推荐写法,可以让uvicorn直接接收容器的停止、重启信号,避免出现容器无法正常停止、被强制kill进程的问题。
补充说明
你当前main.py顶层的scraper.scrapedata()逻辑,会在uvicorn启动加载FastAPI应用时自动执行,不需要在构建阶段单独运行,功能不会受影响。如果你的爬取逻辑需要每次启动容器都重新执行,现有写法可以直接用;如果需要在镜像构建阶段就把爬取结果固化到镜像里,单独写一条RUN执行爬取脚本即可,不要和服务启动命令混写。
构建运行验证
修改完成后正常执行构建命令即可,不会再出现挂起问题:
docker build -t fastapi-demo .
构建完成后启动容器,映射8000端口就能正常访问服务:
docker run -d -p 8000:8000 fastapi-demo
内容的提问来源于stack exchange,提问作者JonneSaloranta
相关产品推荐
相关产品推荐

