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

Masteries

技術的なことや仕事に関することを書いていきます.

DockerでオレオレVPSを作った話

Docker Advnet Calendar 2014の6日目の記事となります.
今日は, 「DockerでオレオレVPSを作った話」というタイトルで, 最近作った「Pocker」という名前のアプリケーションを紹介したいと思います.

どうしてそのようなアプリケーションが必要になったのか, その中でのDockerの使い方や, 利用したテクニックなどについてお話できれば, と思っています.

あらすじ

自分は昔から「さくらのVPS」を愛用していて, 趣味で作った小規模な自分用ウェブアプリのようなものを, VPSの上に複数個設置していました.
さくらのVPSは非常に安価で, しかも価格が固定という事もあり, 小規模なウェブアプリを共存させるには最適だったのですが, 1つのVPS複数Webサービスを設置してくると, 「ゴミが溜まってくる」という問題が出てきます.

つまり, うまく管理していないと, 既に動いていない(運用を停止した)アプリケーションのコードやログ, 或いはそれが依存しているミドルウェアが消されずに残っていく訳ですね.
コードやログが残っているのはVPSのディスク容量を圧迫していきますし, 使っていないミドルウェアが残っているのはセキュリティ的にも余り宜しくありません.

解決方法としては, 1ウェブアプリ = 1VPS構成にする, という策がありますが, 小規模で, しかも自分用のウェブアプリのために1台のVPSを借りるのは, コストが非常に高いです.

そこで, 1つのVPSの上にDockerを使ってコンテナを建て, 1VPSに複数コンテナ, 1コンテナに1ウェブアプリ, という構成を作ることにしました.
いわば, Dockerのコンテナが1つのVPSになる, というイメージですね.
こうして出来上がったのが, PockerというオレオレVPS(のようなもの)です.

Pocker

Pockerは, 「あらすじ」で説明したような仕組みを実現するために用意した, Perl製のウェブアプリです.
コンテナの作成, 起動, 再起動, 停止, 削除といった操作や, Docker Hubからのイメージの取得, コンテナとドメインの紐付け(hoge.papix.netの80番ポートにアクセスすると, XXXXXというコンテナの80番ポートに繋げる, など)などの操作を行う為のウェブインターフェイスのようなものです.

コンテナとドメインの紐付けについては, nginxをリバースプロキシにしているだけで, 紐付けの設定を変更する度にnginxの設定ファイルを書き換えて読み込ませています.
その都合上, 各コンテナのIPは常に同じにしておきたいので, pipeworkを使って常に同じIPになるように固定しています.

現在, Pockerは「さくらのVPS」の2Gプラン(仮想3コア, メモリ2GB)の上で動いています.
私用のブログや昔使っていたブログなど, 4つ程度のウェブアプリを動かしていますが, 1ヶ月程前の導入から今まで, 問題なく動作しています.

Pockerについては, 以前「Perl Casual #6」で紹介させて頂いたりしています.

Dockerをサーバのように使う

さて, Pockerを作るにあたって考慮したのが, 「コンテナをサーバのように"も"使えるようにする」という事でした.
Pocker上に載せたい各ウェブアプリにDockerfileを用意して, これを用いてイメージを生成し, デプロイする事も出来たのですが, 一部のウェブアプリには, 既にAnsibleでデプロイを自動的に実行する仕組みを用意していました.

これらの資源をPockerでも有効に利用出来るように, Pockerでは「コンテナを起動すると, サーバのように使える」イメージを用意しました.
このイメージにはUpstartが入っており, /sbin/initでコンテナを起動すれば, 普通のサーバのように各種サービスが動き出します.
当然sshdも動き出すので, SSHでログインして諸々の操作をしたり, AnsibleでPlaybookを流しこんだりすることが出来ます.
こうすることで, 既存のWebアプリやその周辺資源(今回の場合, AnsibleのPlaybookなど)を有効活用しつつ, VPSのDockerによるオレオレVPS化を進めることができました.

Dockerのコンテナをサーバのように使う方法については, 次の記事が参考になります.

ステージング環境としてのDocker

...実は, Pockerのような仕組みは, 既に自分が所属している会社で導入されています.
私が所属しているGaiaXという会社では, 「DoX」というDockerを使ったステージングサーバ基盤が動いており, 小規模な業務改善アプリや, 脆弱性対応時の動作確認, 社内で開発しているWebアプリのステージング環境などとして使われています.

Dockerを利用してステージング環境を構築することで, コンテナを動かすサーバのリソースを有効に使うことが出来ますし, 複数チームのステージング環境を集約することが出来るので, コストの削減にも繋がります.
更に, Dockerのコンテナの作成や停止, 削除は非常に早いので, 「必要な時にコンテナを作って, 必要がなくなれば削除する」というのを, 非常にストレスなく繰り返すことができます.
これは非常に大事なことで, Perl CasualでPockerについて発表をした際の反響として, 他社のエンジニアの方からお聞きしたのが, 「ステージングサーバを簡単に作れない問題に結構悩んでいる」というお話でした.
自分の会社がDoXを作ったのも, まさにこの問題を解決し, 開発者がサーバを欲しいと思った時に, 安価かつ素早く提供することが出来るようにしたかった為でした.

このような環境を作る事で, 技術的挑戦の障壁が非常に低くなりました.
社員が作った小さな業務改善サービスを, 非常に簡単にデプロイすることが出来るようになったのです.
また, 新しいミドルウェアの試験運用も, ある程度DoX上で出来るようになりました.

例えば, 現在自分のチームではElasticsearchを利用したログの解析に取り組んでいますが, これは当初はDoXの上に導入して動かしていたものでした. 結果, もっと良いスペックのサーバで継続的に取り組んだ方が良い, という結論に至ったので, 現在はDoX上からオンプレのサーバに移行して運用しています.

このように, 「簡単かつ安価」なステージングサーバが提供出来れば, 「XXXという技術に挑戦してみたい!」というエンジニアの挑戦欲求を叶える為の障壁を, 大きく下げる事が出来るのではないかと思っています.
そして, このような挑戦の中で得た知見を業務に活かす事で, 開発しているWebアプリの改善も, 更に加速出来ると個人的には思っています.

Dockerの理想と現実

もちろん, そのような環境として, 「コンテナをサーバのように使う」のではなく, Dockerfileからイメージを作成し, これをデプロイする... というのが理想ではあります.
ただ, 既にオンプレやEC2の上で動いているWebアプリを, ステージング環境の為にDockerfileに対応する(してもらう)というのは, それなりのコストがかかります.
そのような環境において, Dockerのコンテナを「サーバのように」, 「ステージングで」使う/使ってもらうというのは, 選択肢の一つとして非常に有力だと思っています.

Dockerのコンテナを, まるで1つのサーバのように使うPockerやDoXといった仕組みは, まさに「オンプレからDockerへ」移行していく過渡期ならではの, 現実を見た視点の産物なのではないか, と最近思ったりしています.

まとめ

Dockerを, ステージング基盤として使う事について話しました.
DoXやPockerを見ていて, お手軽に環境を作ったり壊してり出来る世界観を作るためのツールとして, Dockerは非常に良い選択肢だなあ, と強く思っています.
プロダクションでのDockerの活用事例だけでなく, このようなステージング環境やCI環境におけるDockerの活用例についても, もっといろいろ挑戦したいですし, 知りたいなあ, と思ったりしています.

さて, 明日のDocker Advent Calendar 2014は, @hoto17296で「Dockerでつくるさいきょうのホームネットワーク」です. お楽しみに!

余談という名の宣伝

...余談ではありますが昨日担当の@saisa6153さんや, 明日担当の@hoto17296は, 自分と同じくGaiaXで働いているエンジニアです.

君もDocker対応企業(?)のGaiaXで働いてみないかっ!?

後日談

@studio3104さんから要望があったので, Pockerのコードを公開しました.
2日くらいでガツッと仕上げた代物なので, テストもドキュメントもないという惨状ではありますが, この記事で説明したような仕組みをどのように実現しているかは伝わる... のではないかと思っております.

近々, Pockerの内部についての詳細を解説する記事を書こうと思っておりますので, そちらも楽しみにして頂けますと幸いです.