Air とは
ホットリロードと呼ばれる機能で俗に言う watch みたいなもの。
今まで realize を使用してきたけど、開発が止まっていて、さらに最新の go にインストールできなかったので、
Air をインストールすることにした。
構成
go ファイルは動くことを確認するだけなので適当に作る。
フレームワークは gin を使用する。
.gitignore
app
├ .air.toml
├ go.mod
├ go.sum
├ main.go
└ src
└ Sample.go
docker-compose.yaml
go
└ Dockerfile
nginx
└ default.conf
サンプルコード
.gitignore
.DS_Store
air.log
main
!.gitkeep
app/.air.toml
本家のサンプル を少し書き換え。
# Config file for [Air](https://github.com/air-verse/air) in TOML format
# Working directory
# . or absolute path, please note that the directories following must be under root.
root = "."
tmp_dir = "tmp"
[build]
# Just plain old shell command. You could use `make` as well.
# cmd = "go build -o ./tmp/main ."
cmd = "go build -o ./main ."
# Binary file yields from `cmd`.
# bin = "tmp/main"
bin = "main"
# Customize binary, can setup environment variables when run your app.
# full_bin = "APP_ENV=dev APP_USER=air ./tmp/main"
full_bin = "APP_ENV=dev APP_USER=air ./main"
# Watch these filename extensions.
include_ext = ["go", "tpl", "tmpl", "html"]
# Ignore these filename extensions or directories.
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
# Watch these directories if you specified.
include_dir = []
# Watch these files.
include_file = []
# Exclude files.
exclude_file = []
# Exclude specific regular expressions.
exclude_regex = ["_test\\.go"]
# Exclude unchanged files.
exclude_unchanged = true
# Follow symlink for directories
follow_symlink = true
# This log file places in your tmp_dir.
log = "air.log"
# It's not necessary to trigger build each time file changes if it's too frequent.
delay = 0 # ms
# Stop running old binary when build errors occur.
stop_on_error = true
# Send Interrupt signal before killing process (windows does not support this feature)
send_interrupt = false
# Delay after sending Interrupt signal
kill_delay = 500 # ms
# Rerun binary or not
rerun = false
# Delay after each executions
rerun_delay = 500
# Add additional arguments when running binary (bin/full_bin). Will run './tmp/main hello world'.
# args_bin = ["hello", "world"]
args_bin = []
[log]
# Show log time
time = false
# Only show main log (silences watcher, build, runner)
main_only = false
[color]
# Customize each part's color. If no color found, use the raw app log.
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"
[misc]
# Delete tmp directory on exit
clean_on_exit = true
app/go.mod
後で確認する際に、コマンドで生成する。
module github.com/docker-sample
go 1.19
require github.com/gin-gonic/gin v1.8.2
require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/ugorji/go/codec v1.2.7 // indirect
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3 // indirect
golang.org/x/net v0.4.0 // indirect
golang.org/x/sys v0.3.0 // indirect
golang.org/x/text v0.5.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
go.sum
割愛
app/main.go
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"github.com/docker-sample/src"
)
func main() {
// Sample.go を呼び出せるか確認しているだけ
s := new(src.Sample)
fmt.Print(s.Test())
// Getting started にあるサンプルをコピペして少し書き換え
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "hello world",
})
})
// r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
r.Run(":8080")
}
app/src/Sample.go
main.go で呼び出せるか確認するだけのファイル。
package src
type Sample struct {}
func (s *Sample) Test() string {
return "\n===============\ntest in Sample.go\n===============\n\n"
}
docker-compose.yaml
version: "3"
services:
app:
depends_on:
- go
image: nginx:1
volumes:
- ./app:/var/www/html
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf
ports:
- 8080:80
tty: true
working_dir: /var/www/html
go:
build:
context: .
dockerfile: ./go/Dockerfile
volumes:
- ./app:/var/www/html
working_dir: /var/www/html
go/Dockerfile
FROM golang:1.19
RUN go install github.com/air-verse/air@latest
CMD ["air", "-c", ".air.toml"]
nginx/default.conf
upstream nginx_sample {
server go:8080;
}
server {
listen 80;
listen [::]:80;
server_name localhost;
root /var/www/html;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
proxy_pass http://nginx_sample/;
}
index index.html;
# redirect server error pages to the static page /50x.html
#
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
location ~ /\.ht {
deny all;
}
}
確認
# go.mod ファイルを作る
$ cd path/to/your/project/app
$ go mod init github.com/docker-sample
# ビルドする
$ cd path/to/your/project
$ docker-compose up --build
# gin のインストール等が失敗する場合は、
# go のイメージを元にした方のコンテナにログインする
# コンテナ確認
$ docker ps
# ログイン
$ docker exec -it your-go-app1 /bin/bash
# gin をインストールする
$ go mod tidy
# コンテナから出る
$ exit
# 一度コンテナを停止する
ctl + c
# コンテナ起動する。 --build はつけない
$ docker-compose up
# http://localhost:8080/ にアクセスして
# main.go などを更新してホットリロードが動いているか確認する。