realize + dockerでGolangのホットリロード付き開発環境を構築する
今回は、gin + gqlgen + gormなGoプロジェクトのホットリロード付き開発環境を構築します。
環境
- Go 1.12.6
プロジェクトの構造
.
├── db
│ └── db.go
├── models
│ ├── model_a.go
│ └── ...
├── schema
│ ├── schema.graphql
│ └── ...
├── server
│ └── server.go
├── docker-compose.yml
├── go.mod
├── go.sum
├── gqlgen.yml
└── ...
使用するホットリロードツール
realizeというツールを使用します。
他にもfreshなどのホットリロードツールがありますが、realize
の方が設定が細かくできるため、realize
を選択しました。
実は最初、fresh
で試していたのですが、Go Modulesモードに対応できないっぽかったです。
realize
では適切に設定を行うことで、対応可能となっていることがわかりました。
Dockerfileとdocker-compose.ymlの準備
以上を踏まえて、ホットリロードを行うためのDockerfile
とdocker-compose.yml
を準備します。
FROM golang:1.12.6-alpine
WORKDIR /app
RUN apk add --no-cache alpine-sdk git && go get -u github.com/oxequa/realize
EXPOSE 8080
CMD ["realize", "start"]
docker-compose.yml
にて、開発環境のディレクトリをコンテナにアタッチする設定を行います。
そのため、ここではソースをコピーは行わず、WORKDIR
と必要なパッケージのインストールのみ行います。
version: '3'
services:
db:
image: mysql:5.7
ports:
- "3306"
restart: always
command: ['mysqld', '--character-set-server=utf8mb4', '--collation-server=utf8mb4_unicode_ci']
environment:
MYSQL_DATABASE: sample
MYSQL_ROOT_PASSWORD: password
volumes:
- mysql-data:/var/lib/mysql
application:
build: .
environment:
MYSQL_DATABASE: sample
MYSQL_HOST: db
MYSQL_PASSWORD: password
MYSQL_PORT: 3306
MYSQL_USER: root
depends_on:
- db
ports:
- "8095:8080"
restart: always
volumes:
- .:/app
volumes:
mysql-data:
driver: local
以下の部分で、開発環境のディレクトリをコンテナにアタッチする場所を選びます。
アタッチ先として、Dockerfile
のWORKDIR
と同じ場所が設定されていることを確認します。
volumes:
- .:/app
realizeの設定
Dockerfile
のCMD
にてrealize start
を実行するようにしていますが、このコマンド単体ではアプリケーションが起動しません。
まずは手元でrealize start
を実行します。
$ go get -u github.com/oxequa/realize
# $GOPATH/binにPATHを通っていることを確認した後
$ realize start
すると.realize.yml
という設定ファイルが生成されます。
適当なgo
ファイルを変更しセーブすると、その旨がログに出力されることを確認し、Ctrl+Cで実行を終了します。
settings:
legacy:
force: false
interval: 0s
schema:
- name: sample
path: .
commands: {}
watcher:
extensions:
- go
paths:
- /
ignore:
paths:
- .git
- .realize
- vendor
アプリケーションを起動するにはrealize start --run
というふうに引数に--run
を与えるか、.realize.yml
を以下のように修正します。
- commands: {}
+ commands:
+ run:
+ status: true
通常、この状態でrealize start
するとアプリが立ち上がるのですが、Go Modules
モードである場合はエラーが発生して起動しません。
また、今回の場合はmain関数が定義されているファイルがmain.go
ではなく、server/server.go
にあるため、その点も特殊です。
これを吸収するための設定を追加します。
commands:
+ install:
+ status: true
+ method: go build -o app.out ./server/server.go
run:
status: true
+ method: ./app.out
これでホットリロードが有効な状態で、アプリケーションが立ち上がるようになります。
手元でrealize start
を実行し、挙動を確認しましょう。
realize
はデフォルトでプロジェクトをリビルドする際に$GOPATH/bin
にリビルドするためにgo install
を使用します。
Go Modules
モードでは$GOPATH
が存在しないので、go install
に失敗してしまいます。
これを避けるため、go install
ではなく、go build -o app.out ./server/server.go
を使用するように設定し、起動時はその成果物を利用して起動するようにしています。
docker-composeで起動
ここまでできれば後はdocker-compose
で起動するだけです。
docker-compose build
docker-compose up -d
Discussion
Go 1.15.2ではなくgo1.12.6ではないでしょうか?👀
修正しました!ご指摘ありがとうございました!
どうやらかなり未来に生きてしまっていたようです・・・