読者です 読者をやめる 読者になる 読者になる

Dockerでffmpegもimagemagickも怖くないという話

Infrastructure インフラ ツール 開発環境

クックパッド 広告事業部の大野晋一です。責任範囲は広告事業の純広告およびネットワーク広告の商品開発担当で、事業部にはそれぞれの売上でコミットしています。

この記事では、動画変換の仕組みにおけるDockerの活用について紹介します。

クックパッドは8月8日、iOS/Androidのブラウザにおいて動画クリエイティブを掲出する広告商品を公開しました。広告商品としての詳細はプレスリリーススライドを見ていただくのがわかりやすいのですが、本稿に関係する特徴としてスマートフォンのブラウザで自動的に再生が開始されるというものがあります。

スマートフォンのブラウザにおいては、現在のところ、動画を自動再生させることは出来ません。これはAppleやGoogleといったブラウザベンダが課している制約です。そこで、クックパッドでは、janiというライブラリを使い、特定の規則に基づいて作られた画像を、JavaScriptで"動かす"ことによって自動再生を実現しました。

今回の話はこの変換の仕組みである、janiConverterに関するものです。

動画変換の仕組み:janiConverter

変換のざっくりとした処理手順としては

  1. 動画から、fpsで指定された頻度で静止画を切り出す
  2. 切り出した静止画を一定のルールで縦につなぎ合わせる
  3. 2で得た画像群をブラウザから読み出すことの出来るストレージに配置する
  4. 3の配置に応じたDOMをHTMLとして出力する
  5. ブラウザが、DOMおよびjaniのJavaScriptを受け取ると、動画として再生が可能になる

というものです。ここで1ではffmpegを使い、2ではimagemagickを使います。つまり、janiConverterを動かすインスタンス上にはffmpegとimagemagickが必要です。

もう一度言うと、「ffmpeg」と「imagemagick」がインストールされたインスタンスが必要です。

このふたつはコンパイルとセットアップが面倒なソフトウェアの東西横綱といっても過言ではなく、いろいろあって(※)、Dockerを使うことにしました。cookpadで本番投入されたDockerはこれが初めてになります。

※: いろいろというのは、主に個人的な興味と、試行錯誤で開発機の環境を汚したくないというのと、インフラストラクチャー部との30分ほどの検討のことです。おそらくインフラストラクチャー部としてもDockerの最初の被験者を捜していたところに、そこまでパフォーマンスが問われなくて社内向け、という良い鴨が現れた格好なのではないかと思っています

Dockerの導入

とはいっても、導入は簡単で、Linuxでセットアップする際のコマンドを普通にDockerfileに書いていくだけです。ffmpegについては、既に公開されているcellofellow/ffmpegを使わせてもらっています。

使ってみて一番良いなと思ったのはこの「普通にDockerfileを書けばOK」というところで、例えば、アプリケーションコードがDockerに依存したり影響を受けたりすることが無いのはDockerの良さです。

Dockerのメリットとおすすめの適用場面

そして、動画変換の仕組みを運用していくなかで以下のようなメリットがあると思っています。

  • 新しいインスタンスを用意する際にffmpeg/imagemagickの面倒な準備が必要ない。jenkinsがリポジトリの更新をポールして常に最新の状態でdocker buildしてくれているので、インスタンスはそれをpullしてくるだけ
  • janiConverterではsidekiqを使っており、実際のエンコードをworkerが処理するが、複数のworkerを立ち上げることが容易に出来る。ここでもworker用のインスタンスはdocker pullするだけ。リビジョンさえ同じなら全てのworkerの環境が同じであることが保証される
  • Docker依存がアプリケーションコードや設定ファイルに入らない。いつでも他の手段に移れる

また、開発においても次のような良さを体験できました。

  • 複数worker環境でのテストが容易である。マシンリソースの許す限りひたすらdocker runして立ち上げてテストできる
  • 本番と完全に同じ環境が保証される。たまたま開発環境で動いているみたいなバグをテストしてつぶしやすい。実際に、OS XとLinuxでの挙動の違いによるバグを発見して修正できた(初歩的ですね……)。
  • アプリケーションのポータビリティがいやでもある程度保証される。環境依存がハードコードされないのは良い

今回のように、master-worker構成が必要な仕組みを作ったり、ファイルなどのOS依存が出やすいものを扱う場合には開発においてもメリットは大きく、お勧めできます。そうした特徴のない通常のアプリケーションであれば開発段階ではあまりメリットはなさそうです。

Docker自体を運用していくノウハウとか、大量のトラフィックやリクエストをさばくノウハウなどはまだまだ確立されていないという感触ですが、このあたりは、今後当社のインフラストラクチャー部からも共有されていくことでしょう。

/* */ @import "/css/theme/report/report.css"; /* */ /* */ body{ background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527163350.png'); background-repeat: repeat-x; background-color:transparent; background-attachment: scroll; background-position: left top;} /* */ body{ border-top: 3px solid orange; color: #3c3c3c; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; line-height: 1.8; font-size: 16px; } a { text-decoration: underline; color: #693e1c; } a:hover { color: #80400e; text-decoration: underline; } .entry-title a{ color: rgb(176, 108, 28); cursor: auto; display: inline; font-family: 'Helvetica Neue', Helvetica, 'ヒラギノ角ゴ Pro W3', 'Hiragino Kaku Gothic Pro', Meiryo, Osaka, 'MS Pゴシック', sans-serif; font-size: 30px; font-weight: bold; height: auto; line-height: 40.5px; text-decoration: underline solid rgb(176, 108, 28); width: auto; line-height: 1.35; } .date a { color: #9b8b6c; font-size: 14px; text-decoration: none; font-weight: normal; } .urllist-title-link { font-size: 14px; } /* Recent Entries */ .recent-entries a{ color: #693e1c; } .recent-entries a:visited { color: #4d2200; text-decoration: none; } .hatena-module-recent-entries li { padding-bottom: 8px; border-bottom-width: 0px; } /*Widget*/ .hatena-module-body li { list-style-type: circle; } .hatena-module-body a{ text-decoration: none; } .hatena-module-body a:hover{ text-decoration: underline; } /* Widget name */ .hatena-module-title, .hatena-module-title a{ color: #b06c1c; margin-top: 20px; margin-bottom: 7px; } /* work frame*/ #container { width: 970px; text-align: center; margin: 0 auto; background: transparent; padding: 0 30px; } #wrapper { float: left; overflow: hidden; width: 660px; } #box2 { width: 240px; float: right; font-size: 14px; word-wrap: break-word; } /*#blog-title-inner{*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-position: left 0px;*/ /*}*/ /*.header-image-only #blog-title-inner {*/ /*background-repeat: no-repeat;*/ /*position: relative;*/ /*height: 200px;*/ /*display: none;*/ /*}*/ /*#blog-title {*/ /*margin-top: 3px;*/ /*height: 125px;*/ /*background-image: url('http://cdn-ak.f.st-hatena.com/images/fotolife/c/cookpadtech/20140527/20140527172848.png');*/ /*background-repeat: no-repeat;*/ /*background-position: left 0px;*/ /*}*/