这是我的Dockerfile:
# Use lightweight Python image
FROM python:3.9-slim
ARG DOCKER_ENV
# PYTHONFAULTHANDLER=1 - Display trace if a sefault occurs.
# PYTHONUNBUFFERED=1 - Allow statements and log messages to immediately appear in the Knative logs
# PIP_NO_CACHE_DIR=off - Disable pip cache for smaller Docker images.
# PIP_DISABLE_PIP_VERSION_CHECK=on - Ignore pip new version warning.
# PIP_DEFAULT_TIMEOUT=100 - Give pip longer than the 15 second timeout.
ENV DOCKER_ENV=${DOCKER_ENV}
PYTHONFAULTHANDLER=1
PYTHONUNBUFFERED=1
PIP_NO_CACHE_DIR=off
PIP_DISABLE_PIP_VERSION_CHECK=on
PIP_DEFAULT_TIMEOUT=100
# Install poetry
RUN pip install
# Set working directory in container to /app
WORKDIR /app
# Copy only dependency requirements to container to cache them in docker layer
COPY poetry.lock pyproject.toml /app/
# Don't need virtualenv because environment is already isolated in a container
RUN poetry config virtualenvs.create false
# Install production dependencies
RUN poetry install --no-dev --no-ansi
# Copy app into container
COPY . /app
# Run server
CMD [ "poetry", "run" , "python", "api.py"]
我可以在本地构建和部署它,没有问题,服务器启动。然而,当我部署到Cloud Run时,我得到以下错误,容器失败:
Creating virtualenv indie-9TtSrW0h-py3.9 in /home/.cache/pypoetry/virtualenvs
File "/app/api.py", line 6, in <module>
import jwt
ModuleNotFoundError: No module named 'jwt'
有没有人知道为什么这在本地成功工作,但在云运行中缺少依赖?一个奇怪的事情是,我明确地告诉docker不要在Dockerfile中使用虚拟环境。当我在本地运行映像时,这是有效的,但在Google Cloud上,它坚持构建一个虚拟环境。是否有某种与Google Cloud Run版本的Docker和诗歌不兼容的地方,我在这里遗漏了?
我们遇到了类似的问题-构建成功,但Cloud Run服务启动失败,没有找到模块,尽管配置略有不同。
在我们的例子中,我们没有设置virtualenvs.create
。
这是问题集virtualenvs.in-project true
的一个解决方案
# Create virtualenv at .venv in the project instead of ~/.cache/
RUN poetry config virtualenvs.in-project true
# Install production dependencies
RUN poetry install --no-dev --no-ansi
另一个解决方案是显式设置虚拟环境路径,这样它就不依赖于$HOME
,例如:
# Create virtualenv at /venv in the project instead of ~/.cache/
RUN poetry config virtualenvs.path /venv
# Install production dependencies
RUN poetry install --no-dev --no-ansi
无论哪种方式都要注意,诗歌将使用虚拟环境at ./。即使它看到它,所以确保.dockerignore
中有.venv/
。
我很确定这是因为这个问题,导致云运行设置$HOME=home
,如果容器用户是root
。
根据HN的评论,这是一个bug,将被修复:https://news.ycombinator.com/item?id=28678152,参见"google cloud run";当RUN使用/root
时,将CMD的HOME更改为/HOME我认为这个问题的更一般的解决方案是设置USER
,所以poetry install
不是作为root运行。
似乎出于某种原因,Cloud Run在与Dockerfile
的其余部分隔离的上下文中运行CMD
命令。这就是为什么poetry
认为它应该创建一个新的虚拟环境。
解决方案
(它适用于我在21.11.2021)
不是
CMD [ "poetry", "run" , "python", "api.py"]
使用:
CMD ["python", "api.py"]
它应该可以工作,因为你的依赖项已经安装了,没有virtualenv,所以你现在不再需要poetry
了。