在Google Cloud Run部署多阶段Docker镜像时Flask模块缺失问题
问题:Google Cloud Run中Python容器无法找到已安装的Flask模块?
我为减小Python应用体积创建了多阶段Docker镜像,Dockerfile内容如下:
FROM python:3.10-slim AS image-compiling # updates pip and prepare for installing wheels RUN pip install --upgrade pip && \ pip install wheel && \ pip cache purge # install needed modules from wheels RUN pip install --user \ Flask==2.2.2 Flask-RESTful==0.3.9 Flask-Cors==3.0.10 keras==2.9.0 && \ pip cache purge # brand new image FROM python:3.10-slim AS image-deploy # get python 'user environment' COPY --from=image-compiling /root/.local /root/.local # get app content COPY app ./app # define working directory and the standard command (run it detached) WORKDIR /app ENTRYPOINT ["python"] CMD ["wsgi.py"]
随后将镜像推送到Google Cloud Registry:
$ docker push us.gcr.io/my_proj/my_image
但在Google Cloud Run中启动服务时,出现以下错误:
Error 2022-09-14 11:41:13.744 EDTTraceback (most recent call last): File "/app/wsgi.py", line 10, in <module> from flask import render_template ModuleNotFoundError: No module named 'flask' Warning 2022-09-14 11:41:13.805 EDTContainer called exit(1).
本地基于该镜像创建的容器可正常运行,为何Cloud Run中找不到Flask模块?
原因分析
问题出在**pip install --user的安装路径与Cloud Run默认运行用户不兼容**:
- 使用
--user参数时,Python包会安装到/root/.local目录下,这是root用户的个人Python环境路径。 - 本地运行容器时默认以root用户启动,root的环境变量(
PATH、PYTHONPATH)包含/root/.local的相关路径,因此能找到安装的包。 - 而Google Cloud Run默认以非root用户(通常是UID=1000的无权限用户)运行容器,该用户的HOME目录不是
/root,其环境变量中没有包含/root/.local下的包路径,导致Python无法定位到Flask等模块。
解决方案
方案1:添加环境变量,让非root用户能访问root的本地包
在image-deploy阶段添加环境变量,将/root/.local的路径加入Python的搜索路径和系统PATH:
FROM python:3.10-slim AS image-compiling RUN pip install --upgrade pip && \ pip install wheel && \ pip cache purge RUN pip install --user \ Flask==2.2.2 Flask-RESTful==0.3.9 Flask-Cors==3.0.10 keras==2.9.0 && \ pip cache purge FROM python:3.10-slim AS image-deploy COPY --from=image-compiling /root/.local /root/.local # 添加环境变量,确保非root用户能找到包 ENV PATH="/root/.local/bin:$PATH" ENV PYTHONPATH="/root/.local/lib/python3.10/site-packages:$PYTHONPATH" COPY app ./app WORKDIR /app ENTRYPOINT ["python"] CMD ["wsgi.py"]
方案2:安装到系统级Python路径(推荐)
去掉pip install的--user参数,将包直接安装到系统级Python目录(/usr/local/lib/python3.10/site-packages),这样所有用户都能访问:
FROM python:3.10-slim AS image-compiling RUN pip install --upgrade pip && \ pip install wheel && \ pip cache purge # 移除--user参数,安装到系统路径 RUN pip install \ Flask==2.2.2 Flask-RESTful==0.3.9 Flask-Cors==3.0.10 keras==2.9.0 && \ pip cache purge FROM python:3.10-slim AS image-deploy # 复制系统级安装的包和可执行文件 COPY --from=image-compiling /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages COPY --from=image-compiling /usr/local/bin /usr/local/bin COPY app ./app WORKDIR /app ENTRYPOINT ["python"] CMD ["wsgi.py"]
方案3:切换为非root用户并调整包路径
创建一个非root用户,将/root/.local的权限修改为该用户可访问,或者将包复制到该用户的HOME目录下,但这种方式步骤较多,不如前两种简便。
内容的提问来源于stack exchange,提问作者adlzanchetta
相关产品推荐
相关产品推荐

