この記事は Go 2 Advent Calendar 2020 の4日目の記事です。
tl;dr
- Goでホットリロード(a.k.a Live reload)を利用する際には今までは Realize というライブラリを使っている人が多いが、開発が止まっている。
- issueも放置され、go modの対応もされておらず、2020/10/25現在のモダンな環境で構築を行うと詰まる点が多い。
- 代わりに Air というライブラリを利用してホットリロードを行う。
Go + docker-composeを利用してホットリロードを利用した開発を行いたいと検索をして一番多かったのがrealizeというライブラリだった。
が、開発が停滞しているようで、issueも溜まっており、go modの対応もされておらず、2020/10/25 現在の環境で新規に作ろうとすると、いくつもハマる点があった。
他にライブラリは無いかといくつか調べたところ、Airというライブラリが開発も頻繁にされており、star数も多く筋が良さそうだったので、こちらを利用することにした。
利用方法
Usageにもあるが、
- .air.toml ファイルを作成する
- repositoryの.air_example.toml をコピーペーストし、自分の環境に合わせる
- コマンドを実行する
air
.air.tomlの設定について
repositoryにexampleがあるので、それを参考にする。
air/air_example.toml at 71d8bf298b426e631c7f51947e8d706246b4ff16 · cosmtrek/air · GitHub
設定ファイルもそんなに難しくなく、ある程度はわかると思う。特に重要な点は
cmd
bin
cmd
は自分のGo Appをbuildするコマンドを記述する。
bin
は cmd
でbuildしたbinaryのpathを記述する
実際に利用するシーンを見たほうが早いので、GitHubにpushしたコードを参考に構築する。
ディレクトリ構成は下記
$ tree -I frontend . ├── LICENSE ├── README.md ├── backend │ ├── Dockerfile │ ├── cmd │ │ └── app │ │ └── main.go │ ├── go.mod │ ├── go.sum │ ├── handlers │ │ ├── handler.go │ │ ├── root.go │ │ └── routes.go │ ├── models │ └── repositories └── docker-compose.yml 6 directories, 10 files
実際にホットリロードを行う。今回の場合の.air.tomlの構成は下記
$ cd backend/ $ go get -u github.com/cosmtrek/air $ air -c .air.toml __ _ ___ / /\ | | | |_) /_/--\ |_| |_| \_ v1.12.1 // live reload for Go apps, with Go1.14.0 watching . watching cmd watching cmd/app watching handlers watching models watching repositories !exclude tmp building... running... ____ __ / __/___/ / ___ / _// __/ _ \/ _ \ /___/\__/_//_/\___/ v4.1.16 High performance, minimalist Go web framework https://echo.labstack.com ____________________________________O/_______ O\ ⇨ http server started on [::]:5000 $ curl localhost:5000 {"result":true}
handlers/root.go
に手を入れてみる。
$ air -c .air.toml __ _ ___ / /\ | | | |_) /_/--\ |_| |_| \_ v1.12.1 // live reload for Go apps, with Go1.14.0 watching . watching cmd watching cmd/app watching handlers watching models watching repositories !exclude tmp building... running... ____ __ / __/___/ / ___ / _// __/ _ \/ _ \ /___/\__/_//_/\___/ v4.1.16 High performance, minimalist Go web framework https://echo.labstack.com ____________________________________O/_______ O\ ⇨ http server started on [::]:5000 handlers/root.go has changed building... running... ____ __ / __/___/ / ___ / _// __/ _ \/ _ \ /___/\__/_//_/\___/ v4.1.16 High performance, minimalist Go web framework https://echo.labstack.com ____________________________________O/_______ O\ ⇨ http server started on [::]:5000 $ $ curl localhost:5000 {"result":false}
とJSON Responseが変わっていることがわかる。
docker-compose
ここまではローカル環境で行ってきたが、目的としてContainer上で行いたいのでdocker-composeで行ってみる。
Dockerfile
docker-compose.yml
$ docker-compose build api Building api Step 1/7 : FROM golang:1.15-alpine as base ---> b3bc898ad092 Step 2/7 : WORKDIR /app/go/base ---> Using cache ---> 99b11653d662 Step 3/7 : COPY go.mod . ---> 8d6ca0f99b03 Step 4/7 : COPY go.sum . ---> 72e5d889c991 Step 5/7 : RUN go mod download ---> Running in 5b61f9b803ee Removing intermediate container 5b61f9b803ee ---> 05068d1b4923 Step 6/7 : RUN go get -u github.com/cosmtrek/air ---> Running in dbefc40ddd77 go: downloading github.com/cosmtrek/air v1.21.2 go: github.com/cosmtrek/air upgrade => v1.21.2 go: downloading github.com/fsnotify/fsnotify v1.4.9 go: downloading github.com/creack/pty v1.1.9 go: downloading github.com/imdario/mergo v0.3.8 go: downloading github.com/pelletier/go-toml v1.6.0 go: downloading github.com/fatih/color v1.7.0 go: github.com/pelletier/go-toml upgrade => v1.8.1 go: github.com/mattn/go-colorable upgrade => v0.1.8 go: github.com/mattn/go-isatty upgrade => v0.0.12 go: github.com/imdario/mergo upgrade => v0.3.11 go: github.com/fatih/color upgrade => v1.9.0 go: github.com/creack/pty upgrade => v1.1.11 go: golang.org/x/sys upgrade => v0.0.0-20201022201747-fb209a7c41cd go: downloading github.com/fatih/color v1.9.0 go: downloading github.com/imdario/mergo v0.3.11 go: downloading github.com/creack/pty v1.1.11 go: downloading golang.org/x/sys v0.0.0-20201022201747-fb209a7c41cd go: downloading github.com/pelletier/go-toml v1.8.1 go: downloading github.com/mattn/go-colorable v0.1.8 Removing intermediate container dbefc40ddd77 ---> 7a9749558df6 Step 7/7 : COPY . . ---> 37c82f03a414 Successfully built 37c82f03a414 Successfully tagged go-nextjs-playground_api:latest $ docker-compose up api Recreating go-nextjs-playground_api_1 ... done Attaching to go-nextjs-playground_api_1 api_1 | api_1 | __ _ ___ api_1 | / /\ | | | |_) api_1 | /_/--\ |_| |_| \_ v1.12.1 // live reload for Go apps, with Go1.14.0 api_1 | api_1 | mkdir /app/go/base/tmp api_1 | watching . api_1 | watching cmd api_1 | watching cmd/app api_1 | watching handlers api_1 | watching models api_1 | watching repositories api_1 | !exclude tmp api_1 | building... api_1 | running... api_1 | api_1 | ____ __ api_1 | / __/___/ / ___ api_1 | / _// __/ _ \/ _ \ api_1 | /___/\__/_//_/\___/ v4.1.16 api_1 | High performance, minimalist Go web framework api_1 | https://echo.labstack.com api_1 | ____________________________________O/_______ api_1 | O\ api_1 | ⇨ http server started on [::]:5000
$ curl localhost:5000 {"result":true}
また handler/root.go
のコードを変える。今回はJSON Responseの値をtrueからfalseに変更する。
api_1 | handlers/root.go has changed api_1 | building... api_1 | running... api_1 | api_1 | ____ __ api_1 | / __/___/ / ___ api_1 | / _// __/ _ \/ _ \ api_1 | /___/\__/_//_/\___/ v4.1.16 api_1 | High performance, minimalist Go web framework api_1 | https://echo.labstack.com api_1 | ____________________________________O/_______ api_1 | O\ api_1 | ⇨ http server started on [::]:5000
$ curl localhost:5000 {"result":false}
Containerを起動したまま、レスポンスが変わっていること(ホットリロードされていること)がわかる。
まとめ
- Realizeは開発が停滞しており、今後扱うと負債になる可能性が高い。
- 代わりにAirというライブラリを利用することで、ホットリロード (a.k.a ライブロード) を利用することが出来るのでそちらを利用する。