什么是云跑
Cloud Run 是一个 GCP(谷歌云平台)——托管服务允许我们部署和运行容器。 所以工作流程很简单:
- 编写应用程序代码
- 使用 Dockerfile 配置(构建、标记和推送映像)将应用程序容器化
- 将构建的镜像推送到容器注册表,例如 谷歌容器注册
- 使用 CLI 命令部署到 Cloud Run
Cloud Run 与 GKE(谷歌 Kubernetes 引擎)
乍一看,这两种服务都有一些相似之处,因为它们都允许我们在 GCP 环境中运行容器。
但是,简而言之,如果我们的应用程序或微服务不需要复杂的资源配置,则更可取的是 Cloud Run。 谷歌只是为我们做了繁重的工作。
另一方面,GKE 可以完全控制容器编排的各个方面,例如 网络、存储。 更多更深入的资源可以在最后的资源部分找到。
编码时间!
好了,说的够多了! 是时候启动并运行我们的应用程序了!
先决条件
本教程假设您熟悉以下主题:
- Node.js 和 Express 构建一个简单的 API
- Docker:如何编写 Dockerfile、构建、标记和推送 Docker 镜像
设置谷歌云项目
- 首先创建一个新的 Google Cloud 项目。 记下项目 ID,因为我们稍后将需要它。
- 安装并初始化 Google Cloud CLI。
启动一个简单的 Express API
让我们简单地创建一个新的 Express 应用程序。 它侦听 1 个端口上的流量并具有多个端点。 我们将在部署后测试端点。
import express, {Express, RequestHandler} from "express";
export const currentUserRouter: RequestHandler = (req, res) => {
res.status(200).json({
name: 'Current user'
})
}
const superUserRouter: RequestHandler = (req, res) => {
res.status(200).json({
name: 'Super user'
})
}
export const createServer = () => {
const app: Express = express();
app.use('/api/currentUser', currentUserRouter)
app.use('/api/superUser', superUserRouter)
app.use('/api', (req, res) => res.status(200).send('Hello World!'))
return app
}
import { createServer } from "./app";
const app = createServer()
const PORT = process.env.PORT || 3000
app.listen(PORT, () => {
console.log(`Server is running on port: ${PORT})`);
})
Dockerfile
现在让我们创建一个 Dockerfile 来将我们的 Express 应用程序构建到一个容器镜像中:
# Build dependencies
FROM node:17-alpine as dependencies
WORKDIR /app
COPY package.json .
RUN npm i
COPY . .
# Build production image
FROM dependencies as builder
RUN npm run build
EXPOSE 3000
CMD npm run start
请注意,我们使用的是 TypeScript,因此这是 npm run ___ 命令在 package.json 中的样子:
{
"scripts": {
"start": "node build/index.js",
"build": "tsc"
},
"devDependencies": {
"typescript": "4.6.3"
}
}
构建 Docker 镜像
让我们构建并标记 Docker 映像:
docker build -t eu.gcr.io/$PROJECT_ID/simple-express:0.0.1 .
我们正在使用 eu.gcr.io/* 标签,以便稍后我们可以将图像推送到 Google 的 Container Register 上。 $PROJECT_ID 是您的 Google Cloud 项目的 ID。
让我们验证一下镜像是否构建成功:
? simple-express git:(main) docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
eu.gcr.io/$PROJECT_ID/simple-express 0.0.1 a26c5f56ad6b 10 seconds ago 410M
将 Docker 镜像推送到 Cloud Registry
我们可以用命令行来做到这一点:
docker push eu.gcr.io/$PROJECT_ID/simple-express:0.0.1
然后我们可以使用 gcloud container CLI 命令来检查镜像是否已经存储在注册表中:
? simple-express git:(main) gcloud container images list-tags eu.gcr.io/$PROJECT_ID/simple-express
DIGEST TAGS TIMESTAMP
295093cf4dbe 0.0.1 2022-04-27T19:02:47
使用 CLI 命令部署到 Cloud Run
现在映像已推送到 Cloud Registry,将其部署到 Cloud Run 的最简单方法是使用 CLI 命令 gcloud run deploy。
为了简单起见,我们现在可以使用这种方法。 在下一部分中,我们可以使用 Cloud Build 设置 CI/CD 管道,以便在新提交合并到主分支后自动完成所有艰苦的工作。
我们需要指定的唯一参数是 --image 指向注册表中推送的图像:
gcloud run deploy --image eu.gcr.io/$PROJECT_ID/simple-express:0.0.1
查看我们新的闪亮服务
gcloud run deploy 命令的输出应指示部署是否成功。 如果是这样,一个新服务已经上线,我们可以通过 gcloud run services list 命令对其进行检查:
? simple-express git:(main) gcloud run services list
SERVICE REGION URL LAST DEPLOYED BY LAST DEPLOYED AT
? simple-express europe-north1 $SERVICE_URL foo.bar@gmail.com 2022-04-27T16:19:31.402119Z
$SERVICE_URL 是我们可以访问端点的公共链接。 让我们测试一下:
? simple-express git:(main) curl $SERVICE_URL/api
Hello World!%
? simple-express git:(main) curl $SERVICE_URL/api/currentUser
{"name":"Current user"}%
? simple-express git:(main) curl $SERVICE_URL/api/superUser
{"name":"Super user"}%
M1 Macs - arm64 陷阱
如果构建的 Docker 映像采用 arm64 架构,而 Google Cloud 支持 amd64,则部署到 Cloud Run 可能会失败。
例如,如果您使用的是 M1 Mac,您可能会遇到此问题。 这是一篇很棒的博客文章,解释了这个问题。
通过检查 Docker 镜像,你可以看到它的架构:
docker inspect eu.gcr.io/$PROJECT_ID/simple-express:0.0.1
[
...
"Architecture": "arm64", <- ?♂?
"Variant": "v8",
"Os": "linux",
]
对此的快速解决方法是使用 docker buildx 命令,请注意我们正在为新映像使用新标签 0.0.2:docker buildx build --platform linux/amd64 -t eu.gcr.io/$PROJECT_ID/simple-express:0.0.2 .
重新检查新建的镜像,我们可以看到它现在具有正确的 amd64 架构:
docker inspect eu.gcr.io/$PROJECT_ID/simple-express:0.0.2
[
...
"Architecture": "amd64",
"Os": "linux",
]
现在将镜像推送到 Cloud Registry 并使用 Cloud Run CLI 命令重新部署,它应该可以工作了。