DockerHub公式の言語Stack

DockerHub Official Repos: Announcing Language Stacks | Docker Blog

DockerHubには公式のレポジトリがある.そこにはUbuntuやCentos,MySQLやPostgres,MongoといったDockerイメージがコミュニティーベースで,つまりより汎用的に使える形で開発され集められており,ベースイメージとして簡単に使えるようになっている.

今までは,OSのディストリビューションや,Webサーバ,DBなどがメインだったが,公式として各種プログラミング言語のベースイメージも公開された.現状(2014年9月時点)では,c/c++(gcc)clojuregolanghylangjavanodeperlPHPpythonrailsrubyがある.

特徴

この公式の言語stackには以下の3つの特徴がある.

これらを簡単に説明する.

Buildpack-deps

buildpack-depsイメージというのは,HerokuのStackのようなイメージで,各言語を動かすために必要な基本的な依存関係等がインストールされている.

Dockerfileは以下.

FROM debian:wheezy

RUN apt-get update && apt-get install -y \
    autoconf \
    build-essential \
    imagemagick \
    libbz2-dev \
    libcurl4-openssl-dev \
    libevent-dev \
    libffi-dev \
    libglib2.0-dev \
    libjpeg-dev \
    libmagickcore-dev \
    libmagickwand-dev \
    libmysqlclient-dev \
    libncurses-dev \
    libpq-dev \
    libpq-dev \
    libreadline-dev \
    libsqlite3-dev \
    libssl-dev \
    libxml2-dev \
    libxslt-dev \
    libyaml-dev \
    zlib1g-dev \
    && rm -rf /var/lib/apt/lists/*

RUN apt-get update && apt-get install -y \
    bzr \
    cvs \
    git \
    mercurial \
    subversion \
    && rm -rf /var/lib/apt/lists/*

よく言語をインストールする際に依存で入れるべきものが揃っている.これを元に各言語スタックは作成されるので,これらの依存のインストールし忘れなどを防ぐことができる.

Version

各言語スタックは適切にバージョンがタグとして付加されているため,使いたいバージョンを選んで使うことができる.例えば,rubyのv2.1.3を使いたければruby:2.1.3イメージを,pythonの3.4.1を使いたければpython:3.4.1イメージを選択できる.

ONBUILD

言語スタックでは,普通のイメージに加えて,ONBUILDイメージもサポートされている.

ONBUILDはDockerfileのコマンドで,これに続いて別のDockerfileコマンドを記述する.そして,そのDockerfileを元にビルドされたイメージをFROMとしてDockerfileを新たに作成し,ビルドを実行すると,上でONBUILDと共に記述したコマンドが実行される.つまり,Dockerfileに親子関係を持たせることができる(詳しくは,“DockerfileのONBUILD”に書いた).

これは結構良くて,言語スタックでは,依存関係ファイルのADDとインストールの実行,アプリのADDに使われている.例えば,RailsのONBUILDイメージの場合は,GemfileとGemfile.lockのADD,RailsアプリのADDが記述されている.つまり,RailsのONBUILDイメージを使えば,特殊なことをしていない限りDockerfileにほとんど何も書かなくて良い.

また,ここにはコミュニティ開発の良さも含まれていて,例えば,“RailsアプリをDockerにデプロイするときにGemfileを変更してなければBundle Installをスキップする方法”といった,Dockerfileのベストプラクティスがちゃんと含まれている.

使ってみる

とりあえず,いくつか軽く使ってみる.

rails

まず,railsイメージ.ruby:2.1.2イメージを元に作られたonbuildイメージを使う.このイメージは以下のDockerfileで作成されている.いくつかのONBUILDと,Railsを動かすのに必要なnodeのインストールなどが記述されている.

FROM ruby:2.1.2

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

ONBUILD ADD Gemfile /usr/src/app/
ONBUILD ADD Gemfile.lock /usr/src/app/
ONBUILD RUN bundle install --system

ONBUILD ADD . /usr/src/app

RUN apt-get update && apt-get install -y nodejs --no-install-recommends && rm -rf /var/lib/apt/lists/*

EXPOSE 3000
CMD ["rails", "server"]

これを使うのは簡単.実際にサンプルアプリを作って動かしてみる.まず,以下でDockerイメージをbuildする.

$ rails new sample-app
$ cd sample-app
$ echo 'FROM rails:onbuild' > Dockerfile
$ docker build -t tcnksm/sample-rails .

1行のDockerfileを作るだけで良い.それをbuildするとONBUILDにより,GemfileGemfile.lockADDbundle installが実行される.そして,カレントディレクトリのアプリケーションがADDされる.

後は以下を実行すれば,親DockerfileのCMDに記述されたrails serverで,コンテナが起動する.

$ docker run -d -p 3000:3000 tcnksm/sample-app
$ curl http://<container-ip>:3000

golang

golangだとアプリケーションを動かすより,コンテナによるクリーンな環境でのコンパイルに使うのが良さそう.それも簡単にできる.

例えば,tcnksm/ghrgo-1.3.1イメージでコンパイルする.

$ git clone https://github.com/tcnksm/ghr
$ cd ghr
$ docker run --rm -v "$(pwd)":/usr/src/ghr -w /usr/src/ghr golang:1.3.1 bash -c 'go get -d ./... && go build -v'

go-1.2イメージでコンパイルする.

$ docker run --rm -v "$(pwd)":/usr/src/ghr -w /usr/src/ghr golang:1.2 go build -v

go-1.3.1のクロスコンパイル用イメージwindows/386にクロスコンパイルする.

$ docker run --rm -v "$(pwd)":/usr/src/ghr -w /usr/src/ghr -e GOOS=windows -e GOARCH=386 golang:1.3.1-cross go build -v

コントリビュートしたい

プロジェクトを作ってpartners@docker.comにメールすれば,公式のDockerHubレポジトリとして取り込んでもらえる可能性もある.

以下のガイドラインに従う.

まとめ

Dockerが出たときって,Dockerfileを書くのは時代に逆行しているから自動生成しようといった意見やツールを見た.実際,自分でも“rbdockというRuby/Rails/Sinatra用のDockerfileを生成するgem”をつくったりした.でも,DockerHubのおかげで良いDockerfileをみんなで作って,そのイメージを使えるだけにしようという流れになっている.どんどん簡単になっていく.

ただ,いきなり使うのは危険で,例えばONBUILDとか何が仕込まれてるかbuildしないとわからい.ので,使う前にちゃんとDockerfileに一度目を通すのが大事かなと.その辺はOSSのツールを使うときと同じ.