Skip to content
Advertisement

Github to Google Cloud Run: Python Flask API WSGI running on Google Cloud Run gives “Container failed to start and listen on the port”

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:

Advertisement