【個人メモ】buildingを使って気軽にDocker containerをつくろう

# buildingとは

仕事を一生懸命していた中、
Twitterのタイムライン中に以下のブログエントリが流れてきた。

http://www.centurylinklabs.com/heroku-on-docker/

heroku-on-docker、パーマリンクからして楽しそうだ。

エントリの内容を見てみると、初文に
アプリケーションをDockerで動かすのは難しい、
もっと簡単にしよう。Herokuみたいに。

と書いてあったので、
これよさ気なんじゃね？と思ったので触ってみた。

# 検証環境

僕の環境は以下の通り

OS: Mac OS X 10.9.2

## 開発環境

...今回の検証のためにインストールをする
必要があるソフトウェアは以下の通り。

- [homebrew](http://brew.sh/)
- [Virtualbox](https://www.virtualbox.org/)
- [boot2docker](https://github.com/boot2docker/boot2docker)
- [docker](https://www.docker.io/)

gistにBrewfileをあげておいた。
homebrewをインストールした後、
以下のコマンドを叩いていってソフトウェアをインストールする。

```
> ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
> git clone https://gist.github.com/9926658.git
> cd 9926658
> brew bundle
```

# buildingのインストール

buildingはgemパッケージであり、以下のコマンドを実行してインストールする。

```
> gem install building --no-ri --no-rdoc
```

なぜグローバルインストールするのか、についてなのだけれど、
Gemfileをアプリケーションと同じディレクトリに置くと
Herokuはrubyアプリケーションとして認識してしまうためだ。

これから、node.jsを利用したサンプルアプリをアップロードするため、
グローバルインストールを行っている。

# サンプルアプリをとりあえず作ってみよう

http://www.centurylinklabs.com/heroku-on-docker/

このエントリに書かれているnode.jsアプリを書いてみた。

※以下のgithubリポジトリから、出来上がったテンプレートはcloneできる。

https://github.com/futoase/testing-building

```js:server.js
var PORT = process.env.PORT || 8080;
var express = require('express');

var app = express();
app.use(app.router);

app.get('/', function(req, res) {
  res.send("Welcome to underground");
});

app.listen(PORT);
```

```json:package.json
{
  "name": "test-app",
  "version": "0.0.1",
  "private": true,
  "main": "server.js",
  "engines": {
    "node": ">=0.10.0",
    "npm": ">=1.3"
  },
  "dependencies": {
    "express": "~3.0"
  }
}
```

## buildingによりDocker imageを作る

以下のコマンドでDocker imageを作成する。

```
> building test/node-app
```

```docker build``` が始まり、imageが作成される。。
**image** が出来上がると、
```docker run``` コマンドでcontainerを作るように促される。

![スクリーンショット 2014-04-02 19.15.29.png](https://qiita-image-store.s3.amazonaws.com/0/3985/b91945be-ac22-22be-0f1b-282b15e8abfd.png)

今回は、boot2docker の ポート 8080 と、
ホスト(Mac Book Pro Retina 13 inch) のポート 8080 を
明示的にポートフォワードする。

```
> VBoxManage controlvm "boot2docker-vm" natpf1 "test-port-of-httpd,tcp,127.0.0.1,8080,,8080" # port forwarding from docker container to host.
> docker run -d -p 8080:8080 -e "PORT=8080" test/node-app:latest
```

ブラウザで開いて、見てみよう。

```
> open http://localhost:8080/
```

![スクリーンショット 2014-04-02 19.57.58.png](https://qiita-image-store.s3.amazonaws.com/0/3985/8612d7e1-0a45-a3c0-55ed-2c59633e30b9.png)

おお、アプリケーションが起動している。

## herokuにもpushしてみよう。

herokuにもpushしてみよう。
Procfileを書いて置くことを忘れずに。

```:Procfile
web: node server.js
```

```
> heroku create
> git push heroku master
> open http://foolish-bastion-2718.herokuapp.com/
```

![スクリーンショット 2014-04-02 20.00.13.png](https://qiita-image-store.s3.amazonaws.com/0/3985/244df341-1151-c220-dab0-b9aea810512c.png)

うむ。動いている。

## build-packを試してみたが...

[参考にしているエントリ](http://www.centurylinklabs.com/heroku-on-docker/)では、
build-pack-hhvmを適用して、
wordpressをhhvmにて動かしていた。

![スクリーンショット 2014-04-02 20.10.55.png](https://qiita-image-store.s3.amazonaws.com/0/3985/9947f428-c95f-d98d-359c-779fc15c5144.png)

build-pack、すでにあるものを
カスタマイズして適用してみるか、と思って
試してみた。

対象とするのは以下のbuild-pack。
(このbuild-packは、すでにdocker imagesに入っているものだ)

https://github.com/CHH/heroku-buildpack-php

```php
display_errors=on
```

に変更したphp.iniを適用した
build-packを使ってみようと思った。

カスタマイズしたbuild-packはすでに作ってある。

https://github.com/futoase/heroku-buildpack-php

## 早速適用しようと思ったものの...

Dockerfileを用意してやったけど、色々とハマった。

1) すでにある同じbuild-packは使えない

buildpackを引数に渡してbuildingを実行することで
buildpackを追加できるようなので以下のコマンドを実行して試してみた。

```
> building -b https://github.com/futoase/heroku-buildpack-php futoase/faid-app
```

が、```git clone``` する時点で、同じbuild-packが存在する、と怒られる。

![スクリーンショット 2014-04-01 22.49.35.png](https://qiita-image-store.s3.amazonaws.com/0/3985/d0493246-30c8-2248-5a0b-65114cb75f27.png)

うぅ

2) カスタマイズしたDockerfileを用意しても結局デフォルトのDockerfileに上書きされてしまう

以下のDocker commandを実行し、
自分がカスタマイズしたbuild packを適用しようと試みた。

```shell-session:Dockerfile
FROM ctlc/buildstep:ubuntu13.10

RUN find /build/buildpacks -type d -delete
RUN truncate --size 0 /build/buildpacks.txt

RUN git clone --depth 1 https://github.com/futoase/heroku-buildpack-php /build/buildpacks/heroku-buildpack-php
RUN echo https://github.com/futoase/heroku-buildpack-php-test >> /build/buildpacks.txt
ADD . /app
RUN /build/builder
CMD /start web
```

buildingにオプションを引き渡し、
カスタマイズしたbuild-packを利用しつつ、
作成したDockerfileを適用しようとした。

```
> building -d Dockerfile futoase/faild-app test
```

が、無理だった。
buildingを実行したディレクトリで作成されたDockerfileは、
意図したものにはならなかった。

```shell-session:Dockerfile
FROM ctlc/buildstep:ubuntu13.10
FROM ctlc/buildstep:ubuntu13.10
ADD . /app
RUN /build/builder
CMD /start web
```

うーむ、コマンド行が全部削除されてしまった。

buildingが利用するdocker imageにすでに含まれている
build-packを利用する場合は、カスタマイズは諦めたほうがよいのかな。

https://index.docker.io/u/ctlc/buildstep/

に含まれているbuild-packは以下の通り。

- https://github.com/heroku/heroku-buildpack-ruby.git
- https://github.com/heroku/heroku-buildpack-nodejs.git
- https://github.com/heroku/heroku-buildpack-java.git
- https://github.com/heroku/heroku-buildpack-play.git
- https://github.com/heroku/heroku-buildpack-python.git
- https://github.com/heroku/heroku-buildpack-scala.git
- https://github.com/heroku/heroku-buildpack-clojure.git
- https://github.com/heroku/heroku-buildpack-gradle.git
- https://github.com/heroku/heroku-buildpack-grails.git
- https://github.com/CHH/heroku-buildpack-php.git
- https://github.com/kr/heroku-buildpack-go.git
- https://github.com/oortcloud/heroku-buildpack-meteorite.git
- https://github.com/miyagawa/heroku-buildpack-perl.git
- https://github.com/igrigorik/heroku-buildpack-dart.git
- https://github.com/rhy-jot/buildpack-nginx.git
- https://github.com/Kloadut/heroku-buildpack-static-apache.git
- https://github.com/bacongobbler/heroku-buildpack-jekyll.git
- https://github.com/ddollar/heroku-buildpack-multi.git

# buildingの活用方法

弄ってみて、わかったのは

1. Herokuアプリを動かそうというプロダクトではない(そう言ってるし)。あくまでHeroku風だ。
2. Herokuアプリを作るかの如くDocker上でアプリを実行できる環境を気軽に作れるものだ
3. すでに一覧に出したが、数多くのheroku-build-packをdocker imageに包含している。ansibleなどで言語環境を構築する手間が省けると思う

ということか。ウェブアプリを作る上で、
動作環境を作るのが億劫で、Herokuでの
アプリ作成ノウハウの延長線上で作りたくて、

```
> building hoge/app-name
```

とコマンド打ち込むだけでアプリの動作環境が作れる(docker image)、且つ
Docker上でアプリが立ち上がるのですぐに動作確認が行えるのは楽だ。

[boot2dockerのWindows向けinstallerも公開されている](https://github.com/boot2docker/windows-installer)ので、
Mac OS X ユーザが作ったアプリのモックアップを
Windows ユーザに向けてさくっと送りつけて実行させたい
場合に役に立ちそうだ。