1つのプロジェクトで複数のGoアプリケーションをビルドするときの開発環境を自分なりに整えてみた。
手間は減ったにせよ、ホットリロードとかはできていないので、改善できそうなら教えて欲しい。
メインアプリケーションとサイドカー
イメージとしては、メインのサーバーがいてその補助として裏でジョブを実行するサブアプリケーションがいるような感じ。
Rubyで言えばsidekiq
を使っていればこれに当たる。
『分散システムデザインパターン ―コンテナを使ったスケーラブルなサービスの設計』では、こういうのを、メインのアプリケーションに対して、サイドカーと呼ぶらしい。

分散システムデザインパターン ―コンテナを使ったスケーラブルなサービスの設計
- 作者:Brendan Burns
- 出版社/メーカー: オライリージャパン
- 発売日: 2019/04/20
- メディア: 単行本(ソフトカバー)
今回はGoなので、goworker
というものを使っている。同じGoのプロジェクトであっても、ビルドして吐き出したいバイナリは2つあることになる。さらにgoworker
はジョブの管理にredisを裏で使うので、合計3つのアプリケーションを起動する必要がある。
それらを開発環境でいい感じに起動・再起動しないと開発したものを動かして確かめられない。その手間を少しでも楽にしようと整えた話。
フォルダ構成
Goの場合、ビルドの起点になるファイルはmainパッケージにいる必要がある なのでメインのアプリケーションとサイドカーのビルドの起点となるファイルはどちらもメインパッケージにいなければならない
今回は以下のようなイメージ
├── worker │ └── main.go └── main.go
こうすることで .
起点でビルドすればメインのアプリケーション、./worker
起点でビルドすればサイドカーが吐かれるはず。
両アプリケーションをビルドする
いちいちどちらもコマンドを叩くと大変なのでシェルにまとめた。
# メインアプリケーション if [ -e hoge-main ]; then # 既にバイナリがある場合は削除 rm hoge-main fi echo 'メインアプリケーションをビルド中...' go build -o hoge-main . # サイドカー if [ -e hoge-worker ]; then # 既にバイナリがある場合は削除 rm hoge-worker fi echo 'サイドカーをビルド中' go build -o hoge-worker ./worker/
コマンドを叩くと以下のような状態になるはず。
├── worker │ └── main.go ├── main.go ├── hoge-main └── hoge-worker
あとはこのバイナリとredisを実行するだけとなる。
実行はforegoを使った
バイナリとredisの立ち上げにはforego
というものを使った。foreman in Go
だとと公式にも書いてあるようにforeman
のGoバージョンである。
Procfile
を書くだけなのでとても簡単。
main: ./hoge-main worker: ./hoge-worker redis: redis-server
しかもforego
でやっておくと、各々自前で起動するのと違って、各アプリケーションごとに色分けされてログが出るのでとても見やすい。
まとめると
これら一連の処理をシェルスクリプトにまとめるとこうなる。
# メインアプリケーション if [ -e hoge-main ]; then # 既にバイナリがある場合は削除 rm hoge-main fi echo 'メインアプリケーションをビルド中...' go build -o hoge-main . # サイドカー if [ -e hoge-worker ]; then # 既にバイナリがある場合は削除 rm hoge-worker fi echo 'サイドカーをビルド中' go build -o hoge-worker ./worker/ # バイナリとredisの立ち上げ forego start
Goのプログラムを書き換えて起動し直すときは、一度ctrl + c
で落としてから、再度スクリプトを実行すれば更新できる。
少し手間ではあるが、これで2つ(redis入れて一応3つ)のアプリケーションが更新されるので、まだマシにはなる。ビルド時間もそんなに遅くはないので、この更新処理が保存時とかに走るようにしたらもっと楽になるんだろうか。