エムスリーテックブログ

エムスリー(m3)のエンジニア・開発メンバーによる技術ブログです

新しいアンケートシステムをつくった(Go / App Engine SPA 開発環境編)

f:id:itto_ki:20190927115639j:plain
ibisは日本語でトキ(鳥)。我々のチームではシステムに動物の名前をつけています。
エムスリーエンジニアリンググループの木村です。 今回は「新しいアンケートシステムをつくった(Go とシステム概要編)]」、「新しいアンケートシステムをつくった(Digdag・Embulk・BigQuery データ同期編)」に引き続き、新しいアンケートシステム「Ibis」について説明します。環境構成編です。

概要

Ibis は開発言語としてフロントエンドに TypeScript + React.js、バックエンドに Go 言語を使った SPA(Single Page Application)として開発しています。 また、前回の Ibis についての記事「新しいアンケートシステムをつくった(Digdag・Embulk・BigQuery データ同期編)」でも軽く触れられていますが、Ibis のアプリケーション基盤は GCP の App Engine を使用しています。 今回はこのような構成のアプリケーションのローカル開発環境、本番環境について書いていきます。

ローカル開発環境

開発では同一のレポジトリの中で、 フロントエンド側のソースコードとバックエンド側のソースコードをディレクトリ単位で明確に分けています。

開発時の動作確認ではフロントエンドとバックエンドをそれぞれ独立させて動かしています。

フロントエンド、バックエンド共にwebpack-dev-serverfreshを使用してホットリロードを実現しているため、 それぞれ以下のようなコマンドで開発用サーバを立ち上げることができます。

フロントエンド

webpack-dev-server --open

バックエンド

fresh

実際にはこれらのコマンドを直接実行することはなく、 Makefile を介して実行されます。 その際にアプリケーションに必要な環境変数を定義することを同時に行います。

また Ibis ではデータベースとして PostgreSQL を利用しており、 こちらもdocker-composeでコマンド一発起動するようにしています。

本番環境

さて上記のようにして開発したアプリケーションを GCP App Engine へデプロイしていきます。

SPA であればフロントエンド部分を S3 や Firebase Hosting 等の静的ファイルをホスティングできるサービスへデプロイ、 バックエンドを App Engine や EC2 等のアプリケーションホスティングサービスへデプロイすることが多いのではないかと思います。

しかし今回 Ibis では、フロントエンドとバックエンド共に GCP App Engine へデプロイすることにしました。

このような構成にした理由は以下の 2 つです。

  • デプロイ工程が非常に簡単になる
  • 同様の構成で運用しているシステムがあり知見が豊富にあった

一方でこのような構成ではスケーリングしづらいといったデメリットもありますが、 Ibis のシステムの特性上これは問題がないだろうという判断をしています。

デプロイの手順は以下のようになります。

  1. フロントエンドのソースコードをビルドする

  2. ビルドしてできた静的ファイルをバックエンド側の所定のディレクトリへコピー

  3. バックエンドアプリケーションをデプロイ

これらの手順を CI からボタンひとつで実行できるようになっています。

バックエンドアプリケーション側のディレクトリ構成は以下のようになっています(一部略)。

src
├── main.go
├── application/
├── domain/
├── infra/
├── lib/
├── app.yaml
├── static/
├── wire.go
└── wire_gen.go

フロントエンドの静的ファイルは上記のstatic/ディレクトリの中にコピーしています。

さて、ユーザからアプリケーションへのアクセスがあったときには、 static/ディレクトリの中の静的ファイルを提供する必要があります。

この時ユーザからアクセスされた URL と静的ファイルをディスパッチする設定を書いているのがapp.yamlです。

このファイルの設定の部分の内容は以下のようになっています。

includes:
  - secret_production.yaml

handlers:
  - url: /(.*\.ico)
    mime_type: image/x-icon
    static_files: static/\1
    upload: static/(.*\.ico)
    expiration: "7d"

  - url: /(.*\.js)
    mime_type: "text/javascript; charset: utf-8"
    static_files: static/\1
    upload: static/(.*\.js)

  - url: /(.*\.css)
    mime_type: "text/css; charset: utf-8"
    static_files: static/\1
    upload: static/(.*\.css)

  - url: /.*
    script: auto
    secure: always

上記のような設定でアクセスされた URL に対して適切な静的ファイルを提供しています。

またapp.yamlにはディスパッチ設定の他にアプリケーションで使用する環境変数等の設定も書くことができます。 Ibis ではそれらの設定がsecret_production.yaml書いてあることを期待し、 app.yamlからsecret_production.yamlを読み込んでいます。 それが上記app.yamlの以下の部分です。

includes:
  - secret_production.yaml

Makefile 内で定義していたアプリケーションに必要な環境変数ですが、 本番環境では CI の段階でそれら環境変数を記述したsecret_production.yamlを生成して、 それをアプリケーションが使用しています。

こうして GCP App Engine からユーザのブラウザに提供されたフロントエンドアプリケーションが、 GCP App Engine 上にいるバックエンドアプリケーションと gRPC-Web で通信を行うというのが Ibis の構成になっています。

まとめ

今回は新アンケートシステム「Ibis」の環境構成について紹介しました。

TypeScript(+React.js)と Go 言語を使用した SPA は珍しくはありませんが、 それらをまとめて 1 つの GCP App Engine インスタンスで提供する構成というのは比較的珍しいのではないでしょうか。

新しいアンケートシステムをつくった(Go とシステム概要編)]」、「新しいアンケートシステムをつくった(Digdag・Embulk・BigQuery データ同期編)」、そして本記事と新アンケートシステム「Ibis」について紹介してきました。

今後もなにか Ibis で面白いネタがあればその都度紹介していきたいと考えています。

関連記事

www.m3tech.blog

www.m3tech.blog

We are hiring!

エムスリーでは GCP を使った開発に興味のあるエンジニアを募集しています。社員とカジュアルにお話することもできますので、興味を持たれた方は下記よりお問い合わせください。

jobs.m3.com