无法 运行 Google App Engine 自定义托管 VM:--custom-entrypoint 必须设置错误

Cannot run Google App Engine custom managed VM: --custom-entrypoint must be set error

问题描述

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

来自googledocumentation,以下Dockerfile指定标准python27运行时间:

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

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

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

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 请求。

我发现的另外两个相关的 Whosebug 问题没有帮助。接受的答案似乎表明这是已解决的 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 生成的 Dockerfile 中复制粘贴的使用 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

更新

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

(虽然我做不到,但我并没有很努力)


有一条完全没有记录但绝对必要的信息w.r.t。自定义托管 VM:

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

如果您认为这个重要事实会在任何理智的地方被提及,比如自定义托管 VM 的文档页面,或 dev_appserver.py,甚至 运行 dev_appserver.py,那么您给 Google 太多的信任了。

我唯一能找到关于此的任何类型声明的地方是 github 上 appengine-java-vm-guestbook-extras demo 的自述文件(严肃地说):

The Cloud SDK does not support anymore running custom runtimes when a Dockerfile is provided. You'll have to deploy the application to App Engine

Google 不关心:

  1. 实施这一基本且重要的功能。
  2. 开发服务器缺少如此重要功能的文档。
  3. 当用户厌倦执行操作时给出任何合理的错误消息。

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

编辑 1:由 user862857 编辑的解决方案 post 利用 Docker 本身构建图像来自 Docker 文件和 运行 它们在容器中。这也是在开发环境中 运行 管理 VM 和自定义运行时的好方法。


接受的答案似乎不正确。在处理快速发展的 Beta 产品时,github 自述文件的权威性不应胜过 official docs。使用 OP 的 post、

中提到的 Docker 文件,开发环境中的 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=whosebug.com 发送请求以查看实际效果。


N.B.

如果他们希望完全脱离 python-compat 运行time 并简单地 deploy/test 通过 python WSGI 应用程序,他们也可以使用 --custom_entrypoint 标志,只要他们有一个命令可以在合适的端口上启动 运行ning 适当的 WSGI 应用程序(这样的命令将是 uwsgi or gunicorn)。

在尝试让我的自定义 VM 更好地与 dev_appserver 一起工作之后 一天的一部分,接受 对此 post 的回答 作为 非常不愉快的惊喜。但我认为部署开发服务器不会那么那么麻烦,因为毕竟 VM 是标准 Docker 映像。

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

麻烦的来源

首先,我发现 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 容器的脚本 运行ning 本地可用 here.

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

如果您有任何评论、功能请求或写得更漂亮,请告诉我 bash 比我高(我觉得我在这方面把门槛定得很低)。