App Service on Linux のカスタム Docker Image を利用していると、やっぱり Heroku のように foreman を使ったプロセス管理が使いたくなってきました。
Heroku では Procfile をルートに用意しておくと、いい感じにランタイムが読み込んで実行してくれます。
2 月に試した時には Ruby on Rails アプリケーションの実行が上手く出来ませんでしたが、最近 Hanselman が動かしていたので試してみます。
Runtime Stack の Dockerfile やスクリプトもいい感じに公開されていたので、参考しながら利用します。
帝国兵殿曰く、Built-in の Runtime Stack に対しては特殊処理が入っているらしいので、独自の Runtime Stack を作る場合には少し手間がかかります。そのままの Dockerfile を使ってビルドしても上手くいきません。
なので多少カスタマイズした Dockerfile を用意しました。基本的な部分は変わりませんが WORKDIR を設定してみたり、ENTRYPOINT を追加してみたりしています。あと foreman のインストールを追加しています。
FROM ruby:2.3.3 COPY startup.sh /bin/ RUN apt-get update -qq \ && apt-get install -y nodejs --no-install-recommends \ && chmod 755 /bin/startup.sh RUN gem uninstall -i /usr/local/lib/ruby/gems/2.3.0 bundler RUN gem install bundler --version "=1.13.6" RUN gem install rubygems-bundler RUN gem regenerate_binstubs RUN gem install --no-user-install foreman RUN gem install --no-user-install passenger WORKDIR /home/site/wwwroot EXPOSE 3000 ENTRYPOINT ["/bin/startup.sh"]
エントリポイントとして実行するスクリプトは、ほぼ Ruby の Built-in Stack と同じものを用意しました。
最後に Procfile のチェックとポートを指定しての実行を行っています。
#!/bin/bash cd /home/site/wwwroot if [ -n "$SECRET_KEY_BASE" ] then echo 'Secret key base present' else echo 'Generating a secret key base' export SECRET_KEY_BASE=$(ruby -rsecurerandom -e 'puts SecureRandom.hex(64)') fi if [ -n "$RAILS_ENV" ] then echo 'RAILS_ENV set to $RAILS_ENV' else echo 'RAILS_ENV not set, default to production' export RAILS_ENV='production' fi echo 'Removing any leftover pids if present' rm -f tmp/pids/* ; bundle config --local path "vendor/bundle" if bundle check --path "vendor/bundle" | grep satisfied then echo 'dependency check passed' else echo 'missing dependencies, try redeploying' exit -1 fi echo 'running bundle install --local --deployment' bundle install --local --deployment foreman check foreman start -p 3000
作成した Docker Image は Docker Hub に push した後に、ポータルから設定をしておきます。
最後に作成しておいたテンプレそのままの Rails アプリケーションに対して Procfile を追加します。この辺りは Heroku で使う場合とほぼ変わらない形で問題ないです。
bundle exec を経由して、ポートを指定するのが重要です。
web: bundle exec rails server -p $PORT
Git を使ってデプロイ後、起動には少し時間はかかりますが空の Rails ページが表示されました。
RAILS_ENV が production になっているので、多少味気ない表示ですが動いているので問題ないですね。
最後に Kudu を使って Docker のログを確認してみると、ちゃんと foreman を使ってアプリケーションが起動されていることが確認できます。
web という名前でサーバーが立ち上がっています。
当然ながら web 以外にも常時起動するタイプのアプリケーションを、追加で動かすことも可能です。
App Service on Linux では Docker Swarm が使えないので Supervisord などを使ってきましたが、foreman を使った方が簡単なケースが多そうです。