托管静态网站

本教程介绍了如何配置 Cloud Storage 存储分区以便为您拥有的网域托管静态网站。静态网页可使用 HTML、CSS 和 JavaScript 等客户端技术。静态网页不能包含动态内容,例如 PHP 等服务器端脚本。

由于 Cloud Storage 本身不支持 HTTPS,因此本教程将 Cloud Storage 与 HTTP(S) 负载平衡搭配使用,以通过 HTTPS 传送自定义网域中的内容。如需了解通过 HTTPS 从自定义网域传送内容的更多方式,请参阅相关问题排查主题。您还可以使用 Cloud Storage 来通过 HTTP 传送自定义网域内容,这不需要负载平衡器。

如需查看有关静态网页的示例和提示(包括如何为动态网站托管静态资源),请参阅静态网站页面

目标

本教程将介绍如何执行以下操作:

  • 创建存储分区。
  • 上传和共享您的网站的文件。
  • 设置负载平衡器和 SSL 证书。
  • 将负载平衡器连接到您的存储分区。
  • 使用 A 记录将您的网域指向负载平衡器。
  • 测试网站。

费用

本教程使用 Google Cloud 的以下收费组件:

  • Cloud Storage
  • Cloud Load Balancing

如需详细了解托管静态网站时可能产生的费用,请参阅关于监控费用的提示;如需详细了解 Cloud Storage 费用,请参阅价格页面。

准备工作

  1. 登录您的 Google 帐号。

    如果您还没有 Google 帐号,请注册一个新帐号

  2. 在 Cloud Console 的项目选择器页面上,选择或创建 Cloud 项目。

    转到项目选择器页面

  3. 确保您的 Google Cloud 项目已启用结算功能。 了解如何确认您的项目已启用结算功能

  4. 准备一个归您所有或管理的域名。如果您还没有现成可用的域名,可以通过多项服务(例如 Google Domains)注册一个新域名。

    本教程使用的域名是 example.com

  5. 确认您是要使用的域名的所有者或管理员。确保您所验证的域名是顶级域名(如 example.com),而不是子域名(如 www.example.com)。

    注意:如果您是要关联到存储分区的网域的所有者,则说明您过去可能已经执行此步骤。如果您的网域是通过 Google Domains 购买的,那么系统会自动进行验证。

  6. 准备一些您要传送的网站文件。如果您至少有一个索引页面 (index.html) 和 404 页面 (404.html),那么最适合使用本教程。
  7. 确保您拥有项目的 Owner 或 Editor 角色,或者拥有以下 Identity and Access Management 角色:Storage Object AdminNetwork Admin

创建存储分区

如需创建名为 www.example.com 的存储分区,请执行以下操作:

控制台

  1. 在 Google Cloud Console 中打开 Cloud Storage 浏览器。
    打开 Cloud Storage 浏览器
  2. 点击创建存储分区,打开存储分区创建表单。

  3. 输入您的存储分区信息,然后点击继续以完成各个步骤:

    • 设置您的存储分区的名称,我们建议您将该名称设置为与域名相同,以方便后续步骤。例如 www.example.com

    • 选择存储分区的位置类型位置。例如,地区us-east1

    • 选择 Standard 存储空间 (Standard Storage) 作为存储类别

    • 访问权限控制中选择统一

  4. 点击创建

如果成功,则“存储分区详情”页面将打开并显示“此存储分区中没有任何活跃对象”的文本。

请参阅问题排查,了解如何获取有关 Cloud Storage 浏览器中失败操作的详细错误信息。

gsutil

使用 gsutil mb 命令:

gsutil mb -b on gs://www.example.com

如果成功,此命令会返回以下内容:

Creating gs://www.example.com/...

代码示例

C++

如需了解详情,请参阅 Cloud Storage C++ API 参考文档

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name) {
  StatusOr<gcs::BucketMetadata> bucket_metadata =
      client.CreateBucket(bucket_name, gcs::BucketMetadata());

  if (!bucket_metadata) {
    throw std::runtime_error(bucket_metadata.status().message());
  }

  std::cout << "Bucket " << bucket_metadata->name() << " created."
            << "\nFull Metadata: " << *bucket_metadata << "\n";
}

C#

如需了解详情,请参阅 Cloud Storage C# API 参考文档

public static Bucket StorageCreateBucket(string projectId, string bucketName)
{
    var storage = StorageClient.Create();
    var bucket = storage.CreateBucket(projectId, bucketName);
    Console.WriteLine($"Created {bucketName}.");
    return bucket;
}

Go

如需了解详情,请参阅 Cloud Storage Go API 参考文档

ctx := context.Background()
bucket := client.Bucket(bucketName)

ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()
if err := bucket.Create(ctx, projectID, &storage.BucketAttrs{
	StorageClass: "COLDLINE",
	Location:     "asia",
}); err != nil {
	return err
}

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.BucketInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageClass;
import com.google.cloud.storage.StorageOptions;

public class CreateBucketWithStorageClassAndLocation {
  public static void createBucketWithStorageClassAndLocation(String projectId, String bucketName) {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID to give your GCS bucket
    // String bucketName = "your-unique-bucket-name";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();

    // See the StorageClass documentation for other valid storage classes:
    // https://googleapis.dev/java/google-cloud-clients/latest/com/google/cloud/storage/StorageClass.html
    StorageClass storageClass = StorageClass.COLDLINE;

    // See this documentation for other valid locations:
    // http://g.co/cloud/storage/docs/bucket-locations#location-mr
    String location = "ASIA";

    Bucket bucket =
        storage.create(
            BucketInfo.newBuilder(bucketName)
                .setStorageClass(storageClass)
                .setLocation(location)
                .build());

    System.out.println(
        "Created bucket "
            + bucket.getName()
            + " in "
            + bucket.getLocation()
            + " with storage class "
            + bucket.getStorageClass());
  }
}

Node.js

如需了解详情,请参阅 Cloud Storage Node.js API 参考文档

/**
 * TODO(developer): Uncomment the following line before running the sample.
 */
// const bucketName = 'Name of a bucket, e.g. my-bucket';

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

async function createBucket() {
  // Creates a new bucket in the Asia region with the coldline default storage
  // class. Leave the second argument blank for default settings.
  //
  // For default values see: https://cloud.google.com/storage/docs/locations and
  // https://cloud.google.com/storage/docs/storage-classes

  const [bucket] = await storage.createBucket(bucketName, {
    location: 'ASIA',
    storageClass: 'COLDLINE',
  });

  console.log(`Bucket ${bucket.name} created.`);
}

createBucket().catch(console.error);

PHP

如需了解详情,请参阅 Cloud Storage PHP API 参考文档

use Google\Cloud\Storage\StorageClient;

/**
 * Create a Cloud Storage Bucket.
 *
 * @param string $bucketName name of the bucket to create.
 * @param string $options options for the new bucket.
 *
 */
function create_bucket($bucketName, $options = [])
{
    $storage = new StorageClient();
    $bucket = $storage->createBucket($bucketName, $options);
    printf('Bucket created: %s' . PHP_EOL, $bucket->name());
}

Python

如需了解详情,请参阅 Cloud Storage Python API 参考文档

from google.cloud import storage

def create_bucket(bucket_name):
    """Creates a new bucket."""
    # bucket_name = "your-new-bucket-name"

    storage_client = storage.Client()

    bucket = storage_client.create_bucket(bucket_name)

    print("Bucket {} created".format(bucket.name))

Ruby

如需了解详情,请参阅 Cloud Storage Ruby API 参考文档

# bucket_name   = "Name of Google Cloud Storage bucket to create"
# location      = "Location of where to create Cloud Storage bucket"
# storage_class = "Storage class of Cloud Storage bucket"

require "google/cloud/storage"

storage = Google::Cloud::Storage.new
bucket  = storage.create_bucket bucket_name,
                                location:      location,
                                storage_class: storage_class

puts "Created bucket #{bucket.name} in #{location}" \
     " with #{storage_class} class"

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个将您的网站名称分配给 name 属性的 .json 文件:

    {
      "name": "www.example.com"
    }
  3. 使用 cURL 调用 JSON API。对于 www.example.com:

    curl -X POST --data-binary @website-bucket-name.json \
      -H "Authorization: Bearer ya29.AHES6ZRVmB7fkLtd1XTmq6mo0S1wqZZi3-Lh_s-6Uw7p8vtgSwg" \
      -H "Content-Type: application/json" \
      "https://storage.googleapis.com/storage/v1/b?project=my-static-website"

XML API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 使用 cURL 调用 XML API,以使用您的网站名称创建一个存储分区。对于 www.example.com:

    curl -X PUT \
      -H "Authorization: Bearer ya29.AHES6ZRVmB7fkLtd1XTmq6mo0S1wqZZi3-Lh_s-6Uw7p8vtgSwg" \
      -H "x-goog-project-id: my-static-website" \
      "https://storage.googleapis.com/www.example.com"

上传网站的文件

将您希望网站传送的文件添加到您的存储分区中:

控制台

  1. 在 Google Cloud Console 中打开 Cloud Storage 浏览器。
    打开 Cloud Storage 浏览器
  2. 在存储分区列表中,点击您创建的存储分区的名称。

    此时会打开“存储分区详情”页面,其中“对象”标签页已选中。

  3. 点击上传文件按钮。

  4. 在文件对话框中,浏览至所需文件并将其选中。

上传完成后,您应该会看到文件名和存储分区中显示的文件信息。

请参阅问题排查,了解如何获取有关 Cloud Storage 浏览器中失败操作的详细错误信息。

gsutil

使用 gsutil cp 命令将文件复制到您的存储分区。例如,要从文件 index.html 的当前位置 Desktop 复制此文件,请使用以下命令:

gsutil cp Desktop/index.html gs://www.example.com

如果成功,此命令会返回以下内容:

Copying file://Desktop/index.html [Content-Type=text/html]...
Uploading   gs://www.example.com/index.html:       0 B/2.58 KiB
Uploading   gs://www.example.com/index.html:       2.58 KiB/2.58 KiB

代码示例

C++

如需了解详情,请参阅 Cloud Storage C++ API 参考文档

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& file_name,
   std::string const& bucket_name, std::string const& object_name) {
  // Note that the client library automatically computes a hash on the
  // client-side to verify data integrity during transmission.
  StatusOr<gcs::ObjectMetadata> metadata = client.UploadFile(
      file_name, bucket_name, object_name, gcs::IfGenerationMatch(0));
  if (!metadata) throw std::runtime_error(metadata.status().message());

  std::cout << "Uploaded " << file_name << " to object " << metadata->name()
            << " in bucket " << metadata->bucket()
            << "\nFull metadata: " << *metadata << "\n";
}

C#

如需了解详情,请参阅 Cloud Storage C# API 参考文档

private void UploadFile(string bucketName, string localPath,
    string objectName = null)
{
    var storage = StorageClient.Create();
    using (var f = File.OpenRead(localPath))
    {
        objectName = objectName ?? Path.GetFileName(localPath);
        storage.UploadObject(bucketName, objectName, null, f);
        Console.WriteLine($"Uploaded {objectName}.");
    }
}

Go

如需了解详情,请参阅 Cloud Storage Go API 参考文档

import (
	"context"
	"fmt"
	"io"
	"os"
	"time"

	"cloud.google.com/go/storage"
)

// uploadFile uploads an object.
func uploadFile(w io.Writer, bucket, object string) error {
	// bucket := "bucket-name"
	// object := "object-name"
	ctx := context.Background()
	client, err := storage.NewClient(ctx)
	if err != nil {
		return fmt.Errorf("storage.NewClient: %v", err)
	}
	defer client.Close()

	// Open local file.
	f, err := os.Open("notes.txt")
	if err != nil {
		return fmt.Errorf("os.Open: %v", err)
	}
	defer f.Close()

	ctx, cancel := context.WithTimeout(ctx, time.Second*50)
	defer cancel()

	// Upload an object with storage.Writer.
	wc := client.Bucket(bucket).Object(object).NewWriter(ctx)
	if _, err = io.Copy(wc, f); err != nil {
		return fmt.Errorf("io.Copy: %v", err)
	}
	if err := wc.Close(); err != nil {
		return fmt.Errorf("Writer.Close: %v", err)
	}
	fmt.Fprintf(w, "Blob %v uploaded.\n", object)
	return nil
}

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

import com.google.cloud.storage.BlobId;
import com.google.cloud.storage.BlobInfo;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class UploadObject {
  public static void uploadObject(
      String projectId, String bucketName, String objectName, String filePath) throws IOException {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID of your GCS bucket
    // String bucketName = "your-unique-bucket-name";

    // The ID of your GCS object
    // String objectName = "your-object-name";

    // The path to your file to upload
    // String filePath = "path/to/your/file"

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    BlobId blobId = BlobId.of(bucketName, objectName);
    BlobInfo blobInfo = BlobInfo.newBuilder(blobId).build();
    storage.create(blobInfo, Files.readAllBytes(Paths.get(filePath)));

    System.out.println(
        "File " + filePath + " uploaded to bucket " + bucketName + " as " + objectName);
  }
}

Node.js

如需了解详情,请参阅 Cloud Storage Node.js API 参考文档

/**
 * TODO(developer): Uncomment the following lines before running the sample.
 */
// const bucketName = 'Name of a bucket, e.g. my-bucket';
// const filename = 'Local file to upload, e.g. ./local/path/to/file.txt';

// Imports the Google Cloud client library
const {Storage} = require('@google-cloud/storage');

// Creates a client
const storage = new Storage();

async function uploadFile() {
  // Uploads a local file to the bucket
  await storage.bucket(bucketName).upload(filename, {
    // Support for HTTP requests made with `Accept-Encoding: gzip`
    gzip: true,
    // By setting the option `destination`, you can change the name of the
    // object you are uploading to a bucket.
    metadata: {
      // Enable long-lived HTTP caching headers
      // Use only if the contents of the file will never change
      // (If the contents will change, use cacheControl: 'no-cache')
      cacheControl: 'public, max-age=31536000',
    },
  });

  console.log(`${filename} uploaded to ${bucketName}.`);
}

uploadFile().catch(console.error);

PHP

如需了解详情,请参阅 Cloud Storage PHP API 参考文档

use Google\Cloud\Storage\StorageClient;

/**
 * Upload a file.
 *
 * @param string $bucketName the name of your Google Cloud bucket.
 * @param string $objectName the name of the object.
 * @param string $source the path to the file to upload.
 *
 * @return Psr\Http\Message\StreamInterface
 */
function upload_object($bucketName, $objectName, $source)
{
    $storage = new StorageClient();
    $file = fopen($source, 'r');
    $bucket = $storage->bucket($bucketName);
    $object = $bucket->upload($file, [
        'name' => $objectName
    ]);
    printf('Uploaded %s to gs://%s/%s' . PHP_EOL, basename($source), $bucketName, $objectName);
}

Python

如需了解详情,请参阅 Cloud Storage Python API 参考文档

使用 Blob.upload_from_file()Blob.upload_from_filename()Blob.upload_from_string() 方法上传对象。
from google.cloud import storage

def upload_blob(bucket_name, source_file_name, destination_blob_name):
    """Uploads a file to the bucket."""
    # bucket_name = "your-bucket-name"
    # source_file_name = "local/path/to/file"
    # destination_blob_name = "storage-object-name"

    storage_client = storage.Client()
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(destination_blob_name)

    blob.upload_from_filename(source_file_name)

    print(
        "File {} uploaded to {}.".format(
            source_file_name, destination_blob_name
        )
    )

Ruby

如需了解详情,请参阅 Cloud Storage Ruby API 参考文档

# bucket_name       = "Your Google Cloud Storage bucket name"
# local_file_path   = "Path to local file to upload"
# storage_file_path = "Path to store the file in Google Cloud Storage"

require "google/cloud/storage"

storage = Google::Cloud::Storage.new
bucket  = storage.bucket bucket_name

file = bucket.create_file local_file_path, storage_file_path

puts "Uploaded #{file.name}"

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 通过 POST Object 请求,使用 cURL 调用 JSON API。对于 www.example.com 的索引页面:

    curl -X POST --data-binary @index.html \
      -H "Content-Type: text/html" \
      -H "Authorization: Bearer ya29.AHES6ZRVmB7fkLtd1XTmq6mo0S1wqZZi3-Lh_s-6Uw7p8vtgSwg" \
      "https://storage.googleapis.com/upload/storage/v1/b/www.example.com/o?uploadType=media&name=index.html"

XML API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 通过 PUT Object 请求,使用 cURL 调用 XML API。对于 www.example.com 的索引页面:

    curl -X PUT --data-binary @index.html \
      -H "Authorization: Bearer ya29.AHES6ZRVmB7fkLtd1XTmq6mo0S1wqZZi3-Lh_s-6Uw7p8vtgSwg" \
      -H "Content-Type: text/html" \
      "https://storage.googleapis.com/www.example.com/index.html"

共享您的文件

如需将存储分区中的所有对象设为可供公共互联网上的所有人读取,请执行以下操作:

控制台

  1. 在 Google Cloud Console 中打开 Cloud Storage 浏览器。
    打开 Cloud Storage 浏览器
  2. 在存储分区列表中,点击要公开的存储分区的名称。

  3. 选择页面顶部附近的权限标签。

  4. 点击添加成员按钮。

    随即会显示“添加成员”对话框。

  5. 新成员字段中,输入 allUsers

  6. 选择角色下拉菜单中,选择 Cloud Storage 子菜单,然后点击 Storage Object Viewer 选项。

  7. 点击保存

  8. 点击允许公开访问

对象群组被公开共享后,“公共访问权限”列中会针对每个对象显示一个链接图标。您可以点击此图标来获取对象的网址。

请参阅问题排查,了解如何获取有关 Cloud Storage 浏览器中失败操作的详细错误信息。

gsutil

使用 gsutil iam ch 命令:

gsutil iam ch allUsers:objectViewer gs://www.example.com

代码示例

C++

如需了解详情,请参阅 Cloud Storage C++ API 参考文档

namespace gcs = google::cloud::storage;
using google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name) {
  StatusOr<google::cloud::IamPolicy> current_policy =
      client.GetBucketIamPolicy(bucket_name);

  if (!current_policy) {
    throw std::runtime_error(current_policy.status().message());
  }

  current_policy->bindings.AddMember("roles/storage.objectViewer",
                                     "allUsers");

  // Update the policy. Note the use of `gcs::IfMatchEtag` to implement
  // optimistic concurrency control.
  StatusOr<google::cloud::IamPolicy> updated_policy =
      client.SetBucketIamPolicy(bucket_name, *current_policy,
                                gcs::IfMatchEtag(current_policy->etag));

  if (!updated_policy) {
    throw std::runtime_error(current_policy.status().message());
  }

  auto role = updated_policy->bindings.find("roles/storage.objectViewer");
  if (role == updated_policy->bindings.end()) {
    std::cout << "Cannot find 'roles/storage.objectViewer' in the updated"
              << " policy. This can happen if another application updates"
              << " the IAM policy at the same time. Please retry the"
              << " operation.\n";
    return;
  }
  auto member = role->second.find("allUsers");
  if (member == role->second.end()) {
    std::cout << "'allUsers' is not a member of the"
              << " 'roles/storage.objectViewer' role in the updated"
              << " policy. This can happen if another application updates"
              << " the IAM policy at the same time. Please retry the"
              << " operation.\n";
    return;
  }
  std::cout << "IamPolicy successfully updated for bucket " << bucket_name
            << '\n';
}

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

import com.google.cloud.Identity;
import com.google.cloud.Policy;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;
import com.google.cloud.storage.StorageRoles;

public class MakeBucketPublic {
  public static void makeBucketPublic(String projectId, String bucketName) {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID of your GCS bucket
    // String bucketName = "your-unique-bucket-name";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    Policy originalPolicy = storage.getIamPolicy(bucketName);
    storage.setIamPolicy(
        bucketName,
        originalPolicy
            .toBuilder()
            .addIdentity(StorageRoles.objectViewer(), Identity.allUsers()) // All users can view
            .build());

    System.out.println("Bucket " + bucketName + " is now publicly readable");
  }
}

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个包含以下信息的 .json 文件:

    {
      "bindings":[
        {
          "role": "roles/storage.objectViewer",
          "members":["allUsers"]
        }
      ]
    }
  3. 使用 cURL,通过 PUT Bucket 请求调用 JSON API

    curl -X PUT --data-binary @[JSON_FILE_NAME].json \
      -H "Authorization: Bearer [OAUTH2_TOKEN]" \
      -H "Content-Type: application/json" \
      "https://storage.googleapis.com/storage/v1/b/[BUCKET_NAME]/iam"

    其中:

    • [JSON_FILE_NAME] 是您在第 2 步中创建的文件的名称。
    • [OAUTH2_TOKEN] 是您在第 1 步中创建的访问令牌。
    • [BUCKET_NAME] 是您要公开其对象的存储分区的名称。例如 my-bucket

XML API

XML API 不支持将存储分区中的所有对象设为可供公开读取。请改用 gsutil 或 JSON API,或为每个对象设置 ACL

如需将存储分区中的单个对象设为可公开访问,您需要将存储分区的访问权限控制模式切换为精细控制。通常,这样可以更轻松、更快地访问存储分区中的所有文件。

如果访问者向网址请求非公开或不存在的文件,他们会收到 http 403 响应代码。如需了解如何添加使用 http 404 响应代码的错误页面,请参阅下一部分。

推荐:分配专用页面

您可以分配索引页面后缀(由 MainPageSuffix 属性控制)和自定义错误页面(由 NotFoundPage 属性控制)。分配这些页面都是可选的,但如果没有索引页面,则当用户访问您的顶级网站(例如 https://www.example.com)时,将没有内容可以传送。如需详细了解 MainPageSuffixNotFoundPage 属性,请参阅专用页面

在以下示例中,MainPageSuffix 设置为 index.htmlNotFoundPage 设置为 404.html

控制台

  1. 在 Google Cloud Console 中打开 Cloud Storage 浏览器。
    打开 Cloud Storage 浏览器
  2. 在存储分区列表中,找到您所创建的存储分区。

  3. 点击与存储分区关联的存储分区溢出菜单 (),然后选择修改网站配置

  4. 在网站配置对话框中,指定主页面和错误页面。

  5. 点击保存

请参阅问题排查,了解如何获取有关 Cloud Storage 浏览器中失败操作的详细错误信息。

gsutil

使用 gsutil web set 命令设置 MainPageSuffix 属性(通过 -m 标志)和 NotFoundPage(通过 -e 标志):

gsutil web set -m index.html -e 404.html gs://www.example.com

如果成功,此命令会返回以下内容:

Setting website config on gs://www.example.com/...

代码示例

C++

如需了解详情,请参阅 Cloud Storage C++ API 参考文档

namespace gcs = google::cloud::storage;
using ::google::cloud::StatusOr;
[](gcs::Client client, std::string const& bucket_name,
   std::string const& main_page_suffix, std::string const& not_found_page) {
  StatusOr<gcs::BucketMetadata> original =
      client.GetBucketMetadata(bucket_name);

  if (!original) throw std::runtime_error(original.status().message());
  StatusOr<gcs::BucketMetadata> patched_metadata = client.PatchBucket(
      bucket_name,
      gcs::BucketMetadataPatchBuilder().SetWebsite(
          gcs::BucketWebsite{main_page_suffix, not_found_page}),
      gcs::IfMetagenerationMatch(original->metageneration()));

  if (!patched_metadata) {
    throw std::runtime_error(patched_metadata.status().message());
  }

  if (!patched_metadata->has_website()) {
    std::cout << "Static website configuration is not set for bucket "
              << patched_metadata->name() << "\n";
    return;
  }

  std::cout << "Static website configuration successfully set for bucket "
            << patched_metadata->name() << "\nNew main page suffix is: "
            << patched_metadata->website().main_page_suffix
            << "\nNew not found page is: "
            << patched_metadata->website().not_found_page << "\n";
}

Java

如需了解详情,请参阅 Cloud Storage Java API 参考文档

import com.google.cloud.storage.Bucket;
import com.google.cloud.storage.Storage;
import com.google.cloud.storage.StorageOptions;

public class SetBucketWebsiteInfo {
  public static void setBucketWesbiteInfo(
      String projectId, String bucketName, String indexPage, String notFoundPage) {
    // The ID of your GCP project
    // String projectId = "your-project-id";

    // The ID of your static website bucket
    // String bucketName = "www.example.com";

    // The index page for a static website bucket
    // String indexPage = "index.html";

    // The 404 page for a static website bucket
    // String notFoundPage = "404.html";

    Storage storage = StorageOptions.newBuilder().setProjectId(projectId).build().getService();
    Bucket bucket = storage.get(bucketName);
    bucket.toBuilder().setIndexPage(indexPage).setNotFoundPage(notFoundPage).build().update();

    System.out.println(
        "Static website bucket "
            + bucketName
            + " is set up to use "
            + indexPage
            + " as the index page and "
            + notFoundPage
            + " as the 404 page");
  }
}

REST API

JSON API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个 .json 文件,以将 website 对象中的 mainPageSuffixnotFoundPage 属性设置为所需页面:

    {
      "website":{
        "mainPageSuffix": "index.html",
        "notFoundPage": "404.html"
      }
    }
  3. 通过 PATCH Bucket 请求,使用 cURL 调用 JSON API。对于 www.example.com:

    curl -X PATCH --data-binary @web-config.json \
      -H "Authorization: Bearer ya29.AHES6ZRVmB7fkLtd1XTmq6mo0S1wqZZi3-Lh_s-6Uw7p8vtgSwg" \
      -H "Content-Type: application/json" \
      "https://storage.googleapis.com/storage/v1/b/www.example.com"

XML API

  1. OAuth 2.0 Playground 获取授权访问令牌。将 Playground 配置为使用您自己的 OAuth 凭据。
  2. 创建一个 .xml 文件,以将 WebsiteConfiguration 元素中的 MainPageSuffixNotFoundPage 元素设置为所需页面:

    <WebsiteConfiguration>
      <MainPageSuffix>index.html</MainPageSuffix>
      <NotFoundPage>404.html</NotFoundPage>
    </WebsiteConfiguration>
  3. 通过 PUT Bucket 请求和 websiteConfig 查询字符串参数,使用 cURL 调用 XML API。对于 www.example.com:

    curl -X PUT --data-binary @web-config.xml \
      -H "Authorization: Bearer ya29.AHES6ZRVmB7fkLtd1XTmq6mo0S1wqZZi3-Lh_s-6Uw7p8vtgSwg" \
      https://storage.googleapis.com/www.example.com?websiteConfig

设置负载平衡器和 SSL 证书

Cloud Storage 本身不支持 HTTPS,因此您还需要设置一份 SSL 证书(该证书会附加到 HTTPS 负载平衡器),以通过 HTTPS 传送您的网站。本部分介绍了如何将您的存储分区添加到负载平衡器的后端,以及如何将新的 Google 管理的 SSL 证书添加到负载平衡器的前端。

  1. 转到 Google Cloud Console 中的“负载平衡”页面。
    转到“负载平衡”页面
  2. HTTP(S) 负载平衡下,点击开始配置
  3. 选择从互联网到我的虚拟机,然后点击继续
  4. 为您的负载平衡器指定一个名称,例如 example-lb

配置后端

  1. 点击后端配置
  2. 创建或选择后端服务和后端存储分区下拉列表中,转到后端存储分区子菜单,然后点击创建后端存储分区选项。
  3. 为后端存储分区选择一个名称,例如 example-bucket
  4. 点击 Cloud Storage 存储分区下的浏览
  5. 选择 www.example.com 存储分区,然后点击选择
  6. 点击创建

配置主机规则和路径匹配器

主机规则和路径匹配器是外部 HTTP(S) 负载平衡器网址映射的配置组件。

  1. 点击主机和路径规则
  2. 保留您之前创建的后端存储分区 example-bucket 的默认简单主机和路径规则模式

配置前端

本部分介绍了如何配置 HTTPS 协议和创建 SSL 证书。您还可以选择现有证书或上传自行管理的 SSL 证书

  1. 点击前端配置
  2. 配置以下字段的值:

  3. 对于 IP 地址字段:

    1. 在下拉列表中,点击创建 IP 地址
    2. 预留新的静态 IP 地址弹出式窗口中,输入 example-ip 作为 IP 地址的名称
    3. 点击预留
  4. 端口中,选择 443

  5. 证书字段中,选择创建新证书。随即将在一个面板中显示证书创建表单。配置以下内容:

    • 名称example-ssl
    • 创建模式创建 Google 托管的证书
    • 网域www.example.com。如果您希望通过其他网域(例如根网域 example.com)传送内容,请按 Enter 键将这些网域添加到其他行。每个证书的网域上限为 100 个。
  6. 点击创建

  7. 点击完成

检查配置

  1. 点击检查并最终确定
  2. 检查后端配置主机和路径规则前端配置
  3. 点击创建

您可能需要等待几分钟才能创建负载平衡器。

将您的网域连接到负载平衡器

创建负载平衡器后,点击负载平衡器的名称:example-lb。请注意与负载平衡器关联的 IP 地址:例如 30.90.80.100。如需将您的网域指向负载平衡器,请使用您的网域注册服务创建 A 记录。如果您向 SSL 证书添加了多个网域,则必须为每个网域添加一条 A 记录,所有网域均指向负载平衡器的 IP 地址。例如,为 www.example.comexample.com 创建 A 记录:

NAME                  TYPE     DATA
www                   A        30.90.80.100
@                     A        30.90.80.100

如果您使用的是 Google Domains,请参阅创建 ACNAME 记录了解详情。

Google Cloud 最长可能需要 60-90 分钟来预配证书并通过负载平衡器提供网站。如需监控您的证书状态,请执行以下操作:

控制台

  1. 转到 Google Cloud Console 中的“负载平衡”页面。
    转到“负载平衡”页面
  2. 点击负载平衡器的名称:example-lb
  3. 点击与负载平衡器关联的 SSL 证书的名称:example-ssl
  4. 状态网域状态行显示了证书状态。两行都必须处于活跃状态,才能使证书对您的网站有效。

gcloud

  1. 如需检查证书状态,请运行以下命令:

    gcloud beta compute ssl-certificates describe certificate-name \
      --global \
      --format="get(name,managed.status)"
    
  2. 如需检查网域状态,请运行以下命令:

    gcloud beta compute ssl-certificates describe certificate-name \
      --global \
      --format="get(managed.domainStatus)"
    

如需详细了解证书状态,请参阅排查 SSL 证书问题

测试网站

SSL 证书生效后,请转到 https://www.example.com/test.html(其中 test.html 是存储在名为 www.example.com 的存储分区中的对象),验证是否已从存储分区传送内容。如果您设置了 MainPageSuffix 属性,则 https://www.example.com 会转到 index.html

清理

学完“托管静态网站”教程后,您可以清理在 Google Cloud 上创建的资源,以避免这些资源占用配额,日后产生费用。以下部分介绍如何删除或关闭这些资源。

删除项目

为了避免产生费用,最简单的方法是删除您为本教程创建的项目。

如需删除项目,请执行以下操作:

  1. 在 Cloud Console 中,转到管理资源页面。

    转到“管理资源”页面

  2. 在项目列表中,选择要删除的项目,然后点击删除
  3. 在对话框中输入项目 ID,然后点击关闭以删除项目。

删除负载平衡器和存储分区

如果您不想删除整个项目,请删除为教程创建的负载平衡器和存储分区:

  1. 转到 Google Cloud Console 中的“负载平衡”页面。
    转到“负载平衡”页面
  2. 选中 example-lb 旁边的复选框。
  3. 点击删除
  4. (可选)选中您要删除的资源以及负载平衡器(例如 www.example.com 存储分区或 example-ssl SSL 证书)旁边的复选框。
  5. 点击删除负载平衡器删除负载平衡器和所选的资源

后续步骤