開発用ベースイメージ
開発環境共通で使えるベースイメージを作成して、Docker Hubとかにアップロードする。
- FROM: Golang公式イメージをベースイメージにする
- 管理ツールをインストール
-
go generateで使う go tool
- stringer: enumの文字列表現コードを自動生成
- jsonenums: enumのjson表現コードを自動生成
- パッケージバージョン管理: gom
- Task runner: godo
-
go generateで使う go tool
FROM golang:1.6
MAINTAINER roothybrid7@gmail.com
# Install tools
RUN go get golang.org/x/tools/cmd/stringer \
github.com/mattn/gom \
gopkg.in/godo.v2/cmd/godo \
github.com/campoy/jsonenums \
github.com/pquerna/ffjson \
github.com/k0kubun/pp
アプリ用にカスタマイズしたDockerfile
開発用ベースイメージを基にカスタマイズして、アプリで使えるようにする。
※ローカルPCのプロジェクトディレクトリをVolumeとして接続している場合は、gomコマンドの実行は不要。
FROM roothy/golang-1.6-development
MAINTAINER roothybrid7@gmail.com
# Setup project
ENV HOSTING=bitbucket.org \
VCS_USER=team1 \
PROJECT=go_app
ENV WORK_DIR=/go/src/${HOSTING}/${VCS_USER}/${PROJECT}
WORKDIR $WORK_DIR
# Workaround: cached go packages not affected by the file changes.
ADD Gomfile ${WORK_DIR}/Gomfile
RUN gom update || echo "gom install error: $?"
RUN gom build
ADD entrypoint.sh ${WORK_DIR}/entrypoint.sh
ADD . $WORK_DIR
Dockerプロセスを起動するためのシェルスクリプト
- ON_WATCHという環境変数がセットされていれば、Task runnerを使って起動
Goアプリケーション
entrypoint.sh
#!/bin/bash -
set -o nounset # Treat unset variables as an error
set -x
env | grep ON_WATCH >/dev/null
if [ $? -eq 0 ]; then
godo server --watch
else
go install
go_app
fi
Go Consumerアプリケーション(Job-Worker)
consumer_entrypoint.sh
#!/bin/bash -
set -o nounset # Treat unset variables as an error
set -x
env | grep ON_WATCH >/dev/null
if [ $? -eq 0 ]; then
godo server --watch
else
go install
go_app runConsumer
fi
Task runner
main.go
package main
import (
do "gopkg.in/godo.v2"
)
func generateTasks(p *do.Project) {
p.Task("default", do.P{"scope", "runas", "errors", "uploadtype", "distrib", "cjob", "topic"}, nil)
// API Scope types
p.Task("scope", nil, func(c *do.Context) {
c.Run(`go generate`, do.M{"$in": "app/scope"})
}).Src("app/scope/*.go", "!app/scope/*_string.go")
// Data fetching/manipulating authority types
p.Task("runas", nil, func(c *do.Context) {
c.Run(`go generate`, do.M{"$in": "app/runas"})
}).Src("app/runas/*.go", "!app/runas/*_string.go")
// Error codes
p.Task("errors", nil, func(c *do.Context) {
c.Run(`go generate`, do.M{"$in": "app/errors"})
}).Src("app/errors/*.go", "!app/errors/*_string.go", "!app/errors/*_jsonenums.go")
// File upload type
p.Task("uploadtype", nil, func(c *do.Context) {
c.Run(`go generate`, do.M{"$in": "app/uploadtype"})
}).Src("app/uploadtype/*.go", "!app/uploadtype/*_string.go")
// Distribution file storage type
p.Task("distrib", nil, func(c *do.Context) {
c.Run(`go generate`, do.M{"$in": "app/distrib"})
}).Src("app/distrib/*.go", "!app/distrib/*_string.go")
// Job type
p.Task("cjob", nil, func(c *do.Context) {
c.Run(`go generate`, do.M{"$in": "module/cjob/ctype"})
}).Src("module/cjob/ctype/ctype.go")
// Message queue topic names(NSQ)
p.Task("topic", nil, func(c *do.Context) {
c.Run(`go generate`, do.M{"$in": "app/topic"})
}).Src("app/topic/*.go", "!app/topic/*_string.go")
}
func tasks(p *do.Project) {
p.Use("generate", generateTasks)
p.Task("generate", do.S{"generate:default"}, nil)
p.Task("default", do.S{"server"}, nil)
p.Task("server", do.S{"generate"}, func(c *do.Context) {
c.Start("cli.go app.go consumer.go", do.M{"$in": "./"})
}).Src("*.go", "**/*.go", "conf/*.toml").Debounce(3000)
p.Task("dbInit", nil, func(c *do.Context) {
c.Run(`go run cli.go app.go dbInit`, do.M{"$in": "./"})
})
}
func main() {
do.Godo(tasks)
}