LoginSignup
13
10

More than 3 years have passed since last update.

go + realize + grpc-gatewayをDocker上で動かしてホットリロードできるようにする

Last updated at Posted at 2018-12-11

Gopher道場 Advent Calendar 12日目のエントリになります。
昨日は、@Baki33 さんによる「Cloud Functions/Node.jsでGoを動かす魔法の裏側」でした。

概要

この記事ではgo + realize + grpc-gatewayをDocker上で動かし、ホットリロードをローカル環境で実現する方法をまとめます。

はじめに

gopher道場の3期生として参加しgo全般非常に勉強になったのですが、gopher道場では触れられておらず、実際に業務にあたり欲しいなと思ったのがホットリロード、つまりファイルに変更をするとビルドし直して再実行してくれる用のツールでした。

ただGoのアプリケーションを作って、それをホットリロードで動かすのであれば各ツールのチュートリアルでできるかと思うので、今回は実際に業務で使用しているのに近い構成でrealizeを動かします。

ホットリロード用のツール

ホットリロード用のツールとして、以下のツールがあるようです。この中で比較的最近まで開発が行われておりスター数も多いrealizeを選択して使っています。

今回の記事のソースコード一式

今回のソースコード一式は以下にあげて動くようにしています。
https://github.com/gosagawa/realize_sample

環境

本体サーバとgrpc-gateway,あとリバースプロクシ用のコンテナを動かします。
それをrealizeで動かせるようにrealizeの設定を追加します。

Dockerfileの設定

dockerファイルを作成する際にrealizeを取得しておき使えるようにしておきます。

FROM golang:latest

RUN go get -u github.com/tockins/realize

docker-composeの設定

Goアプリの本体サーバを4000番ポートで起動し、それに接続したgrpc-gatewayを3000番ポートで起動します。その前段にproxyがありローカル環境でlocal.realize_sample.netを開いた際に接続しに行きます。

起動をrealizeで行うので以下のように本体サーバとgrpc-gatewayを起動します。以下は本体サーバでの例です。grpc-gateway側は--nameの値を変えるだけです。

command: bash -c "realize start --name='server' --run"

realizeの設定

relizeは設定ファイル.realize.yamlの設定を元に実行されます。
ここでは、再起動するタイミング(ファイル変更後、即時か)、実行するファイルとコマンド引数、監視対象のファイル拡張子と無視するディレクトリ等を設定できます。

realize.yamlの構成

以下のような構成になってます。

realize.yaml
settings:
  # 全体設定
schema:
- name: server
  # 本体サーバ用の設定
- name: gateway
  # grpc-gateway用の設定

全体設定

チェックする期間を指定できます。0sだとファイル変更があったら即時で再ビルドおよび実行が行わられます。

realize.yaml
settings:
  legacy:
    force: false
    interval: 0s

本体サーバ側設定

buildするファイル、実行するファイルなどを設定しています。
vendor内を監視すると監視量が膨大になるので(自分の環境ではエラーになって落ちました)外しています。

realize.yaml
schema:
- name: server
  path: .
  commands:
    install:
      status: true
      dir: cmd/grpc-server
    run:
      status: true
      method: /go/bin/grpc-server
  watcher:
    extensions:
    - go
    paths:
    - /
    ignored_paths:
    - .git
    - .realize
    - vendor

grpc-gateway側設定

本体サーバと似たような設定ですが、パラメータでappの4000番ポートに接続する事を渡しています。

realize.yaml
- name: gateway
  path: .
  commands:
    install:
      status: true
      dir: cmd/grpc-gateway
    run:
      status: true
      method: /go/bin/grpc-gateway
  args:
  - --endpoint=app:4000
  watcher:
    extensions:
    - go
    paths:
    - /
    ignored_paths:
    - .git
    - .realize
    - vendor

動作確認

ここまで設定がうまくいっていればコードを変更した時点で自動反映されるようになります。

まずサンプルのソースを動かすと、以下のAPIを実行可能になります。

$ curl http://local.realize_sample.net/user/1
{"id":1,"name":"John","age":18}

これはadapter/grpc/user.goに実装されているので、内容を書き換えます。
以下でAgeを19にします。

adapter/grpc/user.go
// Get ユーザ情報を取得する
func (u *User) Get(ctx context.Context, in *proto.GetUserRequest) (*proto.User, error) {

    user := &proto.User{
        Id:   in.Id,
        Name: "John",
        Age:  18, //ここを19に書き換えて保存する
    }

    return user, nil
}

すると、多少ラグはありますが自動的にAPIに反映されます。

$ curl http://local.realize_sample.net/user/1
{"id":1,"name":"John","age":19}

protoに関してはgoファイルではないためprotoのコンパイルをしないと反映されません(できるようにできるかもしれませんがそこまではできていません)。コンパイルするとgoファイルができるので、その時点で自動反映されます。

まとめ

開発手法によるかもしれませんが、直すと勝手にbuildが走る(エラーがあればそれも確認できる)というは非常に便利です。ぜひ試してみてください。

13
10
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
10