寝ても覚めてもこんぴうた

プログラム書いたり、ネットワーク設計したり、サーバ構築したり、車いじったり、ゲームしたり。そんなひとにわたしはなりたい。 投げ銭は kyash_id : chidakiyo マデ

Building a Node.js App on App Engine なぞってみる

この記事は Building a Node.js App on App Engine をなぞってみた話です。

前回の記事 をふまえて、Node.jsのappを作成してGAEにdeployしようという記事です。

1. Creating a Google Cloud Platform project

GCPにプロジェクトを作りましょう。
あと、appengineを有効化してregionを設定します。
(雑)

まぁ、ここはそんなに難しくないということでこんな感じで。

2. Writing a web service with Node.js

Node.jsのコードを書きます。
ドキュメントには Node.js 8(LTS) をインストールするように書いてありますが、前回の記事にも書いた理由で node v10.9.0 で進めてみます。

キーポイント

  • 依存関係はpackage.jsonに記述します(Nodeやっている人なら説明いらないですね)
  • npm start でアプリケーションを起動できますよ。(ローカル実行ですね)
  • サーバは process.env.PORT で指定されたポートをlistenしておきましょう
  • Appengineにデプロイする際には app.yaml が必要です(GAE使い慣れている人なら説明いらないですね)

サーバを実装します

サンプルでは Express を利用していますが、何を利用してもいいようです。
特にこだわりはないので Express を利用してみます。

ドキュメントをそのまま実行せず以下の手順で行ってみます。

nodeプロジェクトの初期設定をします。

npm init

よくわからなければだいたい全部 エンター で大丈夫ですw

Expressを依存モジュールとして取得する

npm install express --save

index.jsを実装する

以下のような内容で server.js ファイルを作成します。

const express = require('express');
const app = express();

app.get('/', (req, res) => {
  res.send('オレオレ!!オレだよ!');
});

// Listen to the App Engine-specified port, or 8080 otherwise
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
  console.log(`Server listening on port ${PORT}...`);
});

npm start設定をpackage.jsonファイルに投入する

package.json ファイルを開いて以下の内容をJSONとして正しい形で追記します。

"scripts": {
  "start": "node server.js"
}

全体的には以下のようなかたちになります

{
  {
    // ~~ 省略 ~~
  },
  "scripts": {
    "start": "node server.js"
  }
}

サーバをテスト実行してみます

作成したコードをローカルでテスト実行してみます。

npm start

を実行すると 8080 ポートでサーバが起動した旨のメッセージが表示されます。
ブラウザから http://localhost:8080 へアクセスしてみましょう

app.yamlファイルを作成する

Appengineにデプロイするためには app.yaml ファイルが必要です。

最低限、以下の設定が必要です。

runtime: nodejs8

ファイル構造は以下のようになります

my-nodejs-service/
  app.yaml
  package.json
  server.js

3. Deploying your service on App Engine

キーポイント

gcloud app deploygcloud app browse を利用します

Appengineにデプロイします

app.yaml が配置されたディレクトリで以下のコマンドを実行します。

gcloud app deploy --project {PROJECT_ID}

デプロイ時間を計測するため、timeコマンドを利用して time gcloud app deploy --project {PROJECT_ID} のようなかたちで実行したところ、1分10秒ぐらいでした。まぁまぁ速い。

デプロイしたサービスを確認する

以下のコマンドを実行するとブラウザが起動します

gcloud app browse --project {PROJECT_ID}

ブラウザで期待する文字が表示されればデプロイ成功です!!

4. Updating your service

入力フォームを作ります

先程のディレクトリ配下に以下のような内容で views/form.html ファイルを作成します

<!DOCTYPE html>
<html>
  <head>
    <title>My App Engine App</title>
  </head>
  <body>
    <h2>Create a new post</h2>
    <form method="POST" action="/submit">
      <div>
        <input type="text" name="name" placeholder="Name">
      </div>
      <div>
        <textarea name="message" placeholder="Message"></textarea>
      </div>
      <div>
        <button type="submit">Submit</button>
      </div>
    </form>
  </body>
</html>

配置するディレクトリは以下のようになります

my-nodejs-service/
  views/
    form.html
  app.yaml
  package.json
  server.js

フォームの表示

server.js にpathモジュールのimportを追加します。

const path = require('path');

submitのハンドラを追加します

app.get('/submit', (req, res) => {
  res.sendFile(path.join(__dirname, '/views/form.html'));
});

サブミットされたデータをハンドリングする

body-parserを依存に追加する

npm install body-parser --save

server.js に以下を追加する

const bodyParser = require('body-parser');

expressがbody-parserを利用するように server.js に設定する

app.use(bodyParser.urlencoded({ extended: true }));

データを読み込むためのPOSTハンドラを server.js に追加する

app.post('/submit', (req, res) => {
  console.log({
    name: req.body.name,
    message: req.body.message
  });
  res.send('Thanks for your message!');
});

ローカルでチェックする

npm start

コマンドでローカルサーバを起動し、 http://localhost:8080/submit へアクセスして確認を行う。
項目を入力し、submitすると、 Thanks for your message! とブラウザに表示され、コンソール側にはサーバ側で受け取った値が表示されれば成功。

変更をデプロイする

以下のコマンドで変更したコード一式をデプロイする

gcloud app deploy --project {PROJECT_ID}

デプロイしたサービスを確認する

確認も以下のコマンドから行える。

gcloud app browse --project {PROJECT_ID}

ローカルへのデプロイと異なり、Appengine側にデプロイした場合のログは、Stackdriver Loggingに送られる

5. Viewing Your Service's Logs

ログへのアクセスは GCP コンソールの Stackdriver Logging から行える。

f:id:chidakiyo:20180906190732p:plain

細かい使用方法は書きませんが、それほど使い方も難しくなく、複数スケールした場合でもこの1画面ですべて確認できるので非常に便利です!

enjoy!