この記事はTokyoSWアドベントカレンダー6日目の記事です。
業務では開発環境にDockerを使っていますが(といってもMySQLコンテナを立ててるだけ)、一から自分で設定したことはないので勉強のため導入してみようと思います。

docker for macを入れる

開発環境はMacを想定してます。
少し前までならVirtualBox上にLinuxを乗せて更にそこにDockerを入れてコンテナを乗せて…というふうにやってましたが、その時代は終わりました。

今はMac/Win向けに公式が出してくれているのでそれを使います。
これでVirtualBoxともオサラバです。

docker for macを入れるとメニューバーにdockerちゃんのアイコンが表示され、
docker/docker-machine/docker-composeのコマンドが使えるようになります。

今回は主にdocker-composeを使用して環境を構築します。

docker-composeとは複数のコンテナを同時に立ち上げ、さらに連携もできる便利なオーケストレーションツールです。
今回はアプリ用とデータストア用のコンテナを立ち上げるので非常に有用です。

アプリコンテナとデータストアコンテナの設定

普段業務ではScalaを使って仕事をしていますが、今回は趣味で開発しているGolang製のナレッジ共有ツールの開発環境をDocker化させようと思います。

snicket

ちなみにgoのhttpフレームワークであるechoを使っています。

アプリとデータストアを別々のコンテナとして立てます。
まずアプリ用コンテナを作るために以下の内容のDockerfileを作ります。

1
2
FROM golang:1.7
EXPOSE 5000

.dockerディレクトリを作成し、その下にDockerfileを置くようにしてみました。
これは好みがあると思いますが…

1
2
3
4
# プロジェクトルート
.docker
└── web
└── Dockerfile

docker-composeはdocker-compose.ymlというファイルで設定するので、プロジェクト直下にこれを置きます。
ファイルは以下のように設定しました。

docker-compose.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
version: '2'
services:
app:
build: .docker/web
ports:
- 5000:5000
links:
- mongo
volumes:
- .:/go/src/github.com/SnippetsBucket/snicket
command: bash -c 'cd /go/src/github.com/SnippetsBucket/snicket/ && go run server.go'
container_name: snicket-web
mongo:
image: mongo:3.4.0
ports:
- 27017:27017
volumes:
- mongo-data:/data/db
container_name: snicket-mongo
volumes:
mongo-data:
driver: local

appmongoの2つのコンテナを定義しています。
appは先程作ったDockerfileをビルドに使い、5000番ポートを開放し、mongoコンテナに繋ぐようにしています。
volumesでプロジェクトルートをコンテナにマウントし、コンテナ起動時にアプリをビルドしています。

※GOPATHについて

1
2
3
4
5
ホスト側と同じようにコンテナ内も同じようなディレクトリ構成にする必要があります。
Dockerfileで指定している公式イメージには既に/goが$GOPATHに設定されています。
ホスト側:$GOPATH/src/github.com/SnippetsBucket/snicket
コンテナ:$GOPATH/src/github.com/SnippetsBucket/snicket

mongoのvolumesは、通常はコンテナを再起動させた場合、コンテナ内のデータは消えてしまうためデータを永続化させるためにマウントさせています。

この時点でディレクトリ構成はこんな感じになりました。

1
2
3
4
5
.docker
└── web
│   └── Dockerfile
(中略)
└── docker-compose.yml

これで準備が整ったのでdocker-compose upをしてみます。
するとイメージのDLが行われ、ビルドされます。
おそらくmongoのコンソールがずらずらと表示されると思います。

別タブでdocker-compose psをしてみます。
コンテナ一覧の状態を見ることができます。

1
2
3
4
Name Command State Ports
-----------------------------------------------------------------------------------------
snicket-mongo /entrypoint.sh mongod Up 0.0.0.0:27017->27017/tcp
snicket-web bash -c cd /go/src/github. ... Up 0.0.0.0:5000->5000/tcp, 8888/tcp

そして最後にlocalhost:5000にブラウザからアクセスすると画面が表示されました。

もちろん5000番ポートを開けているのでアプリ側でも5000番をリッスンするようにしておく必要があります。

server.go
1
2
3
4
func main() {
router := router.Init()
router.Run(standard.New(":5000"))
}

なんらかの理由でコンテナ内に入りたいときはdocker-compose exec <サービス名> bashで入ることができます。
<サービス名>とはdocker-compose.ymlに書いたサービス名たちのことです。

最初container_nameの名前を指定してハマってました…。

  • コードの変更は次のようにコンテナを再起動すればOKです。
    docker-compose restart app

  • mongoにつなぎたいときは普通にmongoと打てば繋げます。

まとめ

これでgolangの快適な開発環境ができました。

virtualboxを起動していない分、起動も速いですし余計なメモリも食いません。

docker-composeのお陰でdockerが簡単に扱えていいですね。

ぜひこれを機にdocker入門してみませんか?