本記事は2018年5月に公開されました。
Go Modules に対応した記事を再投稿しましたので、
そちらを参照ください。
Docker + Go + Gin の開発環境を準備する 2020/02
Go + Gin で Web API を構築する際の開発環境を準備します。
Docker、Go ともに不慣れだったので、
まずは Gin の クイックスタートが動作するところまでの備忘録です。
いつも環境を用意してくれていたチームメンバーに感謝です
なお、macOS Sierra 上でのみ検証した結果です。
構成
- Docker:Docker Community Edition for Mac
- Docker version 18.03.1-ce, build 9ee9f40
- docker-compose version 1.21.1, build 5a3f1a3
 
- イメージ:golang By Docker
- パッケージ管理:dep
- ライブリロード:codegangsta/gin
- Webフレームワーク:gin-gonic/gin
ディレクトリ
後々 DB 用コンテナも作成する事を考慮したプロジェクト構成にしています。
.
├── .dockerignore
├── docker
│   └── api
│       └── Dockerfile
├── docker-compose.yml
└── src
    └── api
        ├── Gopkg.lock
        ├── Gopkg.toml
        └── main.go
.dockerignore
今のところ何も指定していません。
Dockerfile*
Dockerfile
# API Image 作成
# ベースとなるイメージ
FROM golang:1.10.2-alpine3.7
# Gopkg.toml 等を事前にコピーして dep ensure が実行できるようにする
COPY src/api /go/src/api/
# dep ensure を行うプロジェクトルートに移動する
WORKDIR /go/src/api/
# 必要なパッケージをイメージにインストールする
RUN apk update \
  && apk add --no-cache git \
  && go get -u github.com/codegangsta/gin \
  && go get -u github.com/golang/dep/cmd/dep \
  && dep ensure
# コンテナ実行時のデフォルトを設定する
# ライブリロードを実行する
CMD gin -i run
docker-compose.yml
除外するというよりは他 volume に逃がす(永続化した)というような印象でした。結局のところ Gopkg.toml を編集する際には volume を事前に削除しないと変更前の volume でマウントされ上書きされてしまいます。
version: '3'
# マウント時に vendor 以下を削除してしまうため、別 volume を指定する
# Gopkg.toml を編集する場合、vendor ボリュームも削除しイメージを再構築する
volumes:
  vendor:
services:
  api:
    build:
      context: .
      dockerfile: docker/api/Dockerfile
    volumes:
      - ./src/api:/go/src/api
      - vendor:/go/src/api/vendor
    ports:
      - 3001:3001
    tty:
      true
Gopkg.toml
Gopkg.toml は仮イメージ、仮コンテナを作成して dep init して作成しました。
仮イメージ、仮コンテナは削除しました。
[[constraint]]
  name = "github.com/gin-gonic/gin"
  version = "1.2.0"
[prune]
  go-tests = true
  unused-packages = true
main.go
クイックスタートをコピペしてポート指定のみ編集しています。
package main
import "github.com/gin-gonic/gin"
func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "ping",
		})
	})
	// ポートを設定しています。
	r.Run(":3001")
}
出力結果
これで、以下のようにブラウザからアクセスできます。
