Не удается запустить пользовательскую управляемую виртуальную машину 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-запросы.

Два других соответствующих вопроса stackoverflow, которые я нашел, не помогли. Принятые ответы, кажется, предполагают, что это ошибка в 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 (и фактически буквально скопирован из файла Docker, сгенерированного 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

person user2771609    schedule 17.11.2015    source источник


Ответы (3)


ОБНОВЛЕНИЕ

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

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


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

ОНИ НЕЛЬЗЯ ЗАПУСКАТЬ НА СЕРВЕРЕ РАЗРАБОТКИ!

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

Единственное место, где я могу найти какое-либо заявление об этом, — это файл Readme в appengine-java-vm-guestbook-extras demo на github (серьезно):

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

Google не заботится о:

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

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

person user2771609    schedule 19.11.2015

EDIT 1: решение, опубликованное user862857, использует сам Docker для создания образов из Dockerfile и запуска их в контейнерах. Это также хороший подход к запуску управляемых виртуальных машин и пользовательских сред выполнения в контексте разработки.


Принятый ответ не кажется правильным. README на github не должен превосходить официальную документацию в плане авторитетности при работе с с быстро развивающимся бета-продуктом. Это вполне возможно для приложения 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=stackoverflow.com, чтобы увидеть это в действии.


Примечание

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

person Nick    schedule 15.12.2015
comment
Спасибо, Ник. Несколько комментариев, чтобы добавить сюда. Документ, который охватывает параметр --runtime в dev_appserver.py, только что был обновлен, поэтому, когда эта проблема была создана, в документах отсутствовал флаг :( Извините за это все. Во-вторых, если вы действительно хотите чтобы использовать докер для этого, appstart — еще один вариант: github.com/GoogleCloudPlatform/appstart. запустите приложение и файл dev_appserver.py внутри контейнера докеров. Однако для большинства приложений dev_appserver.py app.yaml --runtime python должно работать нормально. - person Justin Beckwith; 08.01.2016

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

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

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

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

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

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

    • While this may seem obvious, I ran into trouble because I included gunicorn in my project's requirements.txt file. Unfortunately, I was installing all of these dependencies using pip install -t ... which is only able to install source. As a result, there was no gunicorn binary on the image let alone on the PATH.
  • Решение: явным образом pip install gunicorn


  • Problem: google.appengine.* packages are not available from the App Engine base Docker image nor are they available via pip (AFAICT).
    • This may be a common source of trouble because google.appengine.ext.vendor is the recommended interface for importing third-party libraries into your App Engine app.
  • Решение. Я обошел эту проблему, загрузив всю иерархию пакетов Google App Engine и поместив ее в путь к приложению.

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

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

Рабочий пример см. в моем проекте.

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

person user862857    schedule 16.12.2015