😇

Rails APIをfly.ioにデプロイする中で詰まったこと

2022/11/05に公開

はじめに

私は個人開発でRails APIをHerokuにデプロイしていました。Herokuの無料枠が外れるとのことで、新しく無料でRails APIをデプロイすることが出来るFly.ioを試してみました。

環境

windows
ruby 3.0.3
rails 7.0.3

前提

Rails APIをローカルで動かすことが出来る。

実際にやってみる

https://fly.io/
まずは、flyのコマンドをターミナルで使えるようにするために、flyctlをインストールします。

iwr https://fly.io/install.ps1 -useb | iex

flyの認証

flyにデプロイするプロジェクトの直下に行き、以下のコマンドで認証します

flyctl auth signup
flyctl auth login

flyctl launch

次にプロジェクトの直下で以下のコマンドを打ちます
windowsではflyではなく、flyctlコマンドを使うので注意して下さい

flyctl launch

以下のように聞かれますので、プロジェクト名を入力します
ここではrails-api-testというプロジェクトです

? App Name (leave blank to use an auto-generated name):rails-api-test

次にリージョンを選択します。
Tokyo Japanのままエンター

Postgresqlの設定をするならyでエンターを押します
私はPostgresqlを使用するのでyを押しました

お金をかけたくないならば、一番上を選択

launchが完了します

flyctl deploy

その1 改行コード問題

ここで私はflyctl deployコマンドを実行しましたが、次のエラーが出てしまいました

flyctl deploy

Update available 0.0.418 -> v0.0.429.
Run "flyctl.exe version update" to upgrade.
==> Verifying app config
--> Verified app config
==> Building image
Remote builder fly-builder-aged-hill-8650 ready
==> Creating build context
--> Creating build context done
==> Building image with Docker
--> docker host: 20.10.12 linux x86_64
[+] Building 0.0s (0/1)
[+] Building 3.5s (20/20) FINISHED
 => [internal] load remote build context             
 
 ~~~~~~~~~ 省略 ~~~~~~~~~~
 
 => CACHED [stage-3 5/7] COPY . .                                        0.0s 
 => CACHED [stage-3 6/7] RUN chmod +x /app/bin/* &&     sed -i 's/ruby.  0.0s
 => ERROR [stage-3 7/7] RUN bin/rails fly:build                          0.4s 
------
 > [stage-3 7/7] RUN bin/rails fly:build:
#20 0.377 /usr/bin/env: ‘ruby\r’: No such file or directory
------
Error failed to fetch an image or build from source: error building: executor failed running [/bin/bash -o pipefail -c ${BUILD_COMMAND}]: exit code: 127

このエラーはwindowsの改行コードがCRLFで発生するエラーなので、改行コードをLFに直します。

ここでは、bin/railsでエラーが出ているので、bin/railsファイルに行き、vscodeの下にあるCRLFをクリックし、LFに直して保存します。

CRLFをクリック

LFをクリック

bin/railsファイルの改行コードをがLFに直ったことを確認し、保存する

参考
https://qiita.com/nishikawa1031/items/38132298ef7c34a3b7b2

その2 assets:precompile問題

改行コードを直したので、再度flyctl deployを実行したのですが、また新しいエラーが出てしまいました

flyctl deploy
Update available 0.0.418 -> v0.0.429.\ruby\rails\tests\test-api>
Run "flyctl.exe version update" to upgrade.
==> Verifying app config
--> Verified app config
==> Building image

~~~~~~~~~~~ 省略 ~~~~~~~~~~~~

 => CACHED [stage-3 6/7] RUN chmod +x /app/bin/* &&     sed -i 's/ruby.  0.0s 
 => ERROR [stage-3 7/7] RUN bin/rails fly:build                          3.3s 
------
 > [stage-3 7/7] RUN bin/rails fly:build:
#20 3.247 rails aborted!
#20 3.247 Don't know how to build task 'assets:precompile' (See the list of available tasks with `rails --tasks`)
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task_manager.rb:59:in `[]'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:66:in `lookup_prerequisite'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:62:in `block in prerequisite_tasks'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:62:in `map'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:62:in `prerequisite_tasks'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:241:in `invoke_prerequisites'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:218:in `block in invoke_with_call_chain'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `synchronize'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:199:in `invoke_with_call_chain'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/task.rb:188:in `invoke'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:160:in `invoke_task'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `block (2 levels) in top_level'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `each'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:116:in `block in top_level'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:125:in `run_with_threads'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:110:in `top_level'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/railties-7.0.3.1/lib/rails/commands/rake/rake_command.rb:24:in `block (2 levels) in perform'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/application.rb:186:in `standard_exception_handling'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/railties-7.0.3.1/lib/rails/commands/rake/rake_command.rb:24:in `block in perform'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/rake-13.0.6/lib/rake/rake_module.rb:59:in `with_application'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/railties-7.0.3.1/lib/rails/commands/rake/rake_command.rb:18:in `perform'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.13.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
#20 3.247 /app/vendor/bundle/ruby/3.0.0/gems/bootsnap-1.13.0/lib/bootsnap/load_path_cache/core_ext/kernel_require.rb:32:in `require'
#20 3.247 Tasks: TOP => fly:build#20 3.247 (See full trace by running task with --trace)
------Error failed to fetch an image or build from source: error building: executor failed running [/bin/bash -o pipefail -c ${BUILD_COMMAND}]: exit code: 1

これは、flyのbuildにassets:precompileを使用しようとしているのですが、Rails APIではassetsが無いためエラーが出てしまいます。

そこで私は、assets:precompileの箇所をそれ以外のコードに書き換えました。
恐らく、何でも良いと思いますが、ここではdb:createに変えています。

lib/tasks/fly.rake
-  task :build => 'assets:precompile'
+   task :build => 'db:create'

その3 database問題

再度、flyctl deployをしますが、また新たにエラーが出てしまいました

 => [stage-3 5/7] COPY . .                                               0.0s
 => [stage-3 6/7] RUN chmod +x /app/bin/* &&     sed -i 's/ruby.exe/rub  0.3s 
 => ERROR [stage-3 7/7] RUN bin/rails fly:build                          3.0s 
------
flyctl deploy

~~~~~~~~~ 省略 ~~~~~~~~~~~

 > [stage-3 7/7] RUN bin/rails fly:build:
#20 2.946 We could not find your database: postgres. Which can be found in the database configuration file located at config/database.yml.
#20 2.946
#20 2.946 To resolve this issue:
#20 2.946
#20 2.946 - Did you create the database for this app, or delete it? You may need to create your database.
#20 2.946 - Has the database name changed? Check your database.yml config has the correct database name.
#20 2.946
#20 2.946 To create your database, run:
#20 2.946
#20 2.946         bin/rails db:create
#20 2.946 Couldn't create '' database. Please check your configuration.       
#20 2.946 rails aborted!
#20 2.946 ActiveRecord::NoDatabaseError: We could not find your database: postgres. Which can be found in the database configuration file located at config/database.yml.
#20 2.946
#20 2.946 To resolve this issue:
#20 2.946
#20 2.946 - Did you create the database for this app, or delete it? You may need to create your database.
#20 2.946 - Has the database name changed? Check your database.yml config has the correct database name.
#20 2.946
#20 2.946 To create your database, run:
#20 2.946
#20 2.946         bin/rails db:create

~~~~~~~~~ 省略 ~~~~~~~~~

以前、このプロジェクトはHerokuにデプロイしており、database.ymlと、Gemfileをpostgresqlの設定に変更していたので、初期状態に戻します

config/database.yml
default: &default
  adapter: sqlite3
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  timeout: 5000

development:
  <<: *default
  database: db/development.sqlite3
test:
  <<: *default
  database: db/test.sqlite3

- production:
-    <<: *default
-    adapter: postgresql
-    encoding: unicode
-    pool: 5

+  production:
+    <<: *default
+    database: db/production.sqlite3
Gemfile
-  group :development, :test do
-    gem 'sqlite3'
-  end
-  group :production do
-    gem 'pg'
-  end

+  gem "sqlite3"
+  gem "pg"

ですが、またエラーが出てしまいました。

その4 よくわからない問題

このエラーが全然分からなく、新しく一からRails api を作成して、この方法でデプロイすることが出来たのですが、なぜか既存のアプリは失敗してしまいました。

そこで、試しにGitHubからプロジェクトをgit cloneして同じ状態にしてみました

git clone 自分のリポジトリ
cd 自分のリポジトリ
code .

問題である、その1~3を直した後で、

bundle install
rails db:create
rails db:migrate

これで、再度flyctl deployを実行すると、ついにデプロイすることが出来ました

          -- change_column(:users, :email, :string, {:null=>false, :unique=>true})
            -> 0.0017s
         == 20220810054326 AddPasswordToUsers: migrated (0.0171s) ======================
         Starting clean up.
Running release task (running)... 🌍 ==> Monitoring deployment
Running release task (running)... 🌍 
                                      1 desired, 1 placed, 0 healthy, 0 unheal
                                      1 desired, 1 placed, 0 healthy, 0 unheal
                                      1 desired, 1 placed, 0 healthy, 0 unheal
                                      1 desired, 1 placed, 1 healthy, 0 unheal
                                      1 desired, 1 placed, 1 healthy, 0 unhealthy [health checks: 1 total, 1 passing]
--> v0 deployed successfully

デプロイされたサイトの確認

以下のページに行き、実際にデプロイされたかを確認します
https://fly.io/dashboard/personal

画面下に行くと、デプロイされたプロジェクトがあるのでクリックします。ここではrails-api-test

Hostnameにある所を押せば、デプロイされたURLにアクセス出来ます

おまけ GitHub Actionsでfly.ioのCD

GitHubのmasterブランチにマージされた時に、自動でfly.ioにデプロイ出来るように設定します。

https://fly.io/docs/app-guides/continuous-deployment-with-github-actions/

https://www.youtube.com/watch?v=6u9BrDaSHJc

ここで紹介されている、.github/workflows/fly.ymlファイルをそのまま使うと、私は上手く出来なかったので以下のように修正しました。

.github/workflow/fly.yml
on:
  push:
    branches:
      - master
env:
  FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }}

jobs:
  deploy:
    name: Deploy app
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - uses: superfly/flyctl-actions/setup-flyctl@master

      - run: flyctl deploy --remote-only

終わり

今回はfly.ioにRails APIをデプロイする上で、詰まったことについてまとめました。

私自身、Railsの経験が薄いので、おかしいことをしているかもしれませんが、ご了承ください

かなり、デプロイするのに苦労しましたが、この記事をみてRails APIのデプロイに成功する人がいれば嬉しいです。

ここまででデプロイが出来なかった方は、こちらの方法を試してみると良いと思います
https://zenn.dev/ako/articles/6b5477a9ffe518

最後まで読んで下さり、ありがとうございました。

Discussion