Hama Blog

Hama Blog

主にtech関連の記録

RailsアプリケーションをDokkuにデプロイする

概要

個人開発しているサービスを Heroku で運用していたのだが、無料プランが 2022/11/28 (だいぶ前)に終了したのもあり、いつか別の環境に変更しようと思っていた。

Heroku の代替サービスとなるものは色々な記事でまとめられているが、個人的に Dokku (オープンソースで提供されている PaaS) がよさそうだったので、今回は VPS + Dokku 環境にデプロイしてみた。

Dokku 自体は無料で利用できるので、VPS のレンタル先次第で Heroku より安く運用できる。

自分は Heroku で Redis も使用していた関係で $8/月 かかっていたが、今回は ConoHa で VPS をレンタルして Heroku より安く済んだ。

(1年プランにしたのもあって、月500円くらいになった)

記事執筆時の環境

手順

VPS の契約

Dokku は UbuntuDebian 上にインストールする必要がある1 ため、それらが使える環境を用意する。

今回は料金が安かったので、ConoHa の VPS をレンタルしてみた。

Dokku のドキュメントによると、メモリは1GB以上必要2 なので以下を選択した。
※以下は記事執筆時点の料金なので自分が契約したときよりちょっと高くなっていた。

https://www.conoha.jp/vps/?btn_id=top--commonHeader_vps-top

OS は Ubuntu の 22.04 (64bit) を選択した。

サーバー作成時のオプションで SSHキーの作成、登録も同時にできるので、ここであわせてやっておくと楽だった。

Dokku のインストール

VPS が用意できたら、Dokku のドキュメントに従いインストールする。

https://dokku.com/docs/getting-started/installation/#installing-the-latest-stable-version

wget https://dokku.com/install/v0.30.3/bootstrap.sh
sudo DOKKU_TAG=v0.30.3 bash bootstrap.sh

上記の実行に10分くらいかかった。

完了後、SSHキーを登録する。

cat ~/.ssh/authorized_keys | dokku ssh-keys:add admin

グローバルドメインの設定 (dokku domains:set-global) では IP アドレスを指定することも可能らしいが、今回はお名前.comで独自ドメイン (この記事内では example.com と呼ぶことにする) を取得してみたので、それを使う。

dokku domains:set-global example.com

Rails アプリケーションのデプロイ

これも基本的に Dokku のドキュメントに従えばよい。

https://dokku.com/docs/deployment/application-deployment/

ローカル環境で、デプロイしたいリポジトリをクローンする。

git clone https://github.com/[your_user_name]/[your_repository_name]

今度は SSH 接続したサーバー上でアプリの登録をする。(今回は rails-sample-app という名前で進めます)

dokku apps:create rails-sample-app

次に DB のインストールをする必要があるが、PostgreSQL を使っているならドキュメントのとおり進めればいけるはず。

sudo dokku plugin:install https://github.com/dokku/dokku-postgres.git

dokku postgres:create railsdatabase

dokku postgres:link railsdatabase rails-sample-app

もし MySQL を使っているなら、上記の代わりに以下のようにする。

sudo dokku plugin:install https://github.com/dokku/dokku-mysql.git mysql

dokku mysql:create railsdatabase

dokku mysql:link railsdatabase rails-sample-app

再度、ローカル環境に戻り、クローンしたリポジトリディレクトリで以下を実行する。

git remote add dokku dokku@example.com:rails-sample-app
git push dokku main:master

git push 時に DB 未作成によるエラーが出るようであれば、ローカルで以下を実行後に再度 git push する。

※ ローカルで dokku コマンドを使うには、dokku-cli 3 をインストールしておく必要がある。

dokku run rails db:create
dokku run rails db:migrate

Dokku のドキュメントだと、これで http://rails-sample-app.example.com に接続できるようになっているが、自分の場合は以下を実行してからでないと接続できなかった。(単に自分がドキュメントに記載された手順を間違えていたり、すっ飛ばしていただけかもしれない)

dokku domains:set rails-sample-app rails-sample-app.example.com

※ この後に再デプロイ (dokku ps:rebuild rails-sample-app) が必要だったかもしれない。

以上で、http://rails-sample-app.example.com に接続でき、Rails アプリケーションを動作するための最低限の対応が完了。

SSL

このままだと http 接続しかできないため、これも Dokku のドキュメントに従えば容易に SSL 化できる。

https://dokku.com/docs/deployment/application-deployment/#setting-up-ssl

dokku certs:add rails-sample-app server.crt server.key

sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git

dokku letsencrypt:set --global email your-email@your.domain.com

dokku domains:set rails-sample-app rails-sample-app.example.com

dokku letsencrypt:enable rails-sample-app

dokku letsencrypt:cron-job --add

これで、https://rails-sample-app.example.com に接続できるようになる。

Redis の設定

もし Sidekiq で非同期処理をして Redis を使っていたら、これも Dokku の公式プラグインを利用すれば容易に対応できる。

https://github.com/dokku/dokku-redis#installation

sudo dokku plugin:install https://github.com/dokku/dokku-redis.git redis

dokku redis:create rails-sample-app_redis

dokku redis:link rails-sample-app_redis rails-sample-app

# 再デプロイが必要かも
dokku ps:rebuild rails-sample-app

# Procfile を用意していると思うので、これもデプロイ後に必要(毎回やる必要はないはず)
dokku ps:scale rails-sample-app web=1 worker=1

Cron の設定

定期実行処理をしている場合もドキュメントに従えば容易に Cron を設定できる。

https://dokku.com/docs/processes/scheduled-cron-tasks

リポジトリのルートディレクトリに、以下のような内容で app.json を用意し、dokku に push するとあとは勝手に設定されている。

e.g.

{
  "cron": [
    {
      "command": "rails hoge_batch",
      "schedule": "@daily"
    }
  ]
}
dokku cron:list rails-sample-app
ID                                                                                                   Schedule     Command
[ハッシュ値]                      0 * * * *   rails hoge_batch

Chrome, ChromeDriver のインストール

自分が作成している個人サービスではクローリングもできるようにしているため、Chrome と ChromeDriver も欲しかった。

これについてはネット上の記事が少なく、どうしたら実現できるかわからなかったのだが、ドキュメントを読み込んでいたら herokuish-buildpacks というのが用意されており、Heroku でも使っていた Buildpack がそのまま使えることがわかった。(めちゃくちゃありがたい)

なので、ドキュメントのコマンド例を参考に、以下を実行すればインストールできた。

https://dokku.com/docs/deployment/builders/herokuish-buildpacks

Buildpack を追加する。

# Chrome
dokku buildpacks:add rails-sample-app https://github.com/heroku/heroku-buildpack-google-chrome.git

# ChromeDriver
dokku buildpacks:add rails-sample-app https://github.com/heroku/heroku-buildpack-chromedriver.git

# Ruby
dokku buildpacks:add rails-sample-app https://github.com/heroku/heroku-buildpack-ruby.git

Chrome と ChromeDriver 用の Buildpack を追加すると、ビルド時に Ruby のバージョンが古くなってしまい bundle install でエラーになる可能性があるため、最後に Ruby の Buildpack も追加する。

あとは、インストールした Chrome の同等バージョンを CHROMEDRIVER_VERSION に設定しておく。

dokku config:set CHROMEDRIVER_VERSION=[Chromeと同等のバージョン]

GitHub Actions で自動デプロイ

今後も修正したコードを Dokku 環境に適用したいときは、毎度 git push dokku main:master をしないといけないため、せっかくならと思い、GitHub Actions で自動デプロイも設定してみた。

とてもありがたいことに、こちらもドキュメントが用意されており、ほぼそのまま使えた。

https://dokku.com/docs/deployment/continuous-integration/github-actions

まず、GitHub の該当リポジトリの secrets に好きな名前 (今回はサンプルと同じく SSH_PRIVATE_KEY) で ConoHa の VPS に接続するときの鍵情報を登録する。

https://github.com/[your_user_name]/[your_repository_name]/settings/secrets/actions/new

あとは、該当リポジトリ.github/workflows/deploy-to-dokku.yml とかという名前で以下の内容のファイルを作成し、main ブランチにマージすると自動デプロイができるようになる。

---
name: 'deploy'

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Cloning repo
        uses: actions/checkout@v3
        with:
          fetch-depth: 0

      - name: Push to dokku
        uses: dokku/github-action@master
        with:
          git_remote_url: 'ssh://dokku@example.com:22/rails-sample-app'
          ssh_private_key: ${{ secrets.SSH_PRIVATE_KEY }}

所感

Dokku はとにかく便利だった。

日本語の関連記事が少なかったのと、Heroku と違って自分で VPS を用意して CLI で構築していかなければいけなかったので、そこらへんはいろいろと勉強になってよかった。