简体   繁体   中英

Deploying multi-stage Docker image in Google Cloud Run

I created a multi-stage Docker image to reduce the size of my python application. The content of the Dockerfile is:

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"]

Then I pushed the image my_image to the Google Cloud Storage of my project my_proj with:

$ docker push us.gcr.io/my_proj/my_image

When I try to start a Google Cloud Run service with this image, it fails with the Python error:

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).

But flask is installed in the image, and a container created locally from this image does run it normally.

Why the container in Google Cloud Run is not able to find the module flask ? Isn't it created completely?

Reason of the problem:

The problem in this case is not with the fact that the image was created using the multi-stage approach. The issue is that the Python modules were installed using the option --user .

This option was included so that the needed Python modules were stored in the folder /root/.local , which could be copied directly to the new deploy image.

However, for some reason, Python applications in containers in Google Cloud Run are not able to find the modules if they are in the folder /root/.local . Probably a user other than root is used there. Thus, using the --user argument of pip does not work, which also inhibits the multi-stage approach in this type of scenario.

Solution:

Do a "mono-stage" image with global Python modules, ie, a Dockerfile like:

FROM python:3.10-slim

# 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 \
      Flask==2.2.2 Flask-RESTful==0.3.9 Flask-Cors==3.0.10 keras==2.9.0 && \
    pip cache purge

# get app content
COPY app ./app

# define working directory and the standard command (run it detached)
WORKDIR /app
ENTRYPOINT ["python"]
CMD ["wsgi.py"]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM