DockerでGolang最小開発環境構築

最近仕事でちょこちょこGolang書いてるが
ある程度環境できた状態でプロジェクトに入ったので
自身の学習のためにもゼロから環境作ってみる

Docker環境作成

とりあえず「Hello World」出すとこ目標にしようと思う
Golangおすすめディレクトリ構成によるとDockerfile系はbuildディレクトリに配置するといいみたいなのでこんな感じ

$ tree
.
├── build
│   └── Dockerfile
└── cmd
   └── hello
       └── main.go

3 directories, 2 files

とりあえず最小限でいいのでDockerfileはこんな感じ

FROM golang:1.14.6

WORKDIR /go/src/app

Hello worldのソースコード作る

cmd/main.goにHello worldコードを作成

package main

import "fmt"

func main() {
	fmt.Println("Hello world")
}

Hello worldしてみる

コンテナを作成して、一通りgolangの動作確認

$ docker build build -t go-ucwork
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM golang:1.14.6
---> a794da9351a3
Step 2/3 : WORKDIR /go/src/app
---> Using cache
---> b2ba000ed6e9
Step 3/3 : COPY . .
---> Using cache
---> 3f3eb8aa39d2
Successfully built 3f3eb8aa39d2
Successfully tagged go-ucwork:latest
$
$ # コンテナ作成して中に入ってみる
$ docker run --rm -v $PWD:/go/src/app/ -it go-ucwork bash
root@206e0ac91b26:/go/src/app#
root@206e0ac91b26:/go/src/app# # Go Moduleの初期化
root@206e0ac91b26:/go/src/app# go mod init github.com/shintaro-uchiyama/go-ucwork
go: creating new go.mod: module github.com/shintaro-uchiyama/go-ucwork
root@206e0ac91b26:/go/src/app# 
root@206e0ac91b26:/go/src/app# cat go.mod
module github.com/shintaro-uchiyama/go-ucwork

go 1.14
root@206e0ac91b26:/go/src/app#
root@206e0ac91b26:/go/src/app# # go importsをインストールしてgo moduleの動作確認
root@206e0ac91b26:/go/src/app# goimports
bash: goimports: command not found
root@206e0ac91b26:/go/src/app# 
root@206e0ac91b26:/go/src/app# go get golang.org/x/tools/cmd/goimports
go: downloading golang.org/x/tools v0.0.0-20200729041821-df70183b1872
go: found golang.org/x/tools/cmd/goimports in golang.org/x/tools v0.0.0-20200729041821-df70183b1872
go: downloading golang.org/x/mod v0.3.0
go: downloading golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543
root@206e0ac91b26:/go/src/app#
root@206e0ac91b26:/go/src/app# head -n 2 go.sum
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
root@206e0ac91b26:/go/src/app#
root@206e0ac91b26:/go/src/app# goimports cmd/hello/main.go
package main

import "fmt"

func main() {
	fmt.Println("Hello world")
}
root@206e0ac91b26:/go/src/app#
root@206e0ac91b26:/go/src/app# ls -la ${GOPATH}/bin/
total 5820
drwxrwxrwx 1 root root    4096 Jul 29 12:54 .
drwxrwxrwx 1 root root    4096 Jul 29 12:52 ..
-rwxr-xr-x 1 root root 5945488 Jul 29 12:54 goimports
root@206e0ac91b26:/go/src/app# # GOPATH配下にインストールされてる
root@206e0ac91b26:
root@206e0ac91b26: # ビルドして実行してみる
root@206e0ac91b26:/go/src/app# go build -o hello cmd/hello/main.go
root@206e0ac91b26:/go/src/app# ./hello
Hello world

とりあえずビルドしてバイナリファイル実行できた!

Hot Reload対応

都度ビルドして実行するのは面倒なので、変化があるたびにビルドしたい
とりあえず星たくさんついてるしrealizeでやってみる

$ # コンテナ作成して中に入ってみる
$ docker run --rm -v $PWD:/go/src/app/ -it go-ucwork bash
root@206e0ac91b26:/go/src/app#
root@c2949874d450:/go/src/app# go get github.com/oxequa/realize
go: downloading github.com/oxequa/realize v1.5.2
go: downloading github.com/oxequa/realize v2.0.2+incompatible
go: github.com/oxequa/realize upgrade => v2.0.2+incompatible
go: finding module for package gopkg.in/urfave/cli.v2
go: finding module for package github.com/oxequa/interact
go: downloading golang.org/x/net v0.0.0-20200625001655-4c5254603344
go: finding module for package gopkg.in/yaml.v2
go: finding module for package github.com/fsnotify/fsnotify
go: finding module for package github.com/sirupsen/logrus
go: finding module for package github.com/labstack/echo
go: finding module for package github.com/go-siris/siris/core/errors
go: finding module for package github.com/labstack/echo/middleware
go: finding module for package github.com/fatih/color
go: downloading gopkg.in/yaml.v2 v2.3.0
go: downloading github.com/labstack/echo v1.4.4
go: downloading github.com/fsnotify/fsnotify v1.4.9
go: downloading github.com/fatih/color v1.9.0
go: downloading github.com/sirupsen/logrus v1.6.0
go: downloading github.com/oxequa/interact v0.0.0-20171114182912-f8fb5795b5d7
go: downloading gopkg.in/urfave/cli.v2 v2.2.0
go: downloading github.com/go-siris/siris v7.4.0+incompatible
go: downloading github.com/labstack/echo v3.3.10+incompatible
go: found github.com/oxequa/interact in github.com/oxequa/interact v0.0.0-20171114182912-f8fb5795b5d7
go: found gopkg.in/urfave/cli.v2 in gopkg.in/urfave/cli.v2 v2.2.0
go: found github.com/fatih/color in github.com/fatih/color v1.9.0
go: found github.com/fsnotify/fsnotify in github.com/fsnotify/fsnotify v1.4.9
go: found github.com/go-siris/siris/core/errors in github.com/go-siris/siris v7.4.0+incompatible
go: found github.com/labstack/echo in github.com/labstack/echo v3.3.10+incompatible
go: found github.com/sirupsen/logrus in github.com/sirupsen/logrus v1.6.0
go: found gopkg.in/yaml.v2 in gopkg.in/yaml.v2 v2.3.0
go: github.com/oxequa/realize imports
	gopkg.in/urfave/cli.v2: gopkg.in/urfave/cli.v2@v2.2.0: parsing go.mod:
	module declares its path as: github.com/urfave/cli/v2
	        but was required as: gopkg.in/urfave/cli.v2
root@206e0ac91b26:/go/src/app# # む。なんかインストール止まった?
root@206e0ac91b26:/go/src/app#
root@c2949874d450:/go/src/app# ls -la ${GOPATH}/bin/
total 8
drwxrwxrwx 2 root root 4096 Jul 22 23:09 .
drwxrwxrwx 1 root root 4096 Jul 29 13:34 ..
root@c2949874d450:/go/src/app#
root@206e0ac91b26:/go/src/app# # インストールできてない・・・

ググった感じrealizeはgo moduleに対応してないくさい👶

reflexなるものが良さそう。これでやってみよう

$ # とりあえずコンテナに入る
$ docker run --rm -v $PWD:/go/src/app/ -it go-ucwork bash                                                                                                                    +[feature/create_env]
root@c2949874d450:/go/src/app#
root@c2949874d450:/go/src/app# go get github.com/cespare/reflex
go: downloading github.com/cespare/reflex v0.2.0
go: github.com/cespare/reflex upgrade => v0.2.0
go: finding module for package github.com/kballard/go-shellquote
go: finding module for package github.com/fsnotify/fsnotify
go: finding module for package github.com/ogier/pflag
go: finding module for package github.com/kr/pty
go: downloading github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
go: downloading github.com/ogier/pflag v0.0.1
go: downloading github.com/kr/pty v1.1.8
go: found github.com/fsnotify/fsnotify in github.com/fsnotify/fsnotify v1.4.9
go: found github.com/kballard/go-shellquote in github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
go: found github.com/kr/pty in github.com/kr/pty v1.1.8
go: found github.com/ogier/pflag in github.com/ogier/pflag v0.0.1
go: downloading github.com/creack/pty v1.1.7
go: downloading golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9
root@c2949874d450:/go/src/app#
root@c2949874d450:/go/src/app# reflex -r '(\.go$|go\.mod)' -s go build -- -o hello cmd/hello/main.go
[00] Starting service
[00] Killing service
[00] Starting service

goファイル修正すると標準出力にKilling serviceとかStarting serviceが出てくるのでgoファイル修正に反応してそう!
別ターミナルでコンテナ入って出力されたバイナリファイル実行すると
変更が反映されてる

$ docker ps                                                                                                                                                                  +[feature/create_env]
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
c2949874d450        go-ucwork           "bash"              34 minutes ago      Up 34 minutes                           crazy_varahamihira
$ docker exec -it c2949874d450 bash
root@c2949874d450:/go/src/app#
root@c2949874d450:/go/src/app# ./main
Hello world
root@c2949874d450:/go/src/app#
root@c2949874d450:/go/src/app# # goファイルを修正して実行try!
root@c2949874d450:/go/src/app# ./main
Hello world 2

Dockerfileを完成させる

コンテナに入って検証したので
都度再現できるようにDockerfileを完成させる

FROM golang:1.14.6

WORKDIR /go/src/app

RUN go get github.com/cespare/reflex
CMD reflex -r '(\.go$|go\.mod)' -s go build -- -o hello cmd/hello/main.go

ビルド&起動&hot reload確認

$ docker build -f ./build/Dockerfile -t go-ucwork .
$ docker run -d -v $PWD:/go/src/app/ --name go-ucwork go-ucwork
57beafc406f8bcc3cc63d385e3abfff0f0ecce74ba3c4524c81c4aa3f62c990e
$ 
$ docker exec -it go-ucwork ./hello
Hello world
$ 
$ # main.goファイル修正
$ docker exec -it go-ucwork ./hello                                                                                                                                          +[feature/create_env]
Hello world 4

まとめ

とりあえずローカルにgolangインストールしなくても
Docker環境で動かすことはできた
次はwebアプリケーション環境作っていきたい

この記事が気に入ったらサポートをしてみませんか?