96

この記事は最終更新日から1年以上が経過しています。

@po3rin

Go v1.11 + Docker + fresh でホットリロード開発環境を作って愉快なGo言語生活

Go言語 + Docker で開発することが多くなってきました。ファイル更新の度にローカルでサーバー動作確認して、コンテナで動作確認してーなんてのはめんどくさいので、
Dockerコンテナ内とローカルで volume を貼ってホットリロードできる開発環境を試したので記事にします。

GitHub にも 試したプロジェクトは置いてあります。
https://github.com/po3rin/go-playground/tree/master/hot_reload_docker

構成

とりあえずローカルでの構成を参考に書いときます。プロジェクト名などは柔軟に。

hot_reload_docker
├── Dockerfile
├── docker-compose.yml
├── go.mod
└── main.go

ローカルでの作業

go1.11 から出た modules を使っています。go のバージョンが1.11以上になっているか確認してください。

$ go version
go version go1.11.1 darwin/amd64

modules を使う手順もさらっと紹介していきますが、さらっとなので、くわしくは下記のサイトなどを参考に!Wantedlyさんの記事です。

Go 1.11 の modules・vgo を試す - 実際に使っていく上で考えないといけないこと #golang
https://www.wantedly.com/companies/wantedly/post_articles/132270

まず環境変数 GO111MODULE=on を設定します。

export GO111MODULE=on

これで module が有効になります。
go のプロジェクト内で下記を打ち込み、go.modを作ります。

$ go mod init

これで適当に main.go を作ります。

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": "ping",
        })
    })
    r.Run(":8083")
}

ここで

$ go run main.go

をすると サーバー軌道の前にパッケージの読み込みが行われます。modules ではgo testgo buildなどのタイミングで
必要なパッケージの読み込みを自動で行ってくれます。便利!とりあえず動作確認しておきましょう。

$ curl localhost:8083
{"message":"ping"}

いいですね。

Docker化 と ホットリロード

まずは Dockerfile です。

Dockerfile

FROM golang:1.11.1

WORKDIR /go/src/hot_reload_docker
COPY . .
ENV GO111MODULE=on

RUN go get github.com/pilu/fresh
CMD ["fresh"]

ポイントは環境変数 GO111MODULE=on の設定ですね。いままで Dockerfile 内で go getとかdep ensureとかやっていたのはもういりません。go testgo buildなどのタイミングで必要なパッケージの読み込みを自動で行ってくれるからです。

そして今回はgithub.com/pilu/fresh を導入しています。これはファイルを監視し、更新されたらホットリロードしてくれます。ゆえに今回はfreshコマンドでサーバーを起動します。

あとはローカルでのファイル更新とコンテナ内のファイル更新を連打させるだけです。これは Docker の volumes という昨日を使います。
管理しやすいように docker-compose を採用します。docker-compose.yml を作りましょう。

docker-compose.yml
version: '3'
services:
  app:
    build: .
    volumes:
      - ./:/go/src/hot_reload_docker
    ports:
      - "8083:8083"

ポイントは volumes です。<<ローカルのディレクトリパス>>:<<コンテナのディレクトリパス>>でvolumeをはり、ローカルのファイル更新でコンテナ内のファイルを更新するようにします。これでローカルでファイルを編集すれば、コンテナ内で起動しているサーバーがホットリロードされます。

動作確認

さっそく動作確認してみましょう。

Dockerコンテナ起動

$ docker-compose up -d

動作確認

$ curl localhost:8083
{"message":"ping"}

動いてますね。ではローカルでファイルを更新してみましょう。ping を pong に変えました。

main.go
// ...

func main() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run(":8083")
}

ファイルを更新したらホットリロードされます。数秒更新に時間がかかるので少し待ったのち、動作確認しましょう。

curl localhost:8083
{"message":"pong"}

ping が pong になりました。これで愉快なGo言語生活を送れます。

GitHub にも 試したプロジェクトは置いてあります。
https://github.com/po3rin/go-playground/tree/master/hot_reload_docker

96
ユーザー登録して、Qiitaをもっと便利に使ってみませんか。
  1. あなたにマッチした記事をお届けします
    ユーザーやタグをフォローすることで、あなたが興味を持つ技術分野の情報をまとめてキャッチアップできます
  2. 便利な情報をあとで効率的に読み返せます
    気に入った記事を「ストック」することで、あとからすぐに検索できます
po3rin
ブログを移しました。https://po3rin.com/
shiroyagi_corp
私たちは、自然言語処理、機械学習、データ処理のエキスパートです。データとコンピューティングの力を使って、一人ひとりの持つ時間の価値を最大化します。

コメント

この記事にコメントはありません。
あなたもコメントしてみませんか :)
ユーザー登録
すでにアカウントを持っている方はログイン
記事投稿イベント開催中
Trend Micro Cloud One を使ってAWS環境をよりセキュアにする方法について投稿しよう!
~
開発環境を豊かにする開発事例
~