无法运行 Google App Engine 自定义托管虚拟机:--自定义入口点必须设置错误



>问题描述

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

从 google 文档中,以下 Dockerfile 指定了标准的 python27 运行时:

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

我已经通过检查使用标准 python27 运行时由 gcloud preview app run 生成的文件来验证这是正确的 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 映像是否应该已经包含入口点?为什么需要我另外提供一个?另外,gcr.io/google_appengine/python-compat图像的入口点应该是什么?谷歌没有为此提供任何文档。

我尝试了一个毫无意义的--custom-entrypoint="echo",它使错误静音,但应用程序不响应任何HTTP请求。

我发现的另外两个相关的堆栈溢出问题没有帮助。接受的答案似乎表明这是已解决的 SDK 中的错误。但是我已经在两个版本的SDK中尝试过,包括最新版本,但我仍然有问题。

  • 如何解决"The --custom_entrypoint flag must be set for custom runtimes"?
  • Google 托管虚拟机错误 - 自定义入口点
重现

步骤:

为了突出我的问题,我创建了一个生成错误的简单应用程序。它仅包含三个文件:

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 运行时的相同(实际上实际上是从使用 python27 运行时gcloud preview app run生成的 Dockerfile 复制粘贴的(,因此这应该与设置 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

更新

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

(虽然我无法做到这一点。但我并没有很努力(


自定义

托管 VM 有一条完全未记录但绝对必要的信息:

它们不能在开发服务器上运行!

如果您认为这个关键事实会在任何理智的地方提及,例如,自定义托管虚拟机的文档页面,或dev_appserver.py,甚至在运行时作为错误消息 dev_appserver.py ,那么你给了谷歌太多的信任。

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

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

谷歌不在乎:

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

我希望这个答案能拯救一些可怜的开发人员,使他们免于因此而遭受折磨的日子。

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


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

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

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

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

麻烦的来源

首先,我发现在计算引擎虚拟机中运行的 python 环境是一个比普通的 VM 环境更宽松一些(例如,像 webapp2 这样的软件包始终可用(。因此,部署到不太宽容的Docker上容器环境在我的项目中发现了一些潜在的错误。

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

  • 问题:枪角兽(或您选择的服务器(必须安装在码头工人容器的路径。

    • 虽然这看起来很明显,但我遇到了麻烦,因为我包括 gunicorn在我的项目的requirements.txt文件中。不幸的是,我是使用只能安装 source 的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 容器的脚本可以在本地运行这里。

有关工作示例,请查看我的项目。

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

相关内容

  • 没有找到相关文章

最新更新