GoのWeb FrameworkであるGinを使った環境をdocker-composeで作っていきたいと思います。
その際、ホットリロードが可能になるようにAirという技術も取り入れていきます。
筆者の環境
- macOS BigSur 11.4
- M1 Mac
- docker-compose version 1.29.2, build 5becea4c
- Docker version 20.10.7, build f0df350
Goのバージョン
- 1.19(2022-08-02リリース)
やることリスト
- go.modを作成
- main.goを作成
- Dockerfileを作成
- docker-compose.yamlを作成
- イメージをビルド
- .air.tomlを作成
- 依存関係の整理
- コンテナ起動
- Hot Reloadを確認
各手順の時点で、ディレクトリ構成がどうなっているべきかを記載するので都度確認してみてください。
1. go.modを作成
go.mod
はライブラリを管理するファイルです。JSでいうところのpackage.json
に当たります。
$ touch app/src/go.mod
module
は何かしらユニークな名前であればなんでも良いです。この名前が各ファイルのモジュール呼び出しに使用されます。
module nothing-behind.com/sample_gin
go 1.19
今のツリーはこんな感じです
.
└── app
└── src
└── go.mod # New!!
2. main.goを作成
/
にアクセスすると {"message": "SUCCESS!!!!"}
と表示するように設定します。
$ touch app/src/main.go
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "SUCCESS!!!!",
})
})
r.Run()
}
今のツリーはこんな感じです
.
└── app
└── src
├── go.mod
└── main.go # New!!
3. Dockerfileを作成
イメージを作成する元となるDockerfileを作成します。
ここですでにAirの導入が始まっています。
$ touch app/Dockerfile
FROM golang:1.19-alpine
WORKDIR /go/src
COPY ./app/src .
RUN apk upgrade --update && apk --no-cache add git
RUN go get -u github.com/cosmtrek/air && go build -o /go/bin/air github.com/cosmtrek/air
CMD ["air", "-c", ".air.toml"]
今のツリーはこんな感じです
.
└── app
├── Dockerfile # New!!
└── src
├── go.mod
└── main.go
4. docker-compose.yamlを作成
今後、このアプリケーションにいろんなもの(例えばMySQLとか)を追加することを想定し、今は1つのコンテナしか使わないですが、ここで docker-compose.yaml
を作成します。
どんな設定をしているか
app/Dockerfile
を見ている- 3000番ポートでアクセス可能
$ touch docker-compose.yaml
version: '3'
services:
app:
build:
context: .
dockerfile: ./app/Dockerfile
ports:
- "3000:8080"
volumes:
- ./app/src/:/go/src
tty: true
今のツリーはこんな感じです
.
├── app
│ ├── Dockerfile
│ └── src
│ ├── go.mod
│ └── main.go
└── docker-compose.yaml # New!!
5. イメージをビルド
Dockerイメージをビルドします。
$ docker-compose build
イメージが作成されているか、確認してみましょう。以下のコマンドでイメージが作成されているかが確認できます。
$ docker images
筆者はsample_gin
というディレクトリで作業をしているのでこんな感じのイメージが作成されました。
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
sample_gin_app latest 83a3bbc14066 46 seconds ago 398MB
6. airの初期化
作成したイメージでairを初期化(init)します。ここで、.air.toml
ファイルが生成されます。
ここでは.air.toml
の説明は割愛します。
$ docker-compose run --rm app air init
Creating network "sample_gin_default" with the default driver
Creating sample_gin_app_run ... done
__ _ ___
/ /\ | | | |_)
/_/--\ |_| |_| \_ , built with Go
.air.toml file created to the current directory with the default settings
今のツリーはこんな感じです。
.
├── app
│ ├── Dockerfile
│ └── src
│ ├── .air.toml # New!!
│ ├── go.mod
│ └── main.go
└── docker-compose.yaml
7. 依存関係の整理
諸々の依存関係をいい感じにしていきます。
以下のコマンドを実行します。すると下記のような出力がなされ、go.sum
というファイルが作成されます。
$ docker-compose run --rm app go mod tidy
Creating sample_gin_app_run ... done
go: finding module for package github.com/gin-gonic/gin
go: downloading github.com/gin-gonic/gin v1.8.1
go: found github.com/gin-gonic/gin in github.com/gin-gonic/gin v1.8.1
go: downloading github.com/gin-contrib/sse v0.1.0
go: downloading github.com/mattn/go-isatty v0.0.14
go: downloading golang.org/x/net v0.0.0-20210226172049-e18ecbb05110
go: downloading github.com/stretchr/testify v1.7.1
go: downloading google.golang.org/protobuf v1.28.0
go: downloading github.com/go-playground/validator/v10 v10.10.0
go: downloading github.com/pelletier/go-toml/v2 v2.0.1
go: downloading github.com/ugorji/go/codec v1.2.7
go: downloading gopkg.in/yaml.v2 v2.4.0
go: downloading github.com/goccy/go-json v0.9.7
go: downloading github.com/json-iterator/go v1.1.12
go: downloading golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069
go: downloading github.com/davecgh/go-spew v1.1.1
go: downloading github.com/pmezard/go-difflib v1.0.0
go: downloading gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
go: downloading github.com/go-playground/universal-translator v0.18.0
go: downloading github.com/leodido/go-urn v1.2.1
go: downloading golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97
go: downloading golang.org/x/text v0.3.6
go: downloading github.com/go-playground/locales v0.14.0
go: downloading github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421
go: downloading github.com/modern-go/reflect2 v1.0.2
go: downloading github.com/go-playground/assert/v2 v2.0.1
go: downloading github.com/google/go-cmp v0.5.5
go: downloading gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c
go: downloading github.com/kr/pretty v0.3.0
go: downloading golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
go: downloading github.com/rogpeppe/go-internal v1.8.0
go: downloading github.com/kr/text v0.2.0
今のツリーはこんな感じです。
.
├── app
│ ├── Dockerfile
│ └── src
│ ├── .air.toml
│ ├── go.mod
│ ├── go.sum # New!!
│ └── main.go
└── docker-compose.yaml
8. コンテナ起動
さて、準備ができましたのでコンテナを起動していきましょう!docker-compose up
を実行し、以下のような出力がされたらOKです。
$ docker-compose up
...
...
...
app_1 | [GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
app_1 | - using env: export GIN_MODE=release
app_1 | - using code: gin.SetMode(gin.ReleaseMode)
app_1 |
app_1 | [GIN-debug] GET / --> main.main.func1 (3 handlers)
app_1 | [GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
app_1 | Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
app_1 | [GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
app_1 | [GIN-debug] Listening and serving HTTP on :8080
ブラウザで http://localhost:3000/ にアクセスしてみてください。
{"message":"SUCCESS!!!!"}
が表示されたら成功です!
9. Hot Reloadを確認
最後に、Hot Reloadが有効になっているか確認してみましょう。
main.go
を修正し、変更が適用されているかを確認します。
以下のように修正して、保存してみましょう。
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "WOW, SUCCESS!!!!", # ← ここを変えた
})
})
r.Run()
}
ここで、ファイルを保存すると
app_1 | main.go has changed
app_1 | building...
app_1 | running...
↑のような感じになって変更を検知していることがわかります。
では再度ブラウザで localhost:3000 にアクセスしてみましょう。
ブラウザで以下のように表示されれば成功です。
{"message":"WOW, SUCCESS!!!!"}
以上、簡単ではありますが、Ginフレームワークの環境をdocker-composeで構築する手順まとめでした。
最後までお読みいただきありがとうございました。