I am trying to create a Python Flask API on WSGI that I want to run on Google Cloud Run.
The code is stored in a Github repository. In https://console.cloud.google.com/run I have added the Github repository so that when a new push is made to main branch then a build will be done.
The code is a Flask API running on WSGI webserver. I get some error messages when I try to run it on Google Run: ERROR: build step 2 "gcr.io/google.com/cloudsdktool/cloud-sdk:slim" failed: step exited with non-zero status: 1
config/flask-site-nginx.conf
server {
    location / {
        try_files $uri @yourapplication;
    }
    location @yourapplication {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
}
config/nginx.conf
# based on default config of nginx 1.12.1
# Define the user that will own and run the Nginx server
user nginx;
# Define the number of worker processes; recommended value is the number of
# cores that are being used by your server
# auto will default to number of vcpus/cores
worker_processes auto;
# altering default pid file location
pid /tmp/nginx.pid;
# turn off daemon mode to be watched by supervisord
daemon off;
# Enables the use of JIT for regular expressions to speed-up their processing.
pcre_jit on;
# Define the location on the file system of the error log, plus the minimum
# severity to log messages for
error_log /var/log/nginx/error.log warn;
# events block defines the parameters that affect connection processing.
events {
    # Define the maximum number of simultaneous connections that can be opened by a worker process
    worker_connections  1024;
}
# http block defines the parameters for how NGINX should handle HTTP web traffic
http {
    # Include the file defining the list of file types that are supported by NGINX
    include /etc/nginx/mime.types;
    # Define the default file type that is returned to the user
    default_type text/html;
    # Don't tell nginx version to clients.
    server_tokens off;
    # Specifies the maximum accepted body size of a client request, as
    # indicated by the request header Content-Length. If the stated content
    # length is greater than this size, then the client receives the HTTP
    # error code 413. Set to 0 to disable.
    client_max_body_size 0;
    # Define the format of log messages.
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" "$http_x_forwarded_for"';
    # Define the location of the log of access attempts to NGINX
    # access_log /var/log/nginx/access.log  main;
    access_log /dev/stdout main;
    # Define the parameters to optimize the delivery of static content
    sendfile       on;
    tcp_nopush     on;
    tcp_nodelay    on;
    # Define the timeout value for keep-alive connections with the client
    keepalive_timeout  65;
    # Define the usage of the gzip compression algorithm to reduce the amount of _data to transmit
    #gzip  on;
    # Include additional parameters for virtual host(s)/server(s)
    include /etc/nginx/conf.d/*.conf;
}
supervisord.conf
[supervisord] nodaemon=true [program:uwsgi] command=/usr/local/bin/uwsgi --ini /etc/uwsgi/uwsgi.ini --die-on-term stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0 [program:nginx] command=/usr/sbin/nginx stdout_logfile=/dev/stdout stdout_logfile_maxbytes=0 stderr_logfile=/dev/stderr stderr_logfile_maxbytes=0
uwsgi.ini
[uwsgi] module = src.wsgi callable = app uid = nginx gid = nginx socket = /tmp/uwsgi.sock chown-socket = nginx:nginx chmod-socket = 664 cheaper = 1 processes = %(%k + 1)
src/__init__.py
(empty file)
src/main.py
import os
from flask import Flask
from flask_cors import CORS
app = Flask(__name__)
cors = CORS(app)
app.config['CORS_HEADERS'] = 'Content-Type'
# Routes
@app.route('/', methods=['GET'])
def __index():
    return "Hello from Flask API running on WSGI"
# - Main start ----------------------------------------------------------------
if __name__ == "__main__":
    # Start app
    print("main() :: Flask API is starting at: http://127.0.0.1:8080")
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
src/wsgi.py
import os
from src.main import app
if __name__ == "__main__":
    print("wsgi() :: Flask API is starting at: http://127.0.0.1:8080")
    app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
Dockerfile
# Specify Python
FROM python:latest
# Copy files
RUN mkdir /app
WORKDIR /app
COPY . .
# Install Nginx web server
RUN apt-get update
RUN apt-get install -y --no-install-recommends 
        libatlas-base-dev gfortran nginx supervisor
# Install uWSGI Web Server Gateway Interface
RUN pip install uwsgi
# Install requiremets
RUN pip install -r requirements.txt
# Configure Nginx and uWSGI
RUN useradd --no-create-home nginx
RUN rm /etc/nginx/sites-enabled/default
RUN rm -r /root/.cache
COPY config/nginx.conf /etc/nginx/
COPY config/flask-site-nginx.conf /etc/nginx/conf.d/
COPY config/uwsgi.ini /etc/uwsgi/
COPY config/supervisord.conf /etc/
CMD ["/usr/bin/supervisord"]
requirements.txt
flask flask-unittest Flask-RESTful flask-cors
When I try to push the code Google Run builds it but it gives me errors:
Creating revision:
The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable. Logs for this revision might contain more information. Logs URL: https://console.cloud.google.com/logs/viewer?project=engineering-infra&resource=cloud_run_revision/service_name/template-google-cloud-run-backend/revision_name/template-google-cloud-run-backend-00009-rew&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22template-google-cloud-run-backend%22%0Aresource.labels.revision_name%3D%22template-google-cloud-run-backend-00009-rew%22 For more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start
Routing traffic
Pending
Building and deploying from repository:
Trigger execution failed: source code could not be built or deployed; find more information in build logs Revision ‘template-google-cloud-run-backend-00009-rew’ is not ready and cannot serve traffic. The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable. Logs for this revision might contain more information. Logs URL: https://console.cloud.google.com/logs/viewer?project=engineering-infra&resource=cloud_run_revision/service_name/template-google-cloud-run-backend/revision_name/template-google-cloud-run-backend-00009-rew&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22template-google-cloud-run-backend%22%0Aresource.labels.revision_name%3D%22template-google-cloud-run-backend-00009-rew%22 For more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start
The build logs gives me:
Step #2 - "Deploy": 219f975b51dc: Pull complete Step #2 - "Deploy": Digest: sha256:8dde46b24ab5c496d1fb11bdd87a68a07f8d752098caac87bc60d59d904a1ff5 Step #2 - "Deploy": Status: Downloaded newer image for gcr.io/google.com/cloudsdktool/cloud-sdk:slim Step #2 - "Deploy": gcr.io/google.com/cloudsdktool/cloud-sdk:slim Step #2 - "Deploy": Deploying... Step #2 - "Deploy": Creating Revision....failed Step #2 - "Deploy": Deployment failed Step #2 - "Deploy": ERROR: (gcloud.run.services.update) The user-provided container failed to start and listen on the port defined provided by the PORT=8080 environment variable. Logs for this revision might contain more information. Step #2 - "Deploy": Step #2 - "Deploy": Logs URL: https://console.cloud.google.com/logs/viewer?project=engineering-infra&resource=cloud_run_revision/service_name/template-google-cloud-run-backend/revision_name/template-google-cloud-run-backend-00009-rew&advancedFilter=resource.type%3D%22cloud_run_revision%22%0Aresource.labels.service_name%3D%22template-google-cloud-run-backend%22%0Aresource.labels.revision_name%3D%22template-google-cloud-run-backend-00009-rew%22 Step #2 - "Deploy": For more troubleshooting guidance, see https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start Finished Step #2 - "Deploy" ERROR ERROR: build step 2 "gcr.io/google.com/cloudsdktool/cloud-sdk:slim" failed: step exited with non-zero status: 1
Advertisement
Answer
Firstly,the error that is seen during the build execution step clearly states that the revision for the build is not ready on the path, which could be due to the build not ready or the process not recognizing this build due to tag issue.
Trigger execution failed: source code could not be built or deployed; find more information in build logs Revision 'template-google-cloud-run-backend-00009-rew' is not ready and cannot serve traffic
To prevent this issue,ensure that the revision build is ready to be picked and try again.Also try to remove that “revision”tag and try again.
These changes will help because when updating traffic, “0%” traffic was being assigned to every revision specified in the traffic field and as of now since this revision is not ready, any operation that is assigning traffic (even though 0%) would cause the error.
Secondly, the listener port error suggests that when your container starts, it expects a response on port $PORT (8080),as per the environment variable is set.Now as the build is not ready it does not follow the Cloud Run requirements and is terminated when Cloud Run detects no response / incorrect response on port $PORT.
Read this document to better understand the runtime environment contract.
Please review this document which lists a series of steps to follow when encountering this error in order to fix the issue.
Also have a look at these similar examples:
