環境
Docker: 4.20.1
Nginx: 1.23
Air: 1.45.0
記事の要約
Goのホットリロードツール(Air)による再実行時にtcpポート競合が起きてしまっていた問題をAirの設定ファイルを修正することで解決したという記事。
前提
- Dockerについてある程度知っている
- Docker環境でのAirの導入は既に出来ている
目次
背景
Goは(RubyやPHPとは異なり)コンパイル言語であるため、実行中のアプリケーションのソースコードへの変更を反映させるためには実行停止+コンパイル+実行を毎回行う必要がある。
これは明らかに面倒だし効率が悪すぎるということで、この辺りの不満を解決してくれるホットリロードという機能が提供されている(GoではAirというモジュールが主流らしい)。
問題
Go言語での開発においてソースコードを書き換えを勝手に検知してbuild+再実行をしてくれるAirであるが、
# listen tcp :8080: bind: address already in use
というエラーが発生しており、 変更が反映されないこともしばしばあり、とても困っていた。
解決
下記に示す様に、airの設定ファイルである".air.toml"ファイルのdelayを0から50に変更する。
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./tmp/main"
cmd = "go build -o ./tmp/main ."
delay = 50
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = ""
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true
終わりに
# listen tcp :8080: bind: address already in use
このエラーが発生する際にはbuildが2回走っており、今までのプロセスがkillされる前に新しいプロセスが走っていた、もしくは変更検出後の再実行が2回走っていたのではないかと思われる。ここでdelayを設定することによって、buildの際に待ち時間が発生することでkillの時間稼ぎ、もしくは変更検出したプロセスがすでに走っていることの判定ができる様になることでもmん大が解決したのかな?と思っている(なぜ治ったのかよくわかっていない)。
もし詳しい理由をご存知の方がいたらぜひコメントよろしくお願いします!