Git
Node.js
GAE

Google App EngineにGit管理ファイルだけデプロイする

GAEへのデプロイはCloud SDKを使ってgcloud app deployというコマンドで行うことができますが,基本的にカレントディレクトリ以下のすべてのファイルがアップロードされてしまうので,デプロイ用の設定ファイルapp.yamlで除外ファイルを指定できるようになっています.(GCPのドキュメント

ただ,除外ファイルを指定する場合,意図しないファイル(開発用の認証ファイル,お試しコード混入など)がある場合に,それがアップロードされてしまう危険があったので,Git管理のファイル(とビルド済みコードとapp.yaml)だけがデプロイされるように,デプロイ用のスクリプトを作って対処しました.

本当はCIツールなどでちゃんとgit pullしてからデプロイするのが良いのでしょうが,小規模の検証システムを手元で開発してデプロイしたい場合に必要だったので作りました.

herokuのようにgit pushでデプロイできるオプションがあると便利なんですけどね.

環境

  • Google App Engine (Node) スタンダード環境
  • Google Cloud SDK 207.0.0
  • Node v8.11

作ったサンプルプロジェクト

  • koaで動作するWebアプリケーション
  • 環境変数のHELLO_NAMEを読んでHello <HELLO_NAMEの値>とだけ返す
  • babelでビルドしたlib/app.jsを起動する
  • ソースのリポジトリはこちら

ビルドスクリプト

リポジトリのgae-deploy.shがそうです.

gae-deploy.sh
#!/bin/bash -eu

# デプロイ対象のGitブランチ
GIT_BRANCH=${1:-master}
# app.yamlのパス
APP_CONFIG_FILE=${2:-app.yaml}
# gcloudコマンドのオプション
GCLOUD_OPTS=${@:3}

echo "GIT_BRANCH=${GIT_BRANCH}"
echo "APP_CONFIG_FILE=${APP_CONFIG_FILE}"
echo "GCLOUD_OPTS=${GCLOUD_OPTS}"

read -p "デプロイしてもよろしいですか?(y/N): " confirm
if [[ $confirm == [yY] ]]; then
  TEMP_DIR=`mktemp -d`
  echo "TEMP_DIR=$TEMP_DIR"

  # Gitブランチのエクスポート
  git archive --format=tar $GIT_BRANCH | tar -C $TEMP_DIR -xf -

  # app.yamlのコピー
  cp $APP_CONFIG_FILE $TEMP_DIR

  # ビルド
  cd $TEMP_DIR
  npm install
  npm run build

  # デプロイ
  gcloud app deploy $APP_CONFIG_FILE $GCLOUD_OPTS

  rm -r $TEMP_DIR
fi

デプロイ方法

npm run deploy <Gitブランチ> <app.yamlのパス>

例えば

npm run deploy master app.production.yaml

app.produnction.yamlの内容が次のようなとき,WebサーバにアクセスするとHello production-meと表示されます.

app.production.yaml
runtime: nodejs8
env_variables:
  HELLO_NAME: production-me

デプロイ時のコンソール

console
$ npm run deploy master app.production.yaml

> gae-deploy-sample@1.0.0 deploy /Users/xxxxx/src/github.com/ottijp/gae-deploy-sample
> ./gae-deploy.sh "master" "app.production.yaml"

GIT_BRANCH=master
APP_CONFIG_FILE=app.production.yaml
GCLOUD_OPTS=
デプロイしてもよろしいですか?(y/N): y
TEMP_DIR=/var/folders/jh/8g_d52792dld3_ck2yphd2280000gn/T/tmp.xrls1RGL

> fsevents@1.2.4 install /private/var/folders/jh/8g_d52792dld3_ck2yphd2280000gn/T/tmp.xrls1RGL/node_modules/fsevents
> node install

[fsevents] Success: "/private/var/folders/jh/8g_d52792dld3_ck2yphd2280000gn/T/tmp.xrls1RGL/node_modules/fsevents/lib/binding/Release/node-v57-darwin-x64/fse.node" already installed
Pass --update-binary to reinstall or --build-from-source to recompile
npm WARN gae-deploy-sample@1.0.0 No description

added 273 packages in 4.634s

> gae-deploy-sample@1.0.0 build /private/var/folders/jh/8g_d52792dld3_ck2yphd2280000gn/T/tmp.xrls1RGL
> babel src --out-dir lib

src/app.js -> lib/app.js
Services to deploy:

descriptor:      [/private/var/folders/jh/8g_d52792dld3_ck2yphd2280000gn/T/tmp.xrls1RGL/app.production.yaml]
source:          [/private/var/folders/jh/8g_d52792dld3_ck2yphd2280000gn/T/tmp.xrls1RGL]
target project:  [xxxxx]
target service:  [default]
target version:  [20180709t221520]
target url:      [https://xxxxx.appspot.com]


Do you want to continue (Y/n)?  y

Beginning deployment of service [default]...
Created .gcloudignore file. See `gcloud topic gcloudignore` for details.
╔════════════════════════════════════════════════════════════╗
╠═ Uploading 8 files to Google Cloud Storage                ═╣
╚════════════════════════════════════════════════════════════╝
File upload done.
Updating service [default]...done.
Setting traffic split for service [default]...done.
Deployed service [default] to [https://xxxxx.appspot.com]

You can stream logs from the command line by running:
  $ gcloud app logs tail -s default

To view your application in the web browser run:
  $ gcloud app browse

参考