以前heroku上でhubotのdockerコンテナを動かす記事を書いたのだが、2015年8月にアップデートがあり、docker-composeに対応した。
これに伴い、heroku toolbeltのdocker pluginからはdocker:start
が無くなり、普通にdocker-compose up
するだけでローカルで動作させることが可能になった。(前述の記事は意味の無い文章の羅列と化した。)
なお、内容は公式のGetting Startedをやるだけだが、途中自分がよく分からなかった所は詳しく書こうと思う。
今回はnodejsでやるけど、Railsとかでも多分だいたい一緒。
準備
あらかじめ、以下のものをインストールしておく必要がある。
- docker
- docker-compose
- Heroku Toolbelt
gitとかはもう書かなくてもいいよね。
あと、Node.js/Memcachedのサンプルリポジトリを引っ張ってきておく。
これはmemchachedを操作する簡単なwebアプリ。
$ git clone https://github.com/RedisLabs/memcachedcloud-node-sample.git
heroku toolbeltのdocker pluginも導入しておく。
$ heroku plugins:install heroku-docker
リポジトリの構成を確認
package.json
npmのパッケージを管理するためのファイル。
app.json
docker:initのために必要なファイル。色々書いてあるけど、重要なのは以下の2つ。
image
docker hubのどのimageを利用するかを指定する。
サンプルだと以下の部分。
...
"image": "heroku/nodejs",
...
重要な点として、herokuで動かすdocker imageは何でも良いわけではない。
基本的にはherokuが提供しているimageを用いるが、自分でheroku対応のimageを作ることも可能。(→ Modifying the Dockerfile)
公式に提供されているimageの一覧はこちら。
addons
heroku上で利用するアドオン名を指定する。
サンプルだと以下の部分。
...
"addons": [
"memcachedcloud:30"
]
}
Procfile
heroku上で実行するコマンドを指定するファイル。
web: node web.js
ローカルで動かしてみる
まずは以下のコマンドを入力。
$ heroku docker:init
このコマンドは、Procfileやapp.jsonに従って、Dockerfileとdocker-compose.ymlを生成する。
まずDockerfileの中を見てみると、単にapp.jsonで指定したimageを取ってくるだけであることがわかる。
FROM heroku/nodejs
次に、docker-compose.ymlだが、ここではweb
とshell
という二つのコマンドの定義と、memchachedcloudというエイリアス名のmemchachedコンテナを立ち上げるようになっている。
web:
build: .
command: 'bash -c ''node web.js'''
working_dir: /app/user
environment:
PORT: 8080
MEMCACHEDCLOUD_SERVERS: 'memcachedcloud:11211'
ports:
- '8080:8080'
links:
- memcachedcloud
shell:
build: .
command: bash
working_dir: /app/user
environment:
PORT: 8080
MEMCACHEDCLOUD_SERVERS: 'memcachedcloud:11211'
ports:
- '8080:8080'
links:
- memcachedcloud
volumes:
- '.:/app/user'
memcachedcloud:
image: memcached
webでは、Procfileで指定したコマンドを実行するコンテナを立ち上げる。
それに対してshellは単にbashを実行するので、任意のコマンドを実行できる状態になる。
また、app.jsonでaddonsにmemchachedを指定したので、環境変数とmemchachedコンテナも自動的に追加されている。
MEMCACHEDCLOUD_SERVERのホスト名に単にmemcachedcloudと指定するだけで接続できるのがよくわからなかったが、dockerのlinkオプションは/etc/hostsに指定したエイリアス名で追加するようだ。(環境変数を追加するだけだと思ってた……)
さて、生成されたファイルの確認が終わったので、おもむろにサーバを立ち上げてみる。
$ docker-compose up web
するとweb_1 | Listening on 8080
みたいなのが出るので、http://localhost:8080
にアクセス。
こんな感じの画面が表示されれば、正常に動作している。
Actionsのリンクを適当にクリックしてみて、memchachedと繋がっているのを確認する。
herokuにdeployする
deployは極めて簡単で、以下のコマンドを実行するだけ。
$ heroku docker:release
らくちん。
ところでMEMCHACEDCLOUD_USERNAMEって何やねん
web.jsを見ていると、最初にmemjsのclientを以下のように生成している。
var client = memjs.Client.create(process.env.MEMCACHEDCLOUD_SERVERS, {
username: process.env.MEMCACHEDCLOUD_USERNAME,
password: process.env.MEMCACHEDCLOUD_PASSWORD
});
MEMCACHEDCLOUD_USERNAMEとか、deployしたらherokuが勝手に設定するのは分かるけど、ローカルではいつ設定したんだよ…と思ったら、ローカルでは普通にundefinedだった。
memjsの仕様として値が入ってなかったら単に無視されるのかなーと思ってるけど、ちゃんと調べてない。
感想
今回の変更で個人的には以下の2点が嬉しいポイントだと感じている。
- heroku toolbelt無しでも、docker-composeがあればローカルで動く
- heroku add-onsをあまり意識しなくてよくなった
なので、 herokuのことが嫌いになっても別の適当な場所で動かせる
dockerのメリットであるポータビリティが活かせるようになった。
自前のサーバでもいいし、OpenShiftもdocker対応したので動くんじゃないかなーたぶん。
とりあえずheroku対応のdocker imageでアプリ作っとけば幸せになれるんじゃないかと思います。