Goはコンパイラ言語なのでgo build
でコンパイルが必要だが、パッケージを導入することでフロントエンドの yarn run watchみたいなHOTリロードができるらしい。
調べてみたところ、realiseは2018年以降メンテされてない様子。。。
最近はメンテナンスが続いてるair
の方が導入事例が多いようなので、air導入済みのgo環境をを作ってみました。
作成する環境
- Go v1.19
- air v.1.40.4
2022年10月末時点ではGoの最新版はv1.19
です。
airもv1.19に対応しているため、最新版の環境を構築します。
今回作成した環境のリポジトリ
手順は省略してHOTリロードするとこまでいきたい場合
下記のコマンドを上から順に実行すればOKです。
git clone https://github.com/hiro-lapis/go-docker && cd go-docker && docker compose up -d --build
docker exec -it go-docker-go-1 ash
air -c .air.toml
ファイル構成
最終的なファイル構成は以下のとおりです。
src
│
├── app
│ ├── .air.toml
│ └── main.go
├── go.mod
├── Dockerfile
└── docker-compose.yml
はじめにdocker-compose.yml
とDockerfile
を作成し、
次いでgo.mod
と.air.toml
とmain.go
を用意します。
手順
step1 go.mod作成
go.modは、go組み込みのmodule管理ファイルです。
アプリケーションはさまざまな部品同士を組み立ててシステムを構成していますが、その部品の依存関係を解決しているのがgo modです。
airを使うのにもgo.modが必要なので、作成します。
その後、appディレクトリを作成し、main.goを作りましょう。
go.modの置き場所は色々やりようがあるみたいですが、プロジェクトのrootディレクトリ(今回でいえばsrcディレクトリ内)が一番よかろうと判断しておいてあります。
module go_docker
go 1.19
step2 docker-compose.ymlの作成
こちらもsrc内にて作成。
最低限の記述で記載します。
version: "3"
services:
go:
build: .
tty: true
ports:
- "8080:8080"
volumes:
- ./app:/go/src/app
ttyについては↓が詳しいです。
また、フロントエンドやDB用のコンテナ含め作成したい時は、以下資料等を参考にするといいかも
dockerでSPAなgin + vue + mysqlの環境をさくっと作った話
step3 Dockerfileの作成
こちらを作り終えたら、src直下で作成するファイルは準備完了です。
FROM golang:1.19.2-alpine3.16
ENV GOPATH /go
ENV GO111MODULE on
RUN mkdir ${ROOT}
RUN apk update && \
apk --no-cache add git
RUN mkdir ${ROOT}
WORKDIR ${ROOT}
ADD . ${ROOT}
RUN go mod tidy && \
go install github.com/cosmtrek/air@v1.40.4
CMD ["air", "-c", ".air.toml"]
各記述の意味
go mod tidy
でairを入れる準備をした上でインストール
go get
は非推奨になっているので、go install
を使って、バージョン指定してインストールしています。
その他、各記述の意味については↓がわかりやすいです。
step4 サンプルgoプログラムを作成
appディレクトリ内にgoのコードを作っていきましょう。
まずはHOTリロードでコンパイルされるgoプログラムを作ります。
package main
import "fmt"
func main() {
fmt.Println("Hello golang from docker!")
}
step5 air.tomlの作成・編集
この時点でgoとdocker周りの記述はできたので、コンテナを起動してみます。
Dockdrfile内で実行されるair
コマンドの実行のために必要な.air.toml
がないためエラーが発生しているので、.air.toml
を作成します。
↓公式リポジトリから.air.toml
のテンプレートをコピー、
app
配下に.air.toml
を作りましょう。
step6 コンテナの起動(HOTリロードできていることの確認)
再度コンテナを起動してみます。
docker compose up
コンパイル&実行されました!
コンパイル後のバイナリはapp/tmp
配下に置かれています。
さらに、Printlの内容を少し変更してsaveしてみます。
func main() {
fmt.Println("Hello golang from docker!")
}
// ↓変更
func main() {
fmt.Println("Hello golang from docker with air!")
}
saveと同時に再コンパイルされました!
バックグラウンドで起動するdocker compose up -d
で立てたコンテナに入って実行することもできます。
その他注意点
構築時にファイル構成、具体的にはgo.mod
と.air.toml
を置く場所には気をつけましょう。
1. ワーキングディレクトリに.air.tomlを配置する
2. go.modとDockerfileと同じrootディレクトリに配置する
1については、ワーキングディレクトリに.air.tomlがない時にairを実行すると、以下のようなエラーログが出力されます。
2021/10/30 12:09:04 open .air.toml: no such file or directory
2については、↓go.modが.air.tomlと異なる階層にある状態でairを実行すると、以下のようなエラーログが出力されます。
go_1 | go: go.mod file not found in current directory or any parent directory; see 'go help modules'
go_1 | failed to build, error: exit status 1
参考資料
【Go言語】ホットリロード可能なHTTPサーバのDocker環境構築手順
Go+gin+Air環境をDockerで構築
【Golang/Go言語】Goのホットリロードライブラリをrealizeからairに移行しました
go.modってどこにおくのがいいのだろう