github.com
Golang
で Webサイトを作ろうと gin を触っていると、ライブリロードの機能がなく、変更が即座に反映されなくて、面倒くさく思っていました。
Air
というツールがよく使われていそうだったので、使ってみました。
このエントリはそのときのメモです。
gin アプリケーションの準備
まず、Air
と関係のない部分で最小のアプリケーションを用意します。
Golang
バージョンは以下の通りで、環境は macOS Catalina (10.15.7)
です。
$ go version
go version go1.15.5 darwin/amd64
目指すフォルダ構成は以下です。
.
├── go.mod
├── go.sum
└── main.go
フォルダを作成し、go modules
で環境を構築します。
$ mkdir gin-air-example && cd $_
$ go mod init gin-air-example
go: creating new go.mod: module gin-air-example
$ touch main.go
main.go
の内容は以下とします。
package main
import (
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
"message": "OK",
})
})
r.Run(":3000")
}
localhost:3000
にアクセスしたら、 {"message": "OK"}
というJSONを返します。
$ go run main.go
go: finding module for package github.com/gin-gonic/gin
go: found github.com/gin-gonic/gin in github.com/gin-gonic/gin v1.6.3
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET / --> main.main.func1 (3 handlers)
[GIN-debug] Listening and serving HTTP on :3000
$ curl localhost:3000
{"message":"OK"}
このように、デバッグのログにもアクセスが来たことが表示されます。
main.go を編集する
ここで、main.go
を以下のように変更します。
// (省略)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{
- "message": "OK",
+ "message": "Hello World",
})
})
r.Run(":3000")
}
main.go
を保存して、再度 localhost:3000
にアクセスしても結果は変わりません。
この際、go run main.go
を一旦止め、再度同じコマンドを実行すると出力結果は変わります。
$ curl localhost:3000
{"message":"Hello World"}
しかし、普段開発していて毎回 コマンドを叩き直すのはやめたいです。ここで Air
というツールを導入します。
Air
を installします。
$ go get -u github.com/cosmtrek/air
.air.toml
ファイルを作成して、設定ファイルを公式の例)からコピーし、ペーストします。
root = "."
tmp_dir = "tmp"
[build]
cmd = "go build -o ./tmp/main ."
bin = "tmp/main"
full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"
include_ext = ["go", "tpl", "tmpl", "html"]
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
include_dir = []
exclude_file = []
exclude_unchanged = true
log = "air.log"
delay = 1000
stop_on_error = true
send_interrupt = false
kill_delay = 500
[log]
time = false
[color]
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"
[misc]
clean_on_exit = true
そして、gin のプロセスを止め、airコマンドからWebアプリケーションを起動します。
$ air -c .air.toml
すると、main.go
への 変更が即座に反映されるようになったのがわかるかと思います。
これで Air
が導入できました。
gin アプリケーションの構築以外でやったことは、以下のみなので、簡単です。
Abr
の インストール
- 設定ファイルの追加
必要に応じて、.air.toml
を修正して利用します。
最終的にファイル構成はこうなっています。
.
├── .air.toml
├── go.mod
├── go.sum
└── main.go
Docker で利用
Docker
で利用する場合のメモも載せておきます。
Dockerfile
を作成
FROM golang:latest
COPY ./ /go/app
WORKDIR /go/app/
RUN go get -u github.com/gin-gonic/gin
RUN go get -u github.com/cosmtrek/air
CMD ["air", "-c", ".air.toml"]**
docker-compose.yml
を作成
version: '3'
services:
app:
container_name: app
build:
context: ./
dockerfile: ./Dockerfile
ports:
- 3000:3000
tty:
true
volumes:
- ./:/go/app
アプリケーションを立ち上げます。
$ docker-compose up —build
Building app
Step 1/6 : FROM golang:latest
Successfully built 6e9649de9e6b
Successfully tagged gin-air-example_app:latest
Recreating app ... done
Attaching to app
app |
app | __ _ ___
app | / /\ | | | |_)
app | /_/--\ |_| |_| \_ v1.12.1 // live reload for Go apps, with Go1.14.0
app |
app | mkdir /go/app/tmp
app | watching .
app | !exclude tmp
app | building...
app | running...
app | [GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
app |
app | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
app | - using env: export GIN_MODE=release
app | - using code: gin.SetMode(gin.ReleaseMode)
app |
app | [GIN-debug] GET / --> main.main.func1 (3 handlers)
app | [GIN-debug] Listening and serving HTTP on :3000
2回目移行は --build
オプションは不要です。
これで同様にmain.go
の変更が即座に反映されるようになります。
最終のファイル構成はこちらです。
.
├── .air.toml
├── Dockerfile
├── docker-compose.yml
├── go.mod
├── go.sum
└── main.go
終わりです。