App Engineを試す vol3 ~NestJSでサブシステムを動かす~
概要
AppEngine勉強日記、3日目。 この記事ではNestJSで立てたAPIサーバをAppEngineでサブシステムとして動かすとこまでを解説します。
背景
AppEngineが便利っていう話を聞いたので、AppEngineでどこまでできるのかを試す連載。 連載のゴールとしては、NuxtをBFFとしておいてAPIで処理を行うというマルチサービスの構成。
ディレクトリの整理
昨日作ったNuxtのサービスをディレクトリを掘って移動する。
defaultサービスになるのでわかり易い名前を...と思ったが、default
では流石にわかりにくい。
とりあえずroot
と命名して移動する
> git status On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) renamed: app.js -> root/app.js renamed: app.yaml -> root/app.yaml renamed: nuxt.config.js -> root/nuxt.config.js renamed: nuxt/pages/index.vue -> root/nuxt/pages/index.vue renamed: package-lock.json -> root/package-lock.json renamed: package.json -> root/package.json
NestJSのセットアップ
@nestjs/cli
を入れる。
> npm i -g @nestjs/cli > nodenv rehash
apis
ディレクトリを指定してプロジェクトをセットアップする。
> nest new apis ⚡ We will scaffold your app in a few seconds.. CREATE /apis/.prettierrc (51 bytes) CREATE /apis/README.md (3370 bytes) CREATE /apis/nest-cli.json (64 bytes) CREATE /apis/package.json (1687 bytes) CREATE /apis/tsconfig.build.json (97 bytes) CREATE /apis/tsconfig.json (336 bytes) CREATE /apis/tslint.json (426 bytes) CREATE /apis/src/app.controller.spec.ts (617 bytes) CREATE /apis/src/app.controller.ts (274 bytes) CREATE /apis/src/app.module.ts (249 bytes) CREATE /apis/src/app.service.ts (142 bytes) CREATE /apis/src/main.ts (208 bytes) CREATE /apis/test/app.e2e-spec.ts (630 bytes) CREATE /apis/test/jest-e2e.json (183 bytes) ? Which package manager would you ❤️ to use? npm ✔ Installation in progress... ☕ 🚀 Successfully created project apis 👉 Get started with the following commands: $ cd apis $ npm run start Thanks for installing Nest 🙏 Please consider donating to our open collective to help us maintain this package. 🍷 Donate: https://opencollective.com/nest
こんな感じのディレクトリが作成される。
> ls -lah apis/ total 848 drwxr-xr-x 15 mizuki staff 480B 12 3 23:12 . drwxr-xr-x 9 mizuki staff 288B 12 3 23:11 .. drwxr-xr-x 9 mizuki staff 288B 12 3 23:11 .git -rw-r--r-- 1 mizuki staff 375B 12 3 23:11 .gitignore -rw-r--r-- 1 mizuki staff 51B 12 3 23:11 .prettierrc -rw-r--r-- 1 mizuki staff 3.3K 12 3 23:11 README.md -rw-r--r-- 1 mizuki staff 64B 12 3 23:11 nest-cli.json drwxr-xr-x 668 mizuki staff 21K 12 3 23:12 node_modules -rw-r--r-- 1 mizuki staff 389K 12 3 23:12 package-lock.json -rw-r--r-- 1 mizuki staff 1.6K 12 3 23:11 package.json drwxr-xr-x 7 mizuki staff 224B 12 3 23:11 src drwxr-xr-x 4 mizuki staff 128B 12 3 23:11 test -rw-r--r-- 1 mizuki staff 97B 12 3 23:11 tsconfig.build.json -rw-r--r-- 1 mizuki staff 336B 12 3 23:11 tsconfig.json -rw-r--r-- 1 mizuki staff 426B 12 3 23:11 tslint.json
とりあえずローカル環境でサーバを起動する。
> cd apis > npm start > apis@0.0.1 start /Users/mizuki/workspace/20191203-example-appengine/apis > nest start [Nest] 47954 - 2019-12-03 11:15:03 PM [NestFactory] Starting Nest application... [Nest] 47954 - 2019-12-03 11:15:03 PM [InstanceLoader] AppModule dependencies initialized +18ms [Nest] 47954 - 2019-12-03 11:15:03 PM [RoutesResolver] AppController {/}: +5ms [Nest] 47954 - 2019-12-03 11:15:03 PM [RouterExplorer] Mapped {/, GET} route +2ms [Nest] 47954 - 2019-12-03 11:15:03 PM [NestApplication] Nest application successfully started +2ms
> curl -v localhost:3000 * Rebuilt URL to: localhost:3000/ * Trying ::1... * TCP_NODELAY set * Connected to localhost (::1) port 3000 (#0) > GET / HTTP/1.1 > Host: localhost:3000 > User-Agent: curl/7.54.0 > Accept: */* > < HTTP/1.1 200 OK < X-Powered-By: Express < Content-Type: text/html; charset=utf-8 < Content-Length: 12 < ETag: W/"c-Lve95gjOVATpfV8EL5X4nxwjKHE" < Date: Tue, 03 Dec 2019 14:15:52 GMT < Connection: keep-alive < * Connection #0 to host localhost left intact Hello World!%
プロジェクトをデプロイする
例によってapp.yamlを作成する。
今回はdefaultのサービスではなく、サブシステムとなるapis
をservice
に指定する。
> echo ' service: apis runtime: nodejs10 ' > app.yaml
apis
のディレクトリでデプロイコマンドを実行する。
以下のようにターゲットが表示されるので、問題なければy
で実行。
target url
がhttps://apis-dot-astral-web-260712.appspot.com
になっていることに注目。
> gcloud app deploy Services to deploy: descriptor: [/Users/mizuki/workspace/20191203-example-appengine/apis/app.yaml] source: [/Users/mizuki/workspace/20191203-example-appengine/apis] target project: [astral-web-260712] target service: [apis] target version: [20191203t232045] target url: [https://apis-dot-astral-web-260712.appspot.com] Do you want to continue (Y/n)? y Beginning deployment of service [apis]... Created .gcloudignore file. See `gcloud topic gcloudignore` for details. ╔════════════════════════════════════════════════════════════╗ ╠═ Uploading 29 files to Google Cloud Storage ═╣ ╚════════════════════════════════════════════════════════════╝ File upload done. Updating service [apis]...done. Setting traffic split for service [apis]...done. Deployed service [apis] to [https://apis-dot-astral-web-260712.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s apis To view your application in the web browser run: $ gcloud app browse -s apis
さー、デプロイできたぞー、と思ったがーー
> curl https://apis-dot-astral-web-260712.appspot.com <html><head> <meta http-equiv="content-type" content="text/html;charset=utf-8"> <title>500 Server Error</title> </head> <body text=#000000 bgcolor=#ffffff> <h1>Error: Server Error</h1> <h2>The server encountered an error and could not complete your request.<p>Please try again in 30 seconds.</h2> <h2></h2> </body></html>
ーーなんかエラーになるな...
困ったときはとりあえずログを確認。-s
でサービスを指定する。
> gcloud app logs tail -s apis Waiting for new log entries... 2019-12-03 14:22:46 apis[20191203t232045] "GET / HTTP/1.1" 500 2019-12-03 14:22:46 apis[20191203t232045] sh: 1: exec: nest: not found 2019-12-03 14:22:48 apis[20191203t232045] "GET /favicon.ico HTTP/1.1" 500 2019-12-03 14:22:49 apis[20191203t232045] sh: 1: exec: nest: not found 2019-12-03 14:22:52 apis[20191203t232045] "GET / HTTP/1.1" 500 2019-12-03 14:22:52 apis[20191203t232045] sh: 1: exec: nest: not found 2019-12-03 14:22:52 apis[20191203t232045] "GET /favicon.ico HTTP/1.1" 500 2019-12-03 14:22:53 apis[20191203t232045] sh: 1: exec: nest: not found 2019-12-03 14:23:22 apis[20191203t232045] "GET / HTTP/1.1" 500 2019-12-03 14:23:22 apis[20191203t232045] sh: 1: exec: nest: not found
nest not found
らしい...
@nestjs/cli
がdevDependencies
に含まれているため、インストールされないようだ。
npm start
のコマンドからnestの依存を外す。
diff --git a/package.json b/package.json index 6f344f7..01bd10c 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "prebuild": "rimraf dist", "build": "nest build", "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", - "start": "nest start", + "start": "npm run start:prod", "start:dev": "nest start --watch", "start:debug": "nest start --debug --watch", "start:prod": "node dist/main",
さあさ、デプロイデプロイっ
> gcloud app deploy Services to deploy: descriptor: [/Users/mizuki/workspace/20191203-example-appengine/apis/app.yaml] source: [/Users/mizuki/workspace/20191203-example-appengine/apis] target project: [astral-web-260712] target service: [apis] target version: [20191203t233112] target url: [https://apis-dot-astral-web-260712.appspot.com] Do you want to continue (Y/n)? y Beginning deployment of service [apis]... ╔════════════════════════════════════════════════════════════╗ ╠═ Uploading 1 file to Google Cloud Storage ═╣ ╚════════════════════════════════════════════════════════════╝ File upload done. Updating service [apis]...done. Setting traffic split for service [apis]...done. Deployed service [apis] to [https://apis-dot-astral-web-260712.appspot.com] You can stream logs from the command line by running: $ gcloud app logs tail -s apis To view your application in the web browser run: $ gcloud app browse -s apis
ログを起動しとく
> gcloud app logs tail -s apis 2019-12-03 14:33:24 apis[20191203t233112] 2019-12-03 14:33:24 apis[20191203t233112] > apis@0.0.1 start:prod /srv 2019-12-03 14:33:24 apis[20191203t233112] > node dist/main 2019-12-03 14:33:24 apis[20191203t233112] 2019-12-03 14:33:25 apis[20191203t233112] [Nest] 28 - 12/03/2019, 2:33:25 PM [NestFactory] Starting Nest application... 2019-12-03 14:33:25 apis[20191203t233112] [Nest] 28 - 12/03/2019, 2:33:25 PM [InstanceLoader] AppModule dependencies initialized +21ms 2019-12-03 14:33:25 apis[20191203t233112] [Nest] 28 - 12/03/2019, 2:33:25 PM [RoutesResolver] AppController {/}: +6ms 2019-12-03 14:33:25 apis[20191203t233112] [Nest] 28 - 12/03/2019, 2:33:25 PM [RouterExplorer] Mapped {/, GET} route +3ms 2019-12-03 14:33:25 apis[20191203t233112] [Nest] 28 - 12/03/2019, 2:33:25 PM [NestApplication] Nest application successfully started +3ms
満を持してcurlを叩くーー
> curl https://apis-dot-astral-web-260712.appspot.com
ーーが、レスポンスが帰ってこない!なんぞ!? 首をかしげながら考える私。 んー通信出来へんてこたぁサービス起動してへんのかな? やー、ゆうてもログでは起動しるやん?
... ... ...あっ 唐突に思いつく私。
diff --git a/src/main.ts b/src/main.ts index 13cad38..7357152 100644 --- a/src/main.ts +++ b/src/main.ts @@ -3,6 +3,6 @@ import { AppModule } from './app.module'; async function bootstrap() { const app = await NestFactory.create(AppModule); - await app.listen(3000); + await app.listen(Number(process.env.PORT) || 3000); } bootstrap();
あー
> npm run build > gcloud app deploy
ああー
> gcloud app logs tail -s apis 2019-12-03 14:40:25 apis[20191203t233845] > apis@0.0.1 start:prod /srv 2019-12-03 14:40:25 apis[20191203t233845] > node dist/main 2019-12-03 14:40:25 apis[20191203t233845] 2019-12-03 14:40:27 apis[20191203t233845] [Nest] 28 - 12/03/2019, 2:40:27 PM [NestFactory] Starting Nest application... 2019-12-03 14:40:27 apis[20191203t233845] [Nest] 28 - 12/03/2019, 2:40:27 PM [InstanceLoader] AppModule dependencies initialized +23ms 2019-12-03 14:40:27 apis[20191203t233845] [Nest] 28 - 12/03/2019, 2:40:27 PM [RoutesResolver] AppController {/}: +7ms 2019-12-03 14:40:27 apis[20191203t233845] [Nest] 28 - 12/03/2019, 2:40:27 PM [RouterExplorer] Mapped {/, GET} route +25ms 2019-12-03 14:40:27 apis[20191203t233845] [Nest] 28 - 12/03/2019, 2:40:27 PM [NestApplication] Nest application successfully started +3ms
あ〜〜〜〜〜〜〜
> curl https://apis-dot-astral-web-260712.appspot.comHello World!%
まとめ
AppEngineかんたんでとてもわかり易いですね!!!!!
次回予告
サービス2つ作っただけじゃね? 明日は連携できるようにコード書きます!がんばります!