【问题标题】:Cannot run Google App Engine custom managed VM: --custom-entrypoint must be set error无法运行 Google App Engine 自定义托管虚拟机:--custom-entrypoint must be set 错误
【发布时间】:2016-02-19 06:40:21
【问题描述】:

问题描述

我正在尝试为 Google App Engine 创建一个自定义托管 VM,其行为与 Google 提供的标准 python27 托管 VM 相同。 (我这样做是向运行时添加 C++ 库的第一步)。

来自 google documentation,以下 Dockerfile 指定了标准的 python27 运行时:

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

我已经通过检查gcloud preview app run 使用标准python27 运行时生成的Dockerfile 验证了这是正确的Dockerfile。与此相同。

但是,当我使用 dev_appserver.pygcloud preview app run 使用此 Dockerfile 运行我的应用程序时,我收到一条错误消息:

The --custom_entrypoint flag must be set for custom runtimes

我正在使用最新版本的 gcloud(1.9.86,app-engine-python 组件版本为 1.9.28)和独立的 python 应用引擎 SDK (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"

我不知道该怎么做。 docker 映像是否应该尚未包含 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 运行时的相同(实际上是从gcloud preview app run 使用python27 运行时生成的Dockerfile 复制粘贴的),所以这应该与设置@987654341 相同@。

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

【问题讨论】:

    标签: python google-app-engine google-app-engine-python gae-module google-managed-vm


    【解决方案1】:

    更新

    这可能不再准确。看看尼克的回答。

    (虽然我不能让它工作。但我没有很努力)


    有一个完全没有记录但绝对重要的信息w.r.t。自定义托管虚拟机:

    它们无法在开发服务器上运行!

    如果您认为这个重要的事实会在任何理智的地方被提及,例如自定义托管虚拟机的文档页面,或dev_appserver.py,或者甚至在运行dev_appserver.py 时作为错误消息,那么您给了 Google 很大的帮助太多的功劳。

    我可以在 github 上 appengine-java-vm-guestbook-extras demo 的自述文件中找到任何关于此的声明的唯一地方(说真的):

    Cloud SDK 不再支持在以下情况下运行自定义运行时 提供了 Dockerfile。您必须将应用程序部署到 App 引擎

    Google 不关心:

    1. 实现这一基本且重要的功能。
    2. 记录开发服务器缺少如此重要的功能。
    3. 当用户疲于执行操作时,给出任何合理的错误消息。

    我希望这个答案可以让一些遗憾的开发者免于我因此而遭受的折磨。

    【讨论】:

      【解决方案2】:

      EDIT 1user862857 发布的解决方案利用 Docker 本身从 Dockerfile 构建图像并在容器中运行它们。这也是在开发环境中运行托管 VM 和自定义运行时的好方法。


      接受的答案似乎不正确。在处理快速发展的 Beta 产品时,github README 不应胜过official docs 的权威性。完全可以在开发环境中使用runtime: custom 应用程序,使用 OP 帖子中提到的 Dockerfile,

      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-compat 运行时并简单地部署/测试一个 python WSGI 应用程序,他们也可以使用--custom_entrypoint 标志,只要他们有一个可以开始运行适当 WSGI 的命令应用程序在合适的端口上(这样的命令将是 uwsgigunicorn)。

      【讨论】:

      • 谢谢尼克。这里要添加一些 cmets。涵盖 dev_appserver.py 上的 --runtime 参数的文档 just 已更新 - 因此在创建此问题时,文档缺少标志 :( 对不起大家。第二 - 如果你真的想要要使用 docker 执行此操作,appstart 是另一种选择:github.com/GoogleCloudPlatform/appstart。它将在 docker 容器内运行您的应用程序和 dev_appserver.py。对于大多数应用程序,dev_appserver.py app.yaml --runtime python 应该可以正常工作。
      【解决方案3】:

      在尝试让我的自定义 VM 与 dev_appserver 一起更好地工作之后 一天的一部分时间,这个帖子的accepted answer 是 相当不愉快的惊喜。但我认为部署开发服务器不会那么那么麻烦,因为毕竟 VM 是标准的 Docker 映像。

      确实存在一些阻碍直接部署工作的问题。我在下面提供了这些问题的摘要以及我如何解决它们。我可能错过了 Docker 和 App Engine 环境之间的一些不兼容性(尤其是我的项目未使用的 App Engine 的许多方面),但希望它足以让人们启动和运行。

      麻烦的来源

      首先,我发现在 Compute Engine 虚拟机中运行的 python 环境是一个 比普通的 VM 环境更宽松一点(例如,像 webapp2 这样的包总是可用的)。因此,部署到不那么宽容的 Docker 容器环境在我的项目中出现了一些潜在错误。

      话虽如此,但环境中存在一些差异 即使您的项目完美无缺,也需要进行一些调整:

      • 问题:gunicorn(或您选择的服务器)必须安装在 Docker 容器的路径。

        • 虽然这看起来很明显,但我遇到了麻烦,因为我包括 gunicorn 在我项目的 requirements.txt 文件中。不幸的是,我是 使用只能安装源代码的pip install -t ... 安装所有这些依赖项。结果,图像上没有gunicorn二进制文件,更不用说PATH了。
      • 解决方案:显式pip install gunicorn


      • 问题: google.appengine.* 软件包无法从 App Engine 基础 Docker 映像也不能通过 pip (AFAICT) 获得。
        • 这可能是一个常见的问题来源,因为 google.appengine.ext.vendor 是将第三方库导入 App Engine 应用的推荐接口。
      • 解决方案:我通过下载整个 Google App Engine 包层次结构并将其放置在应用程序的路径上来解决这个问题。

      如何获取脚本

      用于构建 VM docker 映像并将其部署到 docker 容器的脚本 本地运行可用 here.

      有关工作示例,请查看my project

      如果您有评论、功能请求或者您是否编写了更漂亮的 bash,请告诉我 比我(我觉得我已经把这个标准定得很低了)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-28
        • 2016-03-17
        • 2016-05-22
        • 1970-01-01
        • 2023-03-21
        • 1970-01-01
        • 2015-09-13
        • 2022-12-19
        相关资源
        最近更新 更多