Docker镜像在本地部署,但在Google Cloud Run上失败



这是我的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了。

最新更新