フォルダ構成をきちんとしないとハマる元
- vendoringも含めた本格ウェブアプリのデプロイは、フォルダ構成とかちゃんとしとかないとハマります・・・
- 自分で書いたコードをどこに置くか、vendorをどこに置くか
- その上でDockerfileをどう書くとスムーズにデプロイしてくれるか
といったことを書きまとめておきます。
以下で構築したIntelliJでの開発環境と合わせてうまくいっています。
プロジェクトのフォルダ構成
- ソースファイルを$GOPATH/ドメイン名/パッケージ名の下に置くのは鉄則!
- 今回は、$GOPATH/example.jp/sample1/とします
- 自分はプロジェクトツリーは以下のようにしています
$GOPATH/example.jp/sample1/以下の配置
ファイル or ディレクトリ | 説明 |
---|---|
app/ | 自分で書いたgoファイルを置く場所。サブディレクトリからなる |
vendor/ | github.com/hoge/fugaなどサードパーティ製のvendoringしたいものを置く |
template/ | テンプレートファイル。app/の中に入れても良い。お好みで |
assets/ | 画像やjs、cssなど静的ファイル置き場。これもapp/の中に入れても良い |
main.go | main()を含むアプリ実行の拠点 |
Dockerfile | Dockerコンテナをビルドするためのお馴染みファイル |
Dockerrun.aws.json | 起動ポートなどを指定 |
.ebextensions | Beanstalk環境への追加設定 |
上記はすべてデプロイに必要なディレクトリ or ファイルとなります。.ebextensionsはファイルアップロード上限指定を行うので、事実上必須だと思います。
Beanstalk + DockerでEntity Too Largeエラーでアップロードできない問題
それ以外は以下のようにフォルダを掘って、そこに置いています。
ファイル or ディレクトリ | 説明 |
---|---|
dev/ | 開発でのみ必要なものを入れる |
dev/script/ | スクリプトファイル置き場 |
dev/gulp/ | .coffeeや.scss置き場。ここからgulpでall.js、all.cssを作って、assetsへコピーしたりする |
いずれにせよ、これらはデプロイ時には必要ないものです。
vendor/への配置
- オープンソースなサードパーティ製パッケージは、go getで最新を得るのではなく、バージョンを固定しておきたい場合があります
- これらはvendor/へ配置します
- git submoduleで配置すると良いでしょう
- 仮にgithub.com/Sirupsen/logrusパッケージをサブモジュールとしてvendorに配置する場合、以下のようにgit submoduleコマンドを叩きます
git sumodule add https://github.com/Sirupsen/logrus.git vendor/github.com/Sirupsen/logrus
Dockerfile
#
# golang:1.6-onbuildではないことに注意。onbuildだとうまくいかないかも・・・
#
FROM golang:1.6
#
# vendoringせずgo getで得る依存パッケージをつらつらと書く
#
RUN go get github.com/golang/protobuf/proto
RUN go get golang.org/x/text/currency
RUN go get golang.org/x/image/draw
RUN go get golang.org/x/image/bmp
RUN go get golang.org/x/image/tiff
RUN go get golang.org/x/net/context
RUN go get gopkg.in/go-playground/validator.v8
RUN go get gopkg.in/yaml.v2
#
# golang:1.6で$GOPATHとなっている/go/以下へ必要なファイルとディレクトリを配置
# ドメイン/パッケージ名は、ローカル開発環境と一致するようにすることが大事
#
ADD app /go/src/example.jp/sample1/app
ADD assets /go/src/example.jp/sample1/assets
ADD vendor /go/src/example.jp/sample1/vendor
ADD main.go /go/src/example.jp/sample1/main.go
EXPOSE 5000
WORKDIR "/go/src/example.jp/sample1/"
CMD ["go", "run", "main.go"]
Dockerrun.aws.json
Dockerfileに合わせて5000ポートを指定
{
"AWSEBDockerrunVersion": "1",
"Ports" : [{ "ContainerPort": "5000" }]
}
これでHTTPおよびHTTPSのリクエストが、Dockerコンテナ内で起動しているウェブアプリ(main.go)がListenしている5000
ポートに流れてきます。
デプロイするファイルはzipで固める
eb deployコマンドでデプロイしますが、デフォルトではgit archiveしてできたzipをアップロードします。しかし、それだとgit submoduleを含まないので、デプロイ先でビルドに失敗します。
以下に書いたように、自前のスクリプトでzipに固めて、それでeb deployでデプロイするようにしたほうがいいでしょう。
今回はzipを以下のようにしてzipを作ります。
zip -r deploy.zip Dockerfile Dockerrun.aws.json main.go app assets vendor template .ebextensions
いちいち打つのは面倒なのでシェルスクリプトにして、上記の後にeb deployを実行するようにしておくと良いでしょう。
プロジェクトルートの.elasticbeanstalk/config.ymlに以下の行を追加します
deploy:
artifact: deploy.zip
デプロイする
ここまできたら、
$ eb deploy
するだけでいけるはず!成功を祈ります。