Невозможно запустить настраиваемую управляемую виртуальную машину Google App Engine: должна быть установлена ​​ошибка --custom-entrypoint

ОПИСАНИЕ ПРОБЛЕМЫ

Я пытаюсь создать настраиваемую управляемую виртуальную машину для Google App Engine, которая работает аналогично стандартной управляемой виртуальной машине python27, предоставленной Google. (Я делаю это как первый шаг к добавлению библиотеки C++ во время выполнения).

Из документации Google следующий Dockerfile определяет стандартную среду выполнения python27:

FROM gcr.io/google_appengine/python-compat
ADD . /app

Я проверил, что это правильный Dockerfile, изучив файл, сгенерированный gcloud preview app run при использовании стандартной среды выполнения python27. Это идентично этому.

Но когда я запускаю свое приложение с этим Dockerfile, используя dev_appserver.py или с gcloud preview app run Я получаю сообщение об ошибке:

The --custom_entrypoint flag must be set for custom runtimes

Я использую последние версии gcloud (1.9.86, с компонентом app-engine-python версии 1.9.28) и SDK автономного движка приложений python (1.9.28). У меня была такая же проблема с более ранними версиями, поэтому я обновился до последней.

Вещи, которые я испытал:

gcloud preview app run --help имеет следующее сказать о --custom-entrypoint:

 --custom-entrypoint CUSTOM_ENTRYPOINT
    Specify an entrypoint for custom runtime modules. This is required when
    such modules are present. Include "{port}" in the string (without
    quotes) to pass the port number in as an argument. For instance:
    --custom_entrypoint="gunicorn -b localhost:{port} mymodule:application"

Я не уверен, что с этим делать. Если изображение докера еще не содержит ENTRYPOINT? Почему я должен предоставить один в дополнение? Кроме того, какой должна быть точка входа для gcr.io/google_appengine/python-compat изображение будет? Google не предоставляет никакой документации для этого.

Я пробовал бессмысленно --custom-entrypoint="echo", который заглушает ошибку, но приложение не отвечает ни на какие HTTP-запросы.

Два других релевантных вопроса о стековом потоке, которые я нашел, не помогли. Принятые ответы, похоже, указывают на то, что это ошибка в SDK, которая была устранена. Но я попробовал это в двух версиях SDK, включая последнюю, и у меня все еще есть проблема.

ШАГИ ПЕРЕПИСАТЬ:

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

app.yaml:

module: default
version: 1
runtime: custom
api_version: 1
threadsafe: true
vm: true

handlers:
- url: /.*
  script: wsgi.app

Dockerfile:

FROM gcr.io/google_appengine/python-compat
ADD . /app

это Dockerfile тот же самый, который используется для среды выполнения python27 (и фактически буквально копируется из файла Dockerfile, сгенерированного gcloud preview app run при использовании среды выполнения Python27), поэтому это должно совпадать с настройкой runtime: python27,

wsgi.py:

import webapp2

class Hello(webapp2.RequestHandler):
    def get(self):
        self.response.write(u'Hello')

app = webapp2.WSGIApplication([('/Hello', Hello)], debug=True)

Когда я бегу dev_appserver.py app.yaml однако в каталоге, содержащем эти три файла, я получаю следующую ошибку:

Traceback (most recent call last):
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/dev_appserver.py", line 83, in <module>
    _run_file(__file__, globals())
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/dev_appserver.py", line 79, in _run_file
    execfile(_PATHS.script_file(script_name), globals_)
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/devappserver2.py", line 1033, in <module>
    main()
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/devappserver2.py", line 1026, in main
    dev_server.start(options)
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/devappserver2.py", line 818, in start
    self._dispatcher.start(options.api_host, apis.port, request_data)
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/dispatcher.py", line 194, in start
    _module.start()
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/module.py", line 1555, in start
    self._add_instance()
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/module.py", line 1707, in _add_instance
    expect_ready_request=True)
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/custom_runtime.py", line 73, in new_instance
    assert self._runtime_config_getter().custom_config.custom_entrypoint
  File "/home/vagrant/google-cloud-sdk/platform/google_appengine/google/appengine/tools/devappserver2/module.py", line 383, in _get_runtime_config
    raise ValueError('The --custom_entrypoint flag must be set for '
ValueError: The --custom_entrypoint flag must be set for custom runtimes

3 ответа

Решение

ОБНОВИТЬ

ЭТО НЕ МОЖЕТ БЫТЬ ТОЛЬКО ТОЧНЫМ. ПОСМОТРЕТЬ НИК ОТВЕТ.

(Хотя я не мог заставить это работать. Но я не очень старался)


Существует совершенно недокументированная, но абсолютно необходимая информация о виртуально управляемых ВМ:

ОНИ НЕ МОГУТ БЫТЬ НА СЕРВЕРЕ РАЗВИТИЯ!

Если вы думаете, что этот важный факт будет упомянут в любом месте, например, на странице документации для настраиваемых управляемых виртуальных машин или для dev_appserver.pyили даже как сообщение об ошибке при запуске dev_appserver.py, тогда вы даете Google слишком много кредитов.

Единственное место, где я могу найти какое-либо утверждение по этому поводу, находится в файле Readme https://github.com/GoogleCloudPlatform/appengine-java-vm-guestbook-extras на github (серьезно):

Cloud SDK больше не поддерживает запуск пользовательских сред выполнения, когда предоставляется Dockerfile. Вам придется развернуть приложение в App Engine.

Google не заботится о том, чтобы:

  1. Реализуйте эту основную и важную функцию.
  2. Документ, что на сервере разработки отсутствует такая важная функция.
  3. Дайте любое разумное сообщение об ошибке, когда пользователь устает выполнять действие.

Я надеюсь, что этот ответ спасет какого-нибудь извиняющегося разработчика от мучительных дней, которые я пережил из-за этого

РЕДАКТИРОВАТЬ 1: Решение, опубликованное user862857, использует сам Docker для создания образов из Dockerfile и запуска их в контейнерах. Это также хороший подход к запуску управляемых виртуальных машин и пользовательских сред выполнения в контексте разработки.


Принятый ответ не кажется правильным. Github README не должен превзойти официальные документы в авторитетности при работе с быстро развивающимся бета-продуктом. Это вполне возможно для runtime: custom приложение в среде разработчика, используя Dockerfile, упомянутый в посте OP,

FROM gcr.io/google_appengine/python-compat
ADD . /app

с использованием --runtime=python-compat флаг. Они должны были бы ловить запросы /_ah/start а также /_ah/health, хоть. Попытайтесь запустить следующую команду, используя следующие файлы, и убедитесь сами:

devserver command

$ dev_appserver.py app.yaml --runtime=python-compat

app.yaml

runtime: custom
vm: true
api_version: 1
threadsafe: true

handlers:
- url: /.*
  script: main.app

Dockerfile

FROM gcr.io/google_appengine/python-compat

RUN apt-get update

RUN apt-get install -y gwhois

ADD . /app

main.py

import logging
import webapp2
from subprocess import Popen, PIPE

class OkHandler (webapp2.RequestHandler):
    def get (self): 
        self.response.write ('ok')

class MainPage(webapp2.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        domain = self.request.get ('domain')
        cmd = ["gwhois", domain]
        process = Popen (cmd, stdout=PIPE, stderr=PIPE)
        output, err = process.communicate()
        exit_code = process.wait()
        self.response.write('stdout: %s' % output)
        logging.info ('stderr: %s' % err)

app = webapp2.WSGIApplication([
    ('/', MainPage),
    ('/_ah/start', OkHandler),
    ('/_ah/health', OkHandler)
], debug=True)

Отправить запрос на /?domain=stackru.com чтобы увидеть это в действии.


NB

Если они хотят полностью отделиться от среды исполнения python-compat и просто развернуть / протестировать приложение Python WSGI через них, они также могут использовать --custom_entrypoint flag, пока у них есть команда, которая запускает соответствующее приложение WSGI на подходящем порту (такой командой будет uwsgi или gunicorn).

После попытки заставить мою собственную виртуальную машину работать с dev_appserver большую часть дня, принятый ответ на этот пост стал довольно неприятным сюрпризом. Но я подумал, что развертывание сервера разработки не может быть такой большой проблемой, потому что, в конце концов, виртуальная машина - это стандартный образ Docker.

Что ж, оказалось, что есть несколько проблем, которые мешают правильному развертыванию. Ниже я представил сводку этих проблем, а также то, как я их решил. Возможно, я упустил некоторые несовместимости между средами Docker и App Engine (особенно со многими аспектами App Engine, которые мой проект не использовал), но, надеюсь, этого достаточно, чтобы люди работали.

Источники неприятностей

Во-первых, я обнаружил, что среда Python, запускаемая на виртуальных машинах Compute Engine, более мягкая, чем обычная среда виртуальных машин (например, пакеты типа webapp2 всегда доступны). Следовательно, развертывание в менее щадящей среде контейнера Docker выявило некоторые скрытые ошибки в моем проекте.

Тем не менее, существуют некоторые различия в средах, которые требуют некоторых настроек, даже если ваш проект безупречен:

  • Проблема: gunicorn (или сервер по вашему выбору) должен быть установлен на пути контейнера Docker.

    • Хотя это может показаться очевидным, я столкнулся с проблемой, потому что я включилgunicorn в моем проекте requirements.txt файл. К сожалению, я устанавливал все эти зависимости, используя pip install -t ... который может только установить источник. В результате не было gunicorn двоичный на изображении, не говоря уже о PATH,
  • Решение: явно pip install gunicorn


  • Проблема: google.appengine.* пакеты недоступны из базового образа Docker App Engine и не доступны через pip (AFAICT).
    • Это может быть общим источником проблем, потому что google.appengine.ext.vendor рекомендуемый интерфейс для импорта сторонних библиотек в приложение App Engine.
  • Решение: я справился с этим, загрузив всю иерархию пакетов Google App Engine и поместив его в путь приложения.

Как получить скрипт

Сценарий для создания и развертывания образа Docker VM в контейнере Docker, работающем локально, доступен здесь.

Для рабочего примера, проверьте мой проект.

Дайте мне знать, если у вас есть комментарий, запрос на добавление функции или если вы пишете более симпатичный bash, чем я (я чувствую, что установил комфортно низкую планку на этом счетчике).

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