GAミント至上主義

Web Monomaniacal Developer.

Dockerを3ヶ月本番環境で使って感じた今後の可能性

2016年5月ごろからbizoceanのデータ集計、解析プロジェクトにDockerを使いはじめ、本番環境にはGoogke Container Engineを使っている。

使ってみて、今後コンテナ技術はどんどん普及していくなと確信した。


利用の有無は、開発スピード、サーバーのコスト、メンテナンス費用など競争力に大きな差がつくと思う。

まだ使い始めて3か月もたっていないが、今後普及すると思っている根拠と、その良さをまとめてみようと思う。

Googleでの普及

Googleは言わずもがな、世界一ともいえるコンピューティング技術とインフラを持った企業だ。

Googleにおいてはデーターセンターの管理をしているBorgからコンテナ運用の実績があり、それをいかしてGKEのベースであるKubernetesの開発も行っている。

Dockerに使われているCgroupsももともとGoogleが開発したものらしい

さらに以前はGoogle App Engine上で動いていたCLOUD DATALAB
cloud.google.com
もDocker形式で配布しローカル、またGCE上で動かすようになっており、ユーザー側にも強要、とまでは言えないとしても使うように勧めている。

また、Google App EngineFlexible Environmentでは、ユーザー独自のDockerfileを使うこともできる。

開発サーバーをきれいに保てる

プロジェクトでは開発環境もすべてDocker上で動かしている。

そのおかげで、ホストマシン(Ubuntu)には、各サービスに必要なパッケージはいれずに、開発に必要なVim、tmuxなどごく少量のものしかインストールしていない。

これは特に複数人で使っている環境で、大きな利点となっている。私はPython3だけど、2が必要だとか、他の人はPHPしか書けない等の時でも、パッケージがごちゃごちゃにならない。

そのおかげでホストマシンのアップデートも早い。


環境ごと、サービスごとに必要なパッケージはすべてDokerfile上でインストールを指定しており、明示的なので、パッケージの競合で苦労したことはない。

あるとすれば、新しい環境を作るとき、既存のDockerfileからコピーしたものを使うことで、不要なもののインストールが残ってしまうことはある。これはDockerに限らない問題か。


開発時はよくいじるソースコードディレクトリをマウントしてrunしているので、ソースコードの反映はリアルタイムだ。

gunicornなどのアプリケーションサーバーを使ってる場合は、オプションでソースコードの変更を監視するオプションを指定すればいい。

バッチにも便利

一日1回本番DBからからデータを取ってきてgzipで固めるバッチ処理にもDockerをつかった。

Pythonシェルスクリプトで用意したファイルを、DockerのCMDに指定すればいい。

ライブラリもそのバッチに必要最低限なものだけいれるので、構成が非常にシンプルに保てるし、パッケージ化ができる。実行サーバーを変えるときもそのDockerfileがあればすぐ実行できる。


そしてDocker runコマンドで動作が確認できたら、それをcrontabに追加すればいい。

Dockerはスーパーユーザー権限が必要なので、rootのcrontabにいれるか、sudo dockerをユーザーがパスワードなしで出来るように権限の設定は必要。

バッチの実行が終わったらDockerも自動で終了するので、特に後処理はいらない。

冪等性なんていらなかった

Dockerを使う前は、サーバーごとの管理、差異に悩んでおり、Ansible等を使おうかと思っていた。

でもDocker使ってみるとすべて解決できた。

一度構築した環境を変更するのが間違っていた。

見知らぬ誰かが何年も前に構築し、たびたび手が入り、どうなっているのか分からず、でも動いているので怖くて触れないサーバーを前に、すべて抹消して、0から構築したいと感じたことがある人は多いと思う。

DockerはそれをDockerfileにそって、数秒から数分でできる。

確かにDockerfileで細かいバージョン指定なしのinstall、updateなどをすれば、その時によって入るものは異なり、冪等性はなくなる。

でも、今のところそれで困ったことはないし、正当に管理されているパッケージのアップデートで動かないのなら、自分のコードを直すべきだと思う。

入れ子OSなんていらなかった

Windows上のVMLinuxを動かしていた同僚がいたけど、私には重すぎて使う気にならなかった。家はUbuntuだし、今もWindowsからLinuxsshで繋げて開発している。

求めていたのは、環境の分離であり、ハードウェアのエミュレーションや入れ子になったほぼ完全なOSではない。ポートで分けられればIPも一つで問題ない。ポートを変えて使うだけならDockerの用意するネットーワークでほぼ困らない。


そして、これのおかげか、Googleがすごいのかわからないけど、サーバー代がすごく安し起動も早い。

ユーザー管理なんていらなかった

Dockerは基本的にすべてrootで動かす。

ただそれだけのことだけど、ホストのユーザー管理がちゃんとしてれば、新しい環境の立ち上げのたびにいちいちユーザーを作ったり、秘密鍵設定をしたり、権限設定する必要がない。

VPSなどもたくさん使ったけど、すごいストレスになっていたことに気づいた。

Dockerの中はすべてroot。すごくシンプル。

suはやるな、sudo使え、でもめんどいからやっぱりsudo suしちゃうなんてことはよくあるけど、環境が隔離されていていればrootで問題なかった。

1プロセス、1コンテナの原則の良さ

最初はちょっと分けたいサービスを作るのに、いちいちフォルダを作って、Dockerfileも作ってが面倒だったけど、本番運用するとこの利点の方が上回った。

いわゆるマイクロサービスにも繋がってるけど、更新はしやすいし、避けれない外部的なエラーに対しても影響範囲を最小限にできる。

必要なコンテナだけスケールアウトもしやすい。これによってスケールアウトするコードを書く力も身についてきた。


どうしても処理しきれないエラーが起きた場合も、Kubernetesでは一瞬で再起動してくれるので、安心してexitするだけでいい。


現在下記コンテナで運用中

  • WEBサーバー(gunicorn)Redisに書き込む&PubSubに送るやつ
  • Redis ほぼ公式のもの。再起動、アップデート用にGoogleの永続ディスクを接続している
  • Redisから読み込んでBigQueryに書き込むやつ
  • PubSubから受け取って、リアルタイム通知やスプレッドシートに書くするやつ
  • BigQueryのテーブルを作るやつ


今後もLinuxをうまく無駄なく使う方法としてDockerをはじめとしたコンテナは、今のところ一番いいと感じた。

課題

どうやって社内に浸透させるか

どんな技術でもそうだけど、やってもないのに分からないといって拒否する人がいたりするのは問題。もっと実績を公開していくのと、それぞれの組織に合わせて工夫が必要だと思う。
ポケモンGoの下記事例でちょっと説明しやすくなったと思う。(注:GKE、Kubernetesの文字はあるけど、Dockerは無い)。

cloudplatform.googleblog.com

死活監視

外側からHTTPなどで叩いて生死がわかるものはいいけど、外から見えないプロセス監視をどうするかはまだできていない。おそらくGCPのStackDriverでできるとは思う。
Kubernetesは死んだら再起動してくれるけど、死んだことは教えてくれない。

ローカル開発環境どうするか

できれば社内にもkubernetesを動かして開発したいけど、バージョンアップも多いし、kubernetesの運用、保守は面倒なのでまだやりたくない。
ローカルでは、dockerコマンドでできることだけにしておいて、全体のテストはGKEでもう一個つくるのが楽そう。n1-standard-1×1で動けば月4000円くらい?