Dockerとは何か?どこで使うべきか?

この記事はDockerに関する実験的な記事や,Buildpackを使ってHeroku AppをDocker Containerとして使えるようにする“building”の開発などで知られるCenturyLink Labsの “What is Docker and When To Use It”の翻訳です. Dockerとは何か?Dockerをどこで使うべきか?についてよく見かける記事とは違った視点から説明されています. 翻訳は許可をとった上で行っています.

Dockerとは何でないか

Dockerとは何かを説明する前に,Dockerは何でないかについて述べる.Dockerの否定形は何か?Dockerの制限は何か?Dockerが得意でないことは何か?

  • DockerはLXCのようなLinux Containerではない
  • DockerはLXCだけのラッパーではない(理論的には仮想マシンも管理できる)
  • DockerはChefやPuppet,SaltStackのようなConfiguration toolの代替ではない
  • DockerはPaaSではない
  • Dockerは異なるホスト間での連携が得意ではない
  • DockerはLXC同士を隔離するのが得意ではない

Dockerとは何か

では,Dockerは何ができるのか?メリットはなにか?

  • Dockerはインフラを管理することができる
  • Dockerはイメージのビルドや,Docker Indexを通じたイメージの共有ができる
  • DockerはChefやPuppetといったConfiguration toolによりビルドされたサーバのテンプレートにとって,イメージ配布の良いモデルである
  • DockerはCopy-on-wirteのファイルシステムであるbtrfsを使っており,Gitのようにファイルシステムの差分を管理することができる
  • Dockerはイメージのリモートレポジトリをもっているため,簡単にそれらを様々なOS上で動かすことができる

Dockerの代替は何か

AmazonのAWS MarketplaceはDocker Indexに近い.ただし,AMIはAWS上でしか動かすことができないのに対して,Dockerイメージは,Dockerが動いているLinuxサーバであればどこでも動かすことができる.

Cloud FoundryのWardenはLXCの管理ツールであり,Dockerに近い.ただし,Docker Indexのような他人とイメージを共有する仕組みを持っていない.

Dockerをいつ使うべきか

DockerはGitやJavaのような基本的な開発ツールになりうるものであり,日々の開発やオペレーションに導入し始めるべきである.

例えば,

  • インフラのバージョン管理システムとして使う
  • チームにアプケーション用のインフラを配布したいときに使う
  • 稼働中のサーバーと同様の環境をラップトップ上に再現して,コードを実行したいときに使う(例えばbuildingを使う)
  • 複数の開発フェーズ(dev,stg,prod,QA)が必要なときに使う
  • ChefのCookbookPuppetのManifestと使う

DockerとJavaはどこが似ているのか

Javaには”Write Once. Run Anywhere(一度書けばどこでも実行できる)”という文言がある.

Dockerはそれに似ている.Dockerは,一度イメージをビルドすると,Dockerが動いているLinuxサーバであれば全く同じようにそれを動かすことができる(“Build Once.Run Anywhere”).

Javaの場合,例えば以下のようなJavaコードがあるとする.

// HelloWorld.java
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

javac HelloWorld.javaにより生成されるHelloWorld.classは,JVMがあればどこでも動かすことができる.

Dockerの場合,例えば以下のようなDockerfileがあるとする.

FROM ubuntu:13.10

ENV DEBIAN_FRONTEND noninteractive
RUN apt-get update -qq -y && \
    apt-get install curl -qq -y && \
    apt-get clean

RUN curl -sSL https://get.rvm.io | bash -s stable --ruby=2.1.1

docker built -t tcnksm/rubyにより生成されるtcnksm/rubyイメージは,Dockerが動いていればどこでも動かすことができる.

DockerとGitはどこが似ているのか

Gitの公式には,”Tiny footprint with lightning fast performance(高速性能を備えた履歴管理)”という文言がある.Dockerはコードの変更履歴ではなく,ファイルシステムの変更履歴を管理する.

diff

Gitの場合,以下のようにコードの変更が確認できる.

$ echo 'Hello' > README.md
$ git diff --name-status
M       README.md

Dockerの場合,以下のようにファイルシステムの変更が確認できる.

$ ID=$(docker run -d ubuntu bash -c 'touch README.md; sleep 100')
$ docker diff $MY_DOCKER
A /README.md
C /dev
C /dev/core
C /dev/fd
C /dev/ptmx
C /dev/stderr
C /dev/stdin
C /dev/stdout

commit & push

Gitの場合,以下のようにコードの変更をコミットし,リモートレポジトリにpushする

$ git commit -m "Add README.md"
$ git push

Dockerの場合,以下のようにファイルシステムの変更をコミットし,リモートレジストリにpushする.

$ docker commit -m "Add README.md" $ID tcnksm/ubuntu
$ docker push tcnksm/ubuntu

pull

Gitの場合,以下のようにリモートレポジトリからコードを取得する.

$ git pull

Dockerの場合,以下のようにリモートレジストリからイメージを取得する.

$ docker pull tcnksm/ubuntu

まとめ

docker pushdocker pullといったイメージの共有機能は,Dockerの大きな特徴のひとつ.pullするだけで,あらゆるDockerイメージをどんなマシン上でも動かすことができるのは素晴らしい.push/pullの機能により,AppチームとOpsチームでインフラ構築の共同作業が簡単になる.Appチームは,アプリケーション用のコンテナの構築に集中でき,Opsチームはサービス用のコンテナの作成に集中できる.Appチームはアプリケーション用のコンテナをOpsチームに共有でき,OpsチームはMySQLやPostgreSQL,Redis用のコンテナをAppチームに共有できる.