Docker 化应用程序的 GCP 计算实例 VM 入门

本博客作为 GCP 入门教程,介绍将 Dockerized PHP 应用部署到 GCP“生产”环境的流程。包括设置 GCP 项目、创建服务帐户及密钥文件、配置 IAM 权限、设置 gcloud CLI 工具、验证 Docker 并将镜像推送到 GCP 注册表,还提及镜像存储在 Google 云存储桶的相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍

在下一个教程中,我们将通过 docker compose 将我们的 dockerized PHP 应用程序部署到“生产” ,并将在GCP(谷歌云平台)上创建这个“生产”环境。本教程作为 GCP 的入门知识,以建立一些基础知识,因为我们将使用该平台提供运行我们的 dockerized PHP 应用程序所需的所有基础设施

在此过程中,我们将了解GCP 项目作为我们自己在 GCP 中的“空间”,并将服务帐户作为一种以编程方式进行通信的方式。我们将从通过 UI 手动执行所有操作开始,但还将解释如何通过gcloudcli以编程方式执行此操作,并以完全自动化的脚本结束。

以下视频显示了整个流程:

我使用的 API 密钥(请参阅服务帐户密钥文件不在存储库中,因为我会为任何使用付费,即,您必须创建自己的项目和密钥才能跟进。

警告

遵循本教程中概述的步骤将产生成本,因为我们将创建“真正的”基础架构。它不会太多(几美分),而且很可能会包含在您试用 GCP(或一般无限GCP 免费层)时获得的 300 美元免费赠款中。

但是您仍然应该预先了解这一点,并确保关闭所有内容/删除所有内容,以防您自己尝试。“最安全”的方法是关闭(删除)整个项目

设置 GCP 项目

在 GCP 上,资源被组织在所谓的项目下。我们可以通过Create Project UI创建一个项目:

项目ID必须是全局唯一的string,我pl-dofroscra-p为本教程选择了(pl=> Pascal Landau;dofroscra=> Docker From Scratch;p=> 生产)。

创建服务帐户

下一步,我们需要一个可以用来发出 API 请求的服务帐户,因为我们不想使用我们的“个人 GCP 帐户”。服务帐户是通过IAM & Admin > Service Accounts UI创建的:

创建服务帐户密钥文件

为了以编程方式使用该帐户,我们还需要通过选择相应服务帐户的“管理密钥”选项来创建一个密钥文件。

其中$serviceAccountId是服务帐户的数字 ID,例如 109548647107864470967. 要创建密钥:
  • 单击"ADD KEY""Create new key"从下拉菜单中选择
    • 这将打开一个模式窗口来选择键类型。
  • 选择推荐的 JSON 类型并单击"Create"
    • 然后 GCP 将生成一个新的密钥对,存储公钥并提供下载的私钥文件。
  • 下载文件并确保像对待任何其他私钥(ssh、gpg、...)一样对待它,即永远不要公开分享它

我们将此文件存储在代码库的根目录gcp-service-account-key.json 中并将其添加到.gitignore文件中。

每个服务帐户还有一个唯一的电子邮件地址,由其(非数字)idproject id. 也可以直接在密钥文件中找到:

此电子邮件地址通常用于引用服务帐户,例如,在分配 IAM 权限时。

配置 IAM 权限

IAM代表身份和访问管理 (IAM),用于管理 GCP 上的权限。两个核心概念是“权限”和“角色”

  • 权限对于特定操作是细粒度的,例如storage.buckets.create创建云存储桶
  • 角色组合了一系列权限,例如,Cloud Storage Admin角色具有以下权限
    • storage.buckets.create
    • storage.buckets.get
    • 等等
  • 角色分配给用户(或服务帐户)

您可以在Permissions Reference中找到所有权限的完整概述以及了解角色 > 预定义角色下的所有角色。

在本教程中,我们将为服务帐户“ user”分配以下角色docker-php-tutorial-deployment@pl-dofroscra-p.iam.gserviceaccount.com

可以通过Cloud Console IAM 界面通过编辑相应的用户来分配角色。

注意: IAM 权限的更改可能需要一些时间(通常是几秒钟)才能生效。

设置 gcloud CLI 工具

GCP的CLI 工具称为 gcloud适用于所有操作系统

在本教程中,我们使用“捆绑 Python ”选项通过GoogleCloudSDKInstaller.exe在 Windows 上本地安装的版本 380.0.0。

仅供参考:如卸载 Google Cloud CLI中所述,您可以通过以下方式找到安装和配置目录:

<span style="color:#000000"><span style="background-color:#fbedbb"># installation directory
$ gcloud info --format='value(installation.sdk_root)'
C:\Users\Pascal\AppData\Local\Google\Cloud SDK\google-cloud-sdk

# config directory
$ gcloud info --format='value(config.paths.global_config_dir)'
C:\Users\Pascal\AppData\Roaming\gcloud </span></span>

不会使用我的个人 Google 帐户来运行gcloud命令,因此我不会通过运行gcloud init. 相反,我将使用我们之前创建的服务帐户并按照gcloud auth activate-service-account中的描述激活它

设置容器注册表

我们将在下一个教程部分中使用 docker compose 来运行我们的 PHP 应用程序,并且需要使我们的 docker 镜像容器注册表中可用。幸运的是,GCP 提供了一个 Container Registry 产品,它为我们提供了一个现成的私有注册表,作为 GCP 项目的一部分在我们可以使用它之前,必须启用相应的Google Container Registry API :

您可以在 Cloud Console 界面中的 Container Registry 下找到Container Registry

验证 Docker

由于 Container Registry 是私有的,我们需要在推送 docker 镜像之前进行身份验证GCP 文档“Container Registry Authentication methods”中描述了可用的身份验证方法。为了从我们的本地主机系统推送图像,我们将使用我们之前创建的服务帐户密钥文件并运行文档的“JSON 密钥文件”部分中显示的命令。

那么当我们运行这个命令时到底“发生”了什么?根据docker login 文档

当您登录时,该命令将凭据存储在 Linux 上的$HOME/.docker/config.json或 Windows 上的%USERPROFILE%/. docker/config.json [...]

Docker 引擎可以将用户凭据保存在外部凭据存储中,例如操作系统的本机钥匙串。[...]

您需要在$HOME/.docker/config.json中指定凭证存储来告诉 docker 引擎使用它。[...]

默认情况下,Docker 在每个平台上查找本机二进制文件,即osxkeychain在 macOS 上查找“ wincred”,在 Windows 上查找“ pass”,在 Linux 上查找“ ”。

换句话说:我将无法在任何地方以“纯文本”形式查看服务帐户密钥文件的内容,但 Docker 将利用操作系统特定的工具来安全地存储它们。在 Windows 上运行命令后,我在~/.docker/config.jsondocker login中找到了以下内容:

注册表

在本教程中,我们将创建一个超级简单的nginxalpine 图像,通过以下方式提供“Hello world” hello.html文件:

码头工人
<span style="color:#000000"><span style="background-color:#fbedbb">docker build -t my-nginx -f - . <<EOF
FROM nginx:<span style="color:#000080">1</span>.<span style="color:#000080">21</span>.5-alpine

RUN echo <span style="color:#800080">"</span><span style="color:#800080">Hello world"</span> >> /usr/share/nginx/html/hello.html

EOF</span></span>

图像的名称是my-nginx

码头工人
<span style="color:#000000"><span style="background-color:#fbedbb">$ docker image ls | grep my-nginx
my-nginx         latest             42dd1608d126   <span style="color:#000080">50</span> seconds ago    <span style="color:#000080">23</span>.5MB </span></span>

为了将映像推送到注册表映像名称必须以相应注册表为前缀。这让我很困惑,因为我本来希望能够运行这样的东西:

码头工人
<span style="color:#000000"><span style="background-color:#fbedbb">$ docker push my-nginx --registry=gcr.io

unknown flag: --registry
See <span style="color:#800080">'</span><span style="color:#800080">docker push --help'</span>. </span></span>

但是不,没有这样的--registry选择。更糟糕的是:省略它会导致推送到docker.io“默认”注册表:

码头工人
<span style="color:#000000"><span style="background-color:#fbedbb">$ docker push my-nginx
Using <span style="color:#0000ff">default</span> tag: latest
The push refers to repository [docker.io/my-nginx] </span></span>

根据有关推送和拉取图像的 GCP 文档,将图像推送到 GCP 注册表需要执行以下步骤:

  • 使用 Container Registry 中的目标路径标记映像,包括gcr.io注册表主机和项目 ID my-project
  • 将镜像推送到注册表

在我们的例子中,我们的 Container Registry 的目标路径是:

<span style="color:#000000"><span style="background-color:#fbedbb">gcr.io/pl-dofroscra-p </span></span>

因为pl-dofroscra-p我们之前创建的 GCP 项目的 id

完整的图像名称变为:

<span style="color:#000000"><span style="background-color:#fbedbb">gcr.io/pl-dofroscra-p/my-nginx </span></span>

要推送my-nginx图像,我们必须首先通过以下方式“添加另一个名称”docker tag

码头工人
<span style="color:#000000"><span style="background-color:#fbedbb">$ docker tag my-nginx gcr.io/pl-dofroscra-p/my-nginx

$ docker image ls
REPOSITORY                       TAG       IMAGE ID       CREATED          SIZE
my-nginx                         latest    ba7a2c5faf0d   <span style="color:#000080">15</span> minutes ago   <span style="color:#000080">23</span>.5MB
gcr.io/pl-dofroscra-p/my-nginx   latest    ba7a2c5faf0d   <span style="color:#000080">15</span> minutes ago   <span style="color:#000080">23</span>.5MB </span></span>

在之后推送该名称

码头工人
<span style="color:#000000"><span style="background-color:#fbedbb">$ docker push gcr.io/pl-dofroscra-p/my-nginx
Using <span style="color:#0000ff">default</span> tag: latest
The push refers to repository [gcr.io/pl-dofroscra-p/my-nginx]
134174afa9ad: Preparing
cb7b4430c52d: Preparing
419df8b60032: Preparing
0e835d02c1b5: Preparing
5ee3266a70bd: Preparing
3f87f0a06073: Preparing
1c9c1e42aafa: Preparing
8d3ac3489996: Preparing
8d3ac3489996: Waiting
3f87f0a06073: Waiting
1c9c1e42aafa: Waiting
cb7b4430c52d: Pushed
134174afa9ad: Pushed
419df8b60032: Pushed
5ee3266a70bd: Pushed
0e835d02c1b5: Pushed
8d3ac3489996: Layer already exists
3f87f0a06073: Pushed
1c9c1e42aafa: Pushed
latest: digest: sha256:0740591fb686227d8cdf4e42b784f634cbaf9f5caa6ee478e3bcc24aeef75d7f 
        size: <span style="color:#000080">1982</span> </span></span>

 

 

然后,您可以在 Container Registry的 UI 中找到该映像:

不用担心:我们不必每次推送前都进行标记,因为我们将设置为make在下一部分构建图像时自动使用正确的名称

图像存储在 Google 云存储桶中

我们将角色分配给Storage Admin之前包含storage.buckets.create权限的服务帐户。如果我们不这样做,就会发生以下错误:

<span style="color:#000000"><span style="background-color:#fbedbb">denied: Token exchange failed for project 'pl-dofroscra-p'. 
Caller does not have permission 'storage.buckets.create'. 
To configure permissions, follow instructions at: 
https://cloud.google.com/container-registry/docs/access-control </span></span>

Container Registry 尝试将 docker 镜像存储在 Google Cloud Storage 存储桶中,该存储桶在推送第一个镜像时动态创建,请参阅GCP 文档“添加注册表”

第一个图像推送到主机名会触发在项目中创建注册表和相应的 Cloud Storage 存储桶。此初始推送需要项目范围的权限才能创建存储桶。

您可以找到存储桶,在我的例子中,它在artifacts.pl-dofroscra-p.appspot.comCloud Storage UI中命名:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值