Gcloud app deploy 不能忽略 Dockerfile

Gcloud app deploy cannot ignore Dockerfile

我通常将 NodeJS 应用程序部署到 Google App Engine 并在通过 .gcloudignore 文件部署时忽略所有 docker 资产,如下所示:

.git
.gitignore
Dockerfile
docker-compose.yml
nginx/
redis-data/
.vscode/
.DS_Store
.prettierrc
README.md
node_modules/
.env

上周我成功地将我的应用程序部署到 App Engine,没有任何问题。但是今天(除了源代码之外没有任何更改)它失败了并给我一个错误:

ERROR: (gcloud.app.deploy) There is a Dockerfile in the current directory, and the runtime field in /Users/tranphongbb/Works/unstatic/habitify-annual-report-backend/app.yaml is currently set to [runtime: nodejs]. To use your Dockerfile to build a custom runtime, set the runtime field to [runtime: custom]. To continue using the [nodejs] runtime, please remove the Dockerfile from this directory.

即使删除 .gcloudignore 文件并使用 app.yaml 中的 skip_files 选项,它仍然失败。

我的源码树:

.dockerignore
.eslintrc.json
.gcloudignore
.gitignore
.prettierrc
.vscode
Dockerfile
README.md
app.yaml
docker-compose.yml
nginx
package.json
src

我通过克隆 Node.js App Engine Flex 快速入门并将 Dockerfile 添加到与 app.yaml 文件相同的文件夹来重现了您的问题。 确实,我收到了与您相同的错误消息。但是我能够看到,如果我将 Dockerfile 移动到不同的目录,部署就会成功。 gcloud app deploy 似乎不遵守 .gcloudignore 文件。

对于灵活环境中的 node.js,App Engine Official Documentation 中没有 skip_files 条目。

要忽略 .gcloudignore 文件中定义的文件,请 运行 命令 gcloud beta app deploy 在 app.yaml 中使用 Nodejs Runtime 时我可以忽略 Dockerfile 或者你可以使用gcloud app deploy 命令,但将 Dockerfile 移动到另一个目录。

.gcloudignore 文件的目的是避免将某些文件上传到 App Engine、Cloud Functions 等已记录的部署 here。当使用 gcloud app deploy 时,此命令会注意到是否存在 Dockerfile 并将关联 app.yaml 中设置的 runtime: custom。如果不满足该条件,您将收到类似如下的错误消息:

ERROR: (gcloud.app.deploy) There is a Dockerfile in the current directory, and the runtime field in path/app.yaml is currently set to [runtime: nodejs]. To use your Dockerfile to build a custom runtime, set the runtime field to [runtime: custom]. To continue using the [nodejs] runtime, please remove the Dockerfile from this directory.

现在是最后一个问题,为什么这适用于 gcloud beta app deploy 而不是 gcloud app deploy

查看任何人都可以查看的Cloud SDK源代码,gcloud app deploy有如下代码进行了前面提到的验证:

if info.runtime == 'custom':
    if has_dockerfile and has_cloudbuild:
      raise CustomRuntimeFilesError(
          ('A custom runtime must have exactly one of [{}] and [{}] in the '
           'source directory; [{}] contains both').format(
               config.DOCKERFILE, runtime_builders.Resolver.CLOUDBUILD_FILE,
               source_dir))
    elif has_dockerfile:
      log.info('Using %s found in %s', config.DOCKERFILE, source_dir)
      return False
    elif has_cloudbuild:
      log.info('Not using %s because cloudbuild.yaml was found instead.',
               config.DOCKERFILE)
      return True
    else:
      raise NoDockerfileError(
          'You must provide your own Dockerfile when using a custom runtime. '
          'Otherwise provide a "runtime" field with one of the supported '
          'runtimes.')
  else:
    if has_dockerfile:
      raise DockerfileError(
          'There is a Dockerfile in the current directory, and the runtime '
          'field in {0} is currently set to [runtime: {1}]. To use your '
          'Dockerfile to build a custom runtime, set the runtime field to '
          '[runtime: custom]. To continue using the [{1}] runtime, please '
          'remove the Dockerfile from this directory.'.format(info.file,

另一方面,gcloud beta app deploy 根本不进行此验证(假设我查看了正确的代码):

if runtime == 'custom' and self in (self.ALWAYS,
                                    self.WHITELIST_BETA,
                                    self.WHITELIST_GA):
  return needs_dockerfile

总而言之,.gcloudignore 会阻止一些 files/folder 的上传,但在对此命令进行一些预检查时不会考虑。在这种情况下,应考虑 Dockerfile,因为它可能是部署的一部分。