Google Cloud Build - firebase 部署错误:“公共目录 'dist/browser' 不存在,无法将托管部署到站点 PROJECT-ID”

Posted

技术标签:

【中文标题】Google Cloud Build - firebase 部署错误:“公共目录 \'dist/browser\' 不存在,无法将托管部署到站点 PROJECT-ID”【英文标题】:Google Cloud Build - firebase deployment error: "public directory 'dist/browser' does not exist, can't deploy hosting to site PROJECT-ID"Google Cloud Build - firebase 部署错误:“公共目录 'dist/browser' 不存在,无法将托管部署到站点 PROJECT-ID” 【发布时间】:2021-06-14 15:27:17 【问题描述】:

我正在尝试同时将我的 Angular Universal Web 应用部署到 Cloud Run(用于 s-s-r)和 Firebase 托管(用于缓存)。 Cloud Run 的部署工作正常,我按照本指南 (https://cloud.google.com/build/docs/deploying-builds/deploy-firebase#using_the_firebase_community_builder) 使用 Google Cloud Build 启用 Firebase 部署。

但是,每当我运行 gcloud builds submit --config=cloudbuild.yaml 时,都会在 cloudbuild.yaml 的 Firebase 部署步骤中抛出错误:public directory 'dist/browser' does not exist, can't deploy hosting to site PROJECT-ID

cloudbuild.yaml:

steps:
  # build image
  - name: 'gcr.io/cloud-builders/docker'
    args: [ 'build', '-t', 'gcr.io/PROJECT-ID/SERVICE-ID', '.' ]
  # push image
  - name: 'gcr.io/cloud-builders/docker'
    args: ['push', 'gcr.io/PROJECT-ID/SERVICE-ID']
  # deploy to Cloud Run
  - name: "gcr.io/cloud-builders/gcloud"
    args: [ "run", "deploy", "SERVICE-ID", "--image", "gcr.io/PROJECT-ID/SERVICE-ID", "--region", "us-central1", "--platform", "managed", "--allow-unauthenticated" ]
  # deploy to Firebase (ERROR HAPPENS HERE Specified public directory 'xx' does not exist, can't deploy hosting to site PROJECT-ID)
  - name: gcr.io/PROJECT-ID/firebase
    args: ['deploy', '--project=PROJECT-ID', '--only=hosting']
images:
  - 'gcr.io/PROJECT-ID/SERVICE-ID'
timeout: 1800s
substitutions:
  _ENV_VARIABLE: development

Dockerfile

FROM node:14

# set work directory
WORKDIR usr/src/app

# copy package.json and package-lock
COPY package*.json ./

# install dependencies
RUN npm install

# copy local code to container
COPY . .

# build app
RUN npm run build:s-s-r

# serve app
CMD ["npm", "run", "serve:s-s-r"]

firebase.json


...
  "hosting": [
    
      "public": "dist/browser",
      "ignore": [
        "**/.*"
      ],
      ...
    
  ]
...

error-log

DEBUG: https://storage.googleapis.com:443 "GET /987290120943.cloudbuild-logs.googleusercontent.com/log-93082fbf-1b87-499a-9132-fed5f1c06aad.txt HTTP/1.1" 206 290
DEBUG: Reading GCS logfile: 206 (read 290 bytes)
Step #3:
Step #3: ←[1m←[37m===←[39m Deploying to 'PROJECT-ID'...←[22m
Step #3:
Step #3: ←[1m←[36mi ←[39m←[22m deploying ←[1mhosting←[22m
Step #3:
Step #3: ←[1m←[31mError:←[39m←[22m Specified public directory 'dist/browser' does not exist, can't deploy hosting to site PROJECT-ID
DEBUG: https://cloudbuild.googleapis.com:443 "GET /v1/projects/PROJECT-ID/locations/global/builds/93082fbf-1b87-499a-9132-fed5f1c06aad?alt=json HTTP/1.1" 200 None
DEBUG: https://storage.googleapis.com:443 "GET /987290120943.cloudbuild-logs.googleusercontent.com/log-93082fbf-1b87-499a-9132-fed5f1c06aad.txt HTTP/1.1" 206 120
DEBUG: Reading GCS logfile: 206 (read 120 bytes)
Finished Step #3
ERROR
ERROR: build step 3 "gcr.io/PROJECT-ID/firebase" failed: step exited with non-zero status: 1
DEBUG: https://storage.googleapis.com:443 "GET /987290120943.cloudbuild-logs.googleusercontent.com/log-93082fbf-1b87-499a-9132-fed5f1c06aad.txt HTTP/1.1" 416 168
DEBUG: Reading GCS logfile: 416 (no new content; keep polling)

由于在本地一切正常,我认为它可能必须与 gcr.io/PROJECT-ID/firebase 位于与服务 gcr.io/PROJECT-ID/SERVICE-ID 不同的容器中,而 dist 文件夹可能在其中创建。

编辑#1:

我测试了在项目的根目录中创建一个名为“static”的文件夹,并将firebase.json 中的public 属性更改为“static”。它起作用了,这让我相信由于某种原因dist/browser 目录在cloudbuild.yaml 的“部署到 Firebase”步骤期间不存在,即使它是在DockerfileRUN npm run build:s-s-r 期间创建的。

编辑#2:

我在类似的问题上发现了一些不太充分的东西 (https://***.com/a/64215324/8581106)。但是,建议似乎是在 cloudbuild.yaml 中的 Firebase 部署之前运行构建命令 npm run build:s-s-r 以确保存在 dist/browser 目录。但我真的很想避免在 Cloud Run 上提供一个构建并将新构建部署到 Firebase,因为 Angular 每次都对 .js.css 文件使用唯一的哈希,我觉得这可能会导致缓存问题。

编辑#3:

我创建了一个图像来更好地可视化我的问题(见下图)。我是 docker 和 Cloud Build 的新手,但我觉得这是我运行 gcloud builds submit --config=cloudbuild.yaml 时的过程。我不明白为什么dist/browser 存在于Dockerfile 范围内但不在cloudbuild.yaml 范围内。

【问题讨论】:

能否分享gcloud builds submit --config=cloudbuild.yaml -verbosity="debug"的日志输出,以确认出现问题的步骤? @FaridShumbar 我将在接下来的几个小时内发布日志。但是,我觉得我知道问题发生在哪里,但我不知道如何解决它。问题可能是dist/browser 目录仅存在于调用npm run buid:s-s-rDockerfile 上下文中,而不存在于我想将dist/browser 目录部署到Firebase 的cloudbuild.yaml 中。也许上面的图片更能说明这一点。 【参考方案1】:

根据https://***.com/a/66714846/8581106,我无法访问cloudbuild.yaml内的dist/browser目录,因为该目录是通过Dockerfile在不同的上下文中创建的。

目前,我找到的唯一解决方案是在将构建部署到 Cloud Run 后立即将一个空文件夹部署到 Firebase 托管。据我了解,用户现在向 Firebase 托管发出请求,如果它已经缓存在 Firebase 托管服务器上,则获得响应。如果请求的数据没有被缓存,firebase.json 中的rewrites 允许从 Cloud Run 获取渲染的数据,并在可能的情况下缓存它。

虽然它似乎有效,但我不知道来自 Cloud Run 的文件是否正确缓存在 Firebase 主机上,此外,由于缺少对文本、图像和之前由 Firebase Hosting 自动管理的文件。不过,目前这是最可行的解决方案。

【讨论】:

以上是关于Google Cloud Build - firebase 部署错误:“公共目录 'dist/browser' 不存在,无法将托管部署到站点 PROJECT-ID”的主要内容,如果未能解决你的问题,请参考以下文章

Google Cloud Build 中的环境变量

Google Cloud Build 可以通过工件目录递归吗?

在 Google Cloud Build 上使用 Docker Buildkit

从 Google Cloud Build 访问存储在 Google Secret Manager 中的环境变量

Google Cloud Build - 查看日志权限

如何通过 cli / rest api / cloud 功能运行 Google Cloud Build 触发器?