☁
12/08 Google Cloud Run
この記事は、Serverless Hello World Advent Calendar 2020の8日目です。
Google Cloud RunでHTTP APIを実装します。
クイックスタート: ビルドとデプロイを参考にすすめていきます。
アプリケーションの作成
$ mkdir severless-helloworld-cloudrun
$ cd severless-helloworld-cloudrun
$ npm init
npm init <1:52>
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (severless-helloworld-cloudrun)
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /home/masa/work/serverless-helloworld/07/severless-helloworld-cloudrun/package.json:
{
"name": "severless-helloworld-cloudrun",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes)
$ npm i express
npm notice created a lockfile as package-lock.json. You should commit this file.
npm WARN severless-helloworld-cloudrun@1.0.0 No description
npm WARN severless-helloworld-cloudrun@1.0.0 No repository field.
+ express@4.17.1
added 50 packages from 37 contributors and audited 50 packages in 3.38s
found 0 vulnerabilities
index.js
const express = require('express');
const app = express();
app.get('/', (req, res) => {
const { name = 'World' } = req.query
res.send(`Hello ${name}!`);
});
const port = process.env.PORT || 8080;
app.listen(port, () => {
console.log(`helloworld: listening on port ${port}`);
});
コンテナ化
Dockerfile
と.dockerignore
を用意して、docker build
します。
Dockefile
FROM node:12-slim
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install --only=production
COPY . ./
CMD [ "node", "index.js" ]
.dockerignore
Dockerfile
.dockerignore
node_modules
npm-debug.log
$ docker build . -t nekoruri/severless-helloworld-cloudrun
[+] Building 2.2s (10/10) FINISHED
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 38B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 34B 0.0s
=> [internal] load metadata for docker.io/library/node:12-slim 2.0s
=> [internal] load build context 0.0s
=> => transferring context: 99B 0.0s
=> [1/5] FROM docker.io/library/node:12-slim@sha256:4b562ee4fca96f0f762f489e61cdf7f89c0b5746928d9c374b7ffba3a1944dc5 0.0s
=> CACHED [2/5] WORKDIR /usr/src/app 0.0s
=> CACHED [3/5] COPY package*.json ./ 0.0s
=> CACHED [4/5] RUN npm install --only=production 0.0s
=> CACHED [5/5] COPY . ./ 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:36c5d161ca45d604d6ce2b05c887b562ba8867bf3320a284f3891cd51f0d101a 0.0s
=> => naming to docker.io/nekoruri/severless-helloworld-cloudrun
ローカルで実行確認
コンテナを起動してcURLで叩いてみます。
$ docker run -d -p 8080:8080 nekoruri/severless-helloworld-cloudrun
$ curl -v 'http://localhost:8080/?name=world'
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /?name=world HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Powered-By: Express
< Content-Type: text/html; charset=utf-8
< Content-Length: 12
< ETag: W/"c-00hq6RNueFa8QiEjhep5cJRHWAI"
< Date: Fri, 18 Dec 2020 17:10:23 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
<
* Connection #0 to host localhost left intact
Hello world!%
コンテナイメージのビルド
gloud builds
でコンテナイメージをCloud build上でビルドし、Container Registryに保存します。
$ gcloud builds submit --tag gcr.io/$(gcloud config get-value project)/helloworld
Creating temporary tarball archive of 331 file(s) totalling 1.6 MiB before compression.
Uploading tarball of [.] to [gs://helloworld-297620_cloudbuild/source/1608311903.149551-d32ac04771814cea99e4bbfc5fcee5bf.tgz]
Created [https://cloudbuild.googleapis.com/v1/projects/helloworld-297620/builds/3ed17100-7bb2-44d8-963e-2d6dbb9ca59b].
Logs are available at [https://console.cloud.google.com/cloud-build/builds/3ed17100-7bb2-44d8-963e-2d6dbb9ca59b?project=211935878594].
------------------------------------------------------------- REMOTE BUILD OUTPUT -------------------------------------------------------------
starting build "3ed17100-7bb2-44d8-963e-2d6dbb9ca59b"
FETCHSOURCE
Fetching storage object: gs://helloworld-297620_cloudbuild/source/1608311903.149551-d32ac04771814cea99e4bbfc5fcee5bf.tgz#1608311902769496
Copying gs://helloworld-297620_cloudbuild/source/1608311903.149551-d32ac04771814cea99e4bbfc5fcee5bf.tgz#1608311902769496...
/ [1 files][522.2 KiB/522.2 KiB]
Operation completed over 1 objects/522.2 KiB.
BUILD
Already have image (with digest): gcr.io/cloud-builders/docker
Sending build context to Docker daemon 19.97kB
Step 1/6 : FROM node:12-slim
12-slim: Pulling from library/node
e50c3c9ef5a2: Pulling fs layer
7d035f3b6068: Pulling fs layer
5d71f0da6484: Pulling fs layer
a264fbab4a3a: Pulling fs layer
5108ca6b9c63: Pulling fs layer
a264fbab4a3a: Waiting
5108ca6b9c63: Waiting
7d035f3b6068: Verifying Checksum
7d035f3b6068: Download complete
a264fbab4a3a: Verifying Checksum
a264fbab4a3a: Download complete
5108ca6b9c63: Verifying Checksum
5108ca6b9c63: Download complete
e50c3c9ef5a2: Verifying Checksum
e50c3c9ef5a2: Download complete
5d71f0da6484: Verifying Checksum
5d71f0da6484: Download complete
e50c3c9ef5a2: Pull complete
7d035f3b6068: Pull complete
5d71f0da6484: Pull complete
a264fbab4a3a: Pull complete
5108ca6b9c63: Pull complete
Digest: sha256:4b562ee4fca96f0f762f489e61cdf7f89c0b5746928d9c374b7ffba3a1944dc5
Status: Downloaded newer image for node:12-slim
---> 9f75429649ae
Step 2/6 : WORKDIR /usr/src/app
---> Running in 967fe48cca8f
Removing intermediate container 967fe48cca8f
---> 89a83b2e3060
Step 3/6 : COPY package*.json ./
---> e03787facd60
Step 4/6 : RUN npm install --only=production
---> Running in f40e08478359
npm WARN severless-helloworld-cloudrun@1.0.0 No description
npm WARN severless-helloworld-cloudrun@1.0.0 No repository field.
added 50 packages from 37 contributors and audited 50 packages in 1.875s
found 0 vulnerabilities
Removing intermediate container f40e08478359
---> 735a7f1b3a75
Step 5/6 : COPY . ./
---> 6cddc80bd764
Step 6/6 : CMD [ "node", "index.js" ]
---> Running in 6038364cb1c1
Removing intermediate container 6038364cb1c1
---> 0225c53bd9ae
Successfully built 0225c53bd9ae
Successfully tagged gcr.io/helloworld-297620/helloworld:latest
PUSH
Pushing gcr.io/helloworld-297620/helloworld
The push refers to repository [gcr.io/helloworld-297620/helloworld]
6d4168a0b1f5: Preparing
9dafb23f2e74: Preparing
8612ccf117e0: Preparing
046c7a5214ca: Preparing
30514665193f: Preparing
49ad56da7e6f: Preparing
2c317e148151: Preparing
79c320b5a45c: Preparing
e4b1e8d0745b: Preparing
49ad56da7e6f: Waiting
2c317e148151: Waiting
79c320b5a45c: Waiting
e4b1e8d0745b: Waiting
30514665193f: Layer already exists
49ad56da7e6f: Layer already exists
2c317e148151: Layer already exists
79c320b5a45c: Layer already exists
e4b1e8d0745b: Layer already exists
046c7a5214ca: Pushed
6d4168a0b1f5: Pushed
8612ccf117e0: Pushed
9dafb23f2e74: Pushed
latest: digest: sha256:d789108b015ded0cf7836962a217ea80e8d916870ca2615f7415056f541506b5 size: 2201
DONE
-----------------------------------------------------------------------------------------------------------------------------------------------
ID CREATE_TIME DURATION SOURCE IMAGES STATUS
3ed17100-7bb2-44d8-963e-2d6dbb9ca59b 2020-12-18T17:18:23+00:00 25S gs://helloworld-297620_cloudbuild/source/1608311903.149551-d32ac04771814cea99e4bbfc5fcee5bf.tgz gcr.io/helloworld-297620/helloworld (+1 more) SUCCESS
デプロイ
Cloud Runにデプロイします。
$ gcloud run deploy --image gcr.io/$(gcloud config get-value project)/helloworld --platform managed
Service name (helloworld):
API [run.googleapis.com] not enabled on project [211935878594]. Would
you like to enable and retry (this will take a few minutes)? (y/N)? y
Enabling service [run.googleapis.com] on project [211935878594]...
Operation "operations/acf.fe66fc95-1258-43c2-951a-219a1905d41e" finished successfully.
Please specify a region:
[1] asia-east1
[2] asia-east2
[3] asia-northeast1
[4] asia-northeast2
[5] asia-northeast3
[6] asia-south1
[7] asia-southeast1
[8] asia-southeast2
[9] australia-southeast1
[10] europe-north1
[11] europe-west1
[12] europe-west2
[13] europe-west3
[14] europe-west4
[15] europe-west6
[16] northamerica-northeast1
[17] southamerica-east1
[18] us-central1
[19] us-east1
[20] us-east4
[21] us-west1
[22] cancel
Please enter your numeric choice: 3
To make this the default region, run `gcloud config set run/region asia-northeast1`.
Allow unauthenticated invocations to [helloworld] (y/N)? y
Deploying container to Cloud Run service [helloworld] in project [helloworld-297620] region [asia-northeast1]
✓ Deploying new service... Done.
✓ Creating Revision...
✓ Routing traffic...
✓ Setting IAM Policy...
Done.
Service [helloworld] revision [helloworld-00001-qat] has been deployed and is serving 100 percent of traffic.
Service URL: https://helloworld-ljzijb4fpq-an.a.run.app
動作確認
ではさっそく叩いてみます。
$ curl -v 'https://helloworld-ljzijb4fpq-an.a.run.app?name=world'
* Trying 216.239.36.53:443...
* TCP_NODELAY set
* Connected to helloworld-ljzijb4fpq-an.a.run.app (216.239.36.53) port 443 (#0)
...(省略)...
> GET /?name=world HTTP/2
> Host: helloworld-ljzijb4fpq-an.a.run.app
> user-agent: curl/7.68.0
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
< x-powered-by: Express
< content-type: text/html; charset=utf-8
< etag: W/"c-00hq6RNueFa8QiEjhep5cJRHWAI"
< x-cloud-trace-context: 79bb0955b694a0975129203bf98d4c43
< date: Fri, 18 Dec 2020 17:25:49 GMT
< server: Google Frontend
< content-length: 12
< alt-svc: h3-29=":443"; ma=2592000,h3-T051=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
<
* Connection #0 to host helloworld-ljzijb4fpq-an.a.run.app left intact
Hello world!%
無事動いていることが確認できました。
追記(2020-12-26)
2020-12-16のアップデートで、1コマンドでビルドとデプロイができるようになっていました。
$ gcloud beta run deploy --source . --platform managed
Service name: helloworld
Please specify a region:
[1] asia-east1
[2] asia-east2
[3] asia-northeast1
[4] asia-northeast2
[5] asia-northeast3
[6] asia-south1
[7] asia-southeast1
[8] asia-southeast2
[9] australia-southeast1
[10] europe-north1
[11] europe-west1
[12] europe-west2
[13] europe-west3
[14] europe-west4
[15] europe-west6
[16] northamerica-northeast1
[17] southamerica-east1
[18] us-central1
[19] us-east1
[20] us-east4
[21] us-west1
[22] cancel
Please enter your numeric choice: 3
To make this the default region, run `gcloud config set run/region asia-northeast1`.
Building using Dockerfile and deploying container to Cloud Run service [helloworld] in project [helloworld-297620] region [asia-northeast1]
✓ Building and deploying... Done.
✓ Uploading sources...
✓ Building Container... Logs are available at [https://console.cloud.google.com/cloud-build/builds/3972926d-f31a-413c-be7d-f4c3a36198fc?project=
211935878594].
✓ Creating Revision...
✓ Routing traffic...
Done.
Service [helloworld] revision [helloworld-00002-kam] has been deployed and is serving 100 percent of traffic.
Service URL: https://helloworld-ljzijb4fpq-an.a.run.app
Discussion