Назад | Перейти на главную страницу

Azure: ошибка приложения Docker «… сайт не был запущен в течение ожидаемого срока» и «Контейнер X не ответил на запросы HTTP на порте 80»

У меня есть приложение Flask Python, которое запускается через Gunicorn из контейнера Docker Linux. Запуск контейнера Docker в Ubuntu отлично работает локально, но когда контейнер помещается в реестр контейнеров Azure, а затем развертывается как приложение Azure, происходит сбой со следующими сообщениями об ошибках:

  1. Контейнер my-app_900f4c для сайта my-app не запустился в течение ожидаемого срока.
  2. Контейнер my-app_900f4c не ответил на запросы HTTP на порт: 80, не удалось запустить сайт.

Журнал Docker

2020-02-17 INFO  - Pull Image successful, Time taken: 0 Minutes and 15 Seconds
2020-02-17 INFO  - Starting container for site
2020-02-17 INFO  - docker run -d -p 9031:80 --name my-app_900f4c -e PORT=80 -e WEBSITES_PORT=80 -e WEBSITE_SITE_NAME=my-app -e WEBSITE_AUTH_ENABLED=False -e WEBSITE_ROLE_INSTANCE_ID=0 -e WEBSITE_HOSTNAME=my-app.azurewebsites.net -e WEBSITE_INSTANCE_ID=eaaf...51e441df96704916ba7b506b6150b26cdc7 -e HTTP_LOGGING_ENABLED=1 myazureappregistry.azurecr.io/my_app:v1  

2020-02-17 INFO  - Initiating warmup request to container my-app_900f4c for site my-app
2020-02-17 ERROR - Container my-app_900f4c for site my-app did not start within expected time limit. Elapsed time = 255.9515056 sec
2020-02-17 ERROR - Container my-app_900f4c didn't respond to HTTP pings on port: 80, failing site start. See container logs for debugging.
2020-02-17 INFO  - Stopping site my-app because it failed during startup.

Журнал Docker по умолчанию

2020-02-17 [1] [INFO] Starting gunicorn 20.0.4
2020-02-17 [1] [INFO] Listening at: http://0.0.0.0:80 (1)
2020-02-17 [1] [INFO] Using worker: gthread
2020-02-17 [7] [INFO] Booting worker with pid: 7
2020-02-17 [8] [INFO] Booting worker with pid: 8
2020-02-17 [9] [INFO] Booting worker with pid: 9
2020-02-17 [10] [INFO] Booting worker with pid: 10

На портале Azure под Настройки> Конфигурация У меня есть следующие Настройки приложения:

Dockerfile

FROM python:3.8-slim-buster

LABEL Name=my_app Version=0.0.1
EXPOSE 80

WORKDIR /app

RUN python3 -m pip install --upgrade pip
RUN python3 -m pip install -r requirements.txt
ADD . /app
CMD ["gunicorn", "-c", "gunicorn.conf.py", "main:app"]

Я не понимаю, что вызывает HTTP-запросы на порт 80 потерпеть неудачу, когда журналы показывают, что Gunicorn слушает http://0.0.0.0:80.

Подобные вопросы, у которых есть не решил вопрос:

Контейнер должен реализовывать обработчик ошибок HTTP 404 (не найдено).

Когда Azure запускает контейнер, запрос на разминку проверяет сервер, запрашивая ресурсы, чтобы убедиться, что он отвечает. Если один из запрошенных ресурсов не найден и у контейнера нет HTTP 404 (Not Found) обработчик ошибок, то время ожидания запроса истечет, и контейнер будет остановлен.

Конфигурация порта контейнера Docker

Лазурный PORT флаг не нужен. В WEBSITES_PORT flag должен быть установлен в зависимости от того, какой порт открыт в контейнере.

Устанавливать WEBSITES_PORT из Azure CLI следующим образом:

az webapp config appsettings set --resource-group <resource-group-name> --name <app-name> --settings WEBSITES_PORT=8000

Или воспользуйтесь порталом Azure:
Ваше приложение> Настройки> Конфигурация> Настройки приложения

Пример Flask - обработчик ошибок HTTP 404

from flask import Flask
from werkzeug.exceptions import Forbidden, HTTPException, NotFound, RequestTimeout, Unauthorized


app = Flask(__name__)


@app.route('/')
def hello():
    return "Hello Flask!"


@app.errorhandler(NotFound)
def page_not_found_handler(e: HTTPException):
    return render_template('404.html'), 404


@app.errorhandler(Unauthorized)
def unauthorized_handler(e: HTTPException):
    return render_template('401.html'), 401


@app.errorhandler(Forbidden)
def forbidden_handler(e: HTTPException):
    return render_template('403.html'), 403


@app.errorhandler(RequestTimeout)
def request_timeout_handler(e: HTTPException):
    return render_template('408.html'), 408


if __name__ == '__main__':
    app.run()