Github для Google Cloud Run: Python Flask API WSGI, работающий в Google Cloud Run, выдает «Не удалось запустить контейнер и прослушать порт»

Я пытаюсь создать Python Flask API on WSGI, который я хочу запустить в Google Cloud Run.

Код хранится в репозитории Github. В https://console.cloud.google.com/run я добавил репозиторий Github, так что когда будет сделан новый пуш в основную ветку, будет выполнена сборка.

Код представляет собой Flask API, работающий на веб-сервере WSGI. Я получаю сообщения об ошибках, когда пытаюсь запустить его в Google Run: ERROR: build step 2 "gcr.io/google.com/cloudsdktool/cloud-sdk:slim" failed: step exited with non-zero status: 1

config/фласк-сайт-nginx.conf

server {
    location / {
        try_files $uri @yourapplication;
    }
    location @yourapplication {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
}

конфиг/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)

источник/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)))

Докерфайл

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

требования.txt

flask
flask-unittest
Flask-RESTful
flask-cors

Когда я пытаюсь отправить код, Google Run строит его, но выдает ошибки:

Создание ревизии:

Предоставленный пользователем контейнер не удалось запустить и прослушивать порт определяется переменной среды PORT=8080. Логи для этого редакция может содержать больше информации. 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- бэкэнд-00009-rew%22 Дополнительные рекомендации по устранению неполадок см. https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start

Маршрутизация трафика

В ожидании

Сборка и развертывание из репозитория:

Не удалось выполнить триггер: исходный код не удалось собрать или развернуть; найти дополнительную информацию в журналах сборки 'template-google-cloud-run-backend-00009-rew' не готов и не может обслуживать трафик. Предоставленный пользователем контейнер не удалось запустить и прослушать на порту, указанном в переменной среды PORT=8080. Журналы для этой версии могут содержать дополнительную информацию. 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- бэкэнд-00009-rew%22 Дополнительные рекомендации по устранению неполадок см. https://cloud.google.com/run/docs/troubleshooting#container-failed-to-start

Журналы сборки дают мне:

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

1) Вам не нужны Nginx, WSGI или супервизор. Настройте Flask для прослушивания $PORT и запуска приложения. 2) Для вашей настройки у вас есть и Nginx, и приложение Flask, прослушивающие соединения. Какой порт прослушивает Nginx (вероятно, порт 80)? Контейнер настроен на порт 8080, Flask прослушивает порт 8080, поэтому Nginx просто тратит место.

John Hanley 14.11.2022 09:16

Когда я запускаю Flask API без WSIG, он говорит: «ВНИМАНИЕ: это сервер разработки. Не используйте его в рабочем развертывании. Вместо этого используйте рабочий сервер WSGI».

Europa 14.11.2022 09:19

Cloud Run имеет GFE (Google Frontend). Это защищает небезопасные приложения, такие как Flask. Вы можете игнорировать это предупреждение для экземпляров Cloud Run. Если вы будете использовать Flask на чем-то вроде Compute Engine, используйте Nginx и т. д., чтобы Flask не отображался в общедоступном интерфейсе. Использование Nginx или Apache может иметь некоторые преимущества, но если ваш экземпляр Cloud Run не будет обслуживать большой трафик, сложность не стоит преимуществ, ИМХО. Cloud Run делает обслуживание трафика очень простым без сложности, которую вы создаете.

John Hanley 14.11.2022 09:25
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
0
3
107
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Во-первых, ошибка, которая появляется на этапе выполнения сборки, четко указывает, что ревизия для сборки не готова по пути, что может быть связано с неготовностью сборки или с тем, что процесс не распознает эту сборку из-за проблемы с тегом.
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
Чтобы предотвратить эту проблему, убедитесь, что сборка ревизии готова к выбору, и повторите попытку. Также попробуйте удалить этот тег «редакция» и повторите попытку.
Эти изменения помогут, потому что при обновлении трафика трафик «0%» назначался каждой ревизии, указанной в поле трафика, и на данный момент, поскольку эта ревизия не готова, любая операция, которая назначает трафик (даже если 0%), вызовет ошибка.
Во-вторых, ошибка порта прослушивателя предполагает, что при запуске вашего контейнера он ожидает ответа на порт $PORT (8080) в соответствии с установленной переменной среды. Теперь, когда сборка не готова, она не соответствует требованиям Cloud Run и прекращается, когда Cloud Run обнаруживает отсутствие ответа или неправильный ответ на порту $PORT.
Прочтите этот документ, чтобы лучше понять контракт среды выполнения.

Пожалуйста, ознакомьтесь с этим документом, в котором перечислены ряд шагов, которые необходимо выполнить при обнаружении этой ошибки, чтобы решить проблему.
Также взгляните на эти похожие примеры:

Другие вопросы по теме