社内向けアプリで本番環境でも使っている dokku のバージョン 0.5.3 をいろいろ試しやすくするために vagrant 環境で試してみました。
確認バージョン
- VirtualBox 5.0.16
- Vagrant 1.8.1
- dokku 0.5.3
dokku v0.5.0 での主な変更点
v0.5.0 での主な変更点は以下の通りです。
- docker 1.10/1.11 のサポートと、 docker 1.9.1 以上の必須化
- ドキュメント改善
- Deployment Tasks (
app.jsonでのscripts.dokku.predeployとscripts.dokku.postdeployのサポート) - Dockerfile Deployment で
Procfileサポート、EXPOSEの扱いの変更 - persistent storage plugin のオフィシャル化
初期設定
git clone https://github.com/dokku/dokku で clone してきたディレクトリの中に入って vagrant up します。 最初は box のダウンロードもあるので時間がかかります。
xip.io を使ってサブドメインを使ったデプロイを試します。
http://10.0.0.2.xip.io/ を開き、 Hostname を 10.0.0.2.xip.io にして Use virtualhost naming for apps にチェックを入れて、 Finish Setup を押します。
http://dokku.viewdocs.io/dokku/application-deployment/ にリダイレクトされるので、そのチュートリアルを試します。
チュートリアル前の準備
vagrant ssh で入って操作します。
docker コマンドや dokku コマンドで sudo を不要にするためにグループに追加します。
sudo usermod -aG docker vagrantsudo usermod -aG dokku vagrant
ビルド中のダウンロードでタイムアウトしにくくするためにタイムアウト時間をのばします。
dokku config:set --global CURL_TIMEOUT=120
dokku run などで実行して終了したコンテナが溜まっていかないようにするために、デフォルトで --rm をつけるようにします。(この設定をしなくても git push したときに自動で実行される dokku cleanup で削除されます。)
dokku config:set --global DOKKU_RM_CONTAINER=1
チュートリアル
チュートリアルも vagrant ssh で入った環境で試します。 sudo dokku plugin:install 以外はホスト側からでも実行できます。
-
git clone git@github.com:heroku/ruby-rails-sample.gitで rails のサンプルを clone しておきます。 -
dokku apps:create ruby-rails-sampleでアプリケーションを作成します。データベースとのリンクに必要なので、事前に作成していますが、 https://github.com/heroku/node-js-sample のように単独で動くアプリケーションでは事前にapps:createしなくても構いません。 -
sudo dokku plugin:install https://github.com/dokku/dokku-postgres.gitで postgres プラグインをインストールします。インストールの後処理でpostgres:9.5.0,svendowideit/ambassador:latest,dokkupaas/wait:latestが docker pull されるので、ダウンロードに少し時間がかかります。 -
docker imagesで確認するとわかるのですが、なぜかgliderlabs/herokuishが 0 バイトのイメージになってしまっているのでdocker pull gliderlabs/herokuishでダウンロードしておきます。ここもダウンロードに時間がかかります。この手順は普通にインストールした場合は不要なはずです。 -
dokku postgres:create rails-databaseでデータベースのコンテナを作成してdokku postgres:link rails-database ruby-rails-sampleでリンクします。 -
git remote add dokku dokku@10.0.0.2:ruby-rails-sampleで remote に dokku を登録してgit push dokku masterでデプロイします。 -
curlコマンドでエラーになった場合、CURL_TIMEOUTをのばして、再度git push dokku masterします。 -
http://ruby-rails-sample.10.0.0.2.xip.io/を開いてHello Worldと現在時刻が UTC (+0000) で表示されていたら成功です。
チュートリアル後の変更例
現在時刻が UTC で表示されていたので JST に変更してみます。
dokku config:set ruby-rails-sample TZ=Asia/Tokyo
http://ruby-rails-sample.10.0.0.2.xip.io/ を開いて Hello World と現在時刻が JST (+0900) で表示されていたら成功です。
rake db:migrate を実行する
dokku run ruby-rails-sample bundle exec rake db:migrate で実行できます。
scripts.dokku.predeploy で rake db:migrate を自動実行する
Deployment Tasks に書いてあるように v0.5.0 から app.json に scripts.dokku.predeploy を設定できるようになっているので、そこで rake db:migrate を自動実行するように設定してみます。
heroku が対応している scripts.postdeploy は初回の deploy 時にしか実行されないのに対して、 scripts.dokku.predeploy と scripts.dokku.postdeploy は毎回実行されるという違いがあります。
diff --git a/app.json b/app.json
index 452cef1..4c828fa 100644
--- a/app.json
+++ b/app.json
@@ -5,6 +5,9 @@
"repository": "https://github.com/heroku/ruby-rails-sample",
"logo": "https://upload.wikimedia.org/wikipedia/commons/c/c3/Ruby_on_Rails_logo.svg",
"scripts": {
+ "dokku": {
+ "predeploy": "bundle exec rake db:migrate"
+ },
"postdeploy": "bundle exec rake db:migrate"
},
"env": {
という変更を commit して push して動作確認します。
さらに rails g model などで migration ファイルを作成してさらに動作確認できます。
pre-flight checks
Zero Downtime Deploys に書いてあるようにゼロダウンタイムデプロイを実現するために CHECKS ファイルを作成します。 (デプロイ後のメッセージに Shutting down old containers in 60 seconds とあるように、デプロイして新しいコンテナに切り替わった直後の 1 分間は古いコンテナも動いています。)
以下の内容の CHECKS ファイルを作成して、デプロイ時の起動確認をデフォルトの 10 秒待つだけの動作から、 http で特定の URL にアクセスして指定した内容が含まれるかどうかのチェックに変更します。
/ Hello World
デフォルトでは 5 秒ごとに 5 回までのチェックですが、以下の内容にすると 10 秒ごとに 20 回までのチェックになります。 起動に時間がかかるアプリケーションの場合に、回数を増やしたり時間をのばしたりすると良いと思います。
WAIT=10
ATTEMPTS=20
/ Hello World
アプリケーションを削除する
dokku apps:destroy ruby-rails-sample で削除できます。 heroku での削除と同じように、確認のため、アプリケーション名を再度入力しないと消えないようになっています。
データベースも作成していたので、同様に dokku postgres:destroy rails-database で削除します。
node-js-sample を試す
Dokku の昔のバージョンのチュートリアルは node-js-sample を使っていたので、 node-js-sample も試してみます。
git clone git@github.com:heroku/node-js-sample.gitcd node-js-samplegit remote add dokku dokku@10.0.0.2:node-js-samplegit push dokku master
http://node-js-sample.10.0.0.2.xip.io/ を開いて Hello World! が表示されたら成功です。
動作確認用シェルスクリプト
rails g model 用に anyenv と rbenv を使って ruby と rails のインストールまでしています。
実行前に http://10.0.0.2.xip.io/ を開いて設定をしないと途中で失敗して止まります。
#!/bin/bash
set -euo pipefail
set -x
cd /home/vagrant
sudo usermod -aG docker vagrant
sudo usermod -aG dokku vagrant
dokku config:set --global CURL_TIMEOUT=120
dokku config:set --global DOKKU_RM_CONTAINER=1
if [[ ! -d ruby-rails-sample ]]; then
git clone https://github.com/heroku/ruby-rails-sample.git
fi
if [[ ! -d /home/dokku/ruby-rails-sample ]]; then
dokku apps:create ruby-rails-sample
fi
if [[ ! -d /var/lib/dokku/plugins/available/postgres ]]; then
sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git || :
sudo docker pull gliderlabs/herokuish
fi
if [[ ! -f /home/dokku/ruby-rails-sample/DOCKER_OPTIONS_RUN ]]; then
dokku postgres:create rails-database || :
dokku postgres:link rails-database ruby-rails-sample
fi
pushd ~/ruby-rails-sample
if ! git remote | grep -q dokku; then
git remote add dokku dokku@10.0.0.2:ruby-rails-sample
fi
git push dokku master
if ! dokku config ruby-rails-sample | grep -q '^TZ'; then
dokku config:set ruby-rails-sample TZ=Asia/Tokyo
fi
popd
if [[ ! -d node-js-sample ]]; then
git clone https://github.com/heroku/node-js-sample.git
fi
pushd ~/node-js-sample
if ! git remote | grep -q dokku; then
git remote add dokku dokku@10.0.0.2:node-js-sample
fi
git push dokku master
popd
if [[ -z "$(dpkg -l | grep nodejs)" ]]; then
sudo sed -i~ -e 's/us\.archive/jp.archive/' /etc/apt/sources.list
sudo apt-get update
sudo apt-get -y install autoconf bison build-essential libssl-dev libyaml-dev libreadline6-dev zlib1g-dev libncurses5-dev libffi-dev libgdbm3 libgdbm-dev
sudo apt-get -y install libpq-dev
sudo apt-get -y install nodejs
fi
if [[ ! -d ~/.anyenv ]]; then
git clone https://github.com/riywo/anyenv.git ~/.anyenv
echo 'export PATH="$HOME/.anyenv/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(anyenv init -)"' >> ~/.bashrc
fi
if [[ -z "$(command -v anyenv)" ]]; then
export PATH="$HOME/.anyenv/bin:$PATH"
set +x
eval "$(anyenv init - --no-rehash)"
set -x
fi
if [[ ! -d ~/.anyenv/envs/rbenv ]]; then
anyenv install rbenv
fi
if [[ -z "$(command -v rbenv)" ]]; then
set +x
eval "$(anyenv init - --no-rehash)"
set -x
fi
ruby_version=$(awk '/^ruby/{print $2}' ~/ruby-rails-sample/Gemfile | tr -d "'")
if ! rbenv versions | grep -q "$ruby_version"; then
rbenv install "$ruby_version"
fi
if [[ ! -f ~/.gemrc ]]; then
cat <<EOF >~/.gemrc
install: --no-rdoc --no-ri --format-executable
update: --no-rdoc --no-ri --format-executable
EOF
fi
export RBENV_VERSION="$ruby_version"
if ! gem list | grep -q bundler; then
gem install bundler
fi
pushd ~/ruby-rails-sample
bundle
cat <<EOF >CHECKS
WAIT=10
ATTEMPTS=20
/ Hello World
EOF
git add CHECKS
git commit -m "Add pre-flight checks file" || :
git push dokku master
cat <<EOF >app.json
{
"scripts": {
"dokku": {
"predeploy": "bundle exec rake db:migrate"
}
}
}
EOF
git add app.json
git commit -m "Set script.dokku.predeploy to app.json" || :
git push dokku master
popd
pushd ~/node-js-sample
cat <<EOF >CHECKS
/ Hello World!
EOF
git add CHECKS
git commit -m "Add pre-flight checks file" || :
git push dokku master
popd
まとめ
vagrant を使って dokku をいろいろ試す環境を簡単に作ることができました。 この環境を使ってテストやデバッグなどいろいろ試しやすくなると思います。