golangをDockerでデプロイする¶
(golangでDocker上にデプロイする際に得られた知見を共有します。間違いやもっといい方法があればご指摘下さい)
golangはlibcなどに依存せず、さらにすべてstatic linkする、という特徴があります。これはどういうことかというと、golangで出力したバイナリが一つだけあれば動作する、ということです。
golangバイナリをDocker上で動かす¶
Dockerは異なる環境を動かすコンテナとして優れています。しかし、baseとなるイメージが巨大だったり、 docker pullは安全なの? だったりという問題も抱えています。
しかし、golangを使っている場合は、上記の特徴があるため、 出力したバイナリ + 必要なファイル だけで動作できます。(ただし、cgoなどを使っていない場合に限ります)
例¶
1. tar.gzを作成する¶
以下の様なディレクトリ構成だとします。
github.com/shirou/test
|-- main.go
|-- public
| `-- css
| `-- sample.css
`-- view
`-- base.html
main.goはpublicとviewを適当に使うwebアプリだとします。(別になんでもいいです)
そのまま全部tar.gzで固め、dockerを動かすhostにscpします。
GOOS=linux GOARCH=amd64 go build
tar cvfz /tmp/image.tar.gz .
scp /tmp/image.tar.gz docker:/tmp/
別に全部固めなくても必要なファイルだけ固めれば大丈夫です。実際にはbuild用ディレクトリを作成し、その中に必要なファイルをcopyしていくことになるでしょう。
2. docker import¶
docker host側でtar.gzからdocker imageを作成します。
cat image.tar.gz | sudo docker import - test:latest
3. docker run¶
あとは普通に動かせます。
sudo docker run -p 8000:8000 test:latest /test
利点¶
この方式では、以下の利点が生まれます。
docker pullやdocker hubが必要ない。private レポジトリも必要ない
必要なファイルだけなので、容量を消費しない
不必要なプロセスがまったく動いておらず、ファイルすら存在しないため、セキュリティ上問題が起こりえない(自分のプログラムに問題があった場合は別です)
構成管理をする必要がない(依存パッケージインストールなど必要ないし)
s3の利用¶
今回はtar.gzをscpで送っていますが、s3に置くことももちろんできます。 docker import
はURLを引数に渡せます。
一つのファイルに固める¶
今回は必要なファイルをコピーする方式をとっていますが、 go-bindata などを使うと、一つのバイナリファイルにすべてを固められます。 kocha を使うのもいいでしょう。
その場合、tar.gzなどは必要なく、Dockerfileでそのファイルを単に ADD
すれば動きます。
ハマりポイント¶
HTTPSで外部にアクセスする場合、 /etc/ssl/certs/ca-certificates.crt
が必要な場合があります。
まとめ¶
golangで作成したバイナリをDockerで動かすといろいろな利点が生まれるよ、ということを説明しました。ansibleなんて要らなかったんや!(嘘です)
Comments
comments powered by Disqus