LoginSignup
5
4

Docker, Rails7.1.3.2の環境構築が上手くいかなかった記録

Last updated at Posted at 2024-04-11

初めに

初学者です。
webアプリを個人で開発するために、dockerを使用してruby on railsでの開発環境構築を実施した際の記録を共有します。
公開日時点での最新安定版を使用しています。

本記事ではdockerを使いherokuへのデプロイをgithub actionsで自動化するところまで行いますが、最終的にエラーで行き詰まり、別記事にて再度環境構築をやり直します。

成功した手順のみを参考にしたい方は、こちらの記事を読んでください。
https://qiita.com/tkhero555/items/a1811369c59021077d62

構築したい技術構成

カテゴリ 技術
フロントエンド javascript/Hotwire/bootstrap 
バックエンド ruby3.3.0/rails7.1.3.2
データベース PostgreSQL16.2
認証 devise
環境構築 Docker / docker-compose
CI/CD Github Actions
インフラ   heroku

docker関係のファイルを作成~rails newまで

作業するディレクトリを作成した後、docker関係のファイルを作成します。

  • compose.yml
  • Dockerfile
  • Gemfile
  • Gemfile.lock

各ファイルの構成

compose.yaml
services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

Dockerfile

FROM ruby:3.3.0

# データベース用にPostgreSQLをインストール
RUN apt-get update -qq && apt-get install -y postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
COPY . /myapp

# Rails サーバ起動
CMD ["rails", "server", "-b", "0.0.0.0"]

Gemfile

source 'https://rubygems.org'
gem 'rails', '~> 7.1', '>= 7.1.3.2'

イメージをbuildする

docker compose build

rails newを実行する。

$ docker compose run --rm web rails new . --force --no-deps --database=postgresql

上手くいかずログを確認すると、

! db The requested image's platform (linux/amd64) does not match the detected host platform (linux/arm64/v8) and no specific platform was requested 0.0s 
Error response from daemon: failed to create task for container: failed to create shim task: OCI runtime create failed: runc create failed: unable to start container process: exec: "rails": executable file not found in $PATH: unknown

dockerが実行しようとするプラットフォームと、ホストのプラットフォームが違うよ〜というエラーと、railsが$path内に見つからないよとのエラーが出ている。

Dockerfileにbundle installを追記

FROM ruby:3.3.0

RUN apt-get update -qq && apt-get install -y postgresql-client
RUN mkdir /myapp
WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp/

CMD ["rails", "server", "-b", "0.0.0.0"]

コマンドにプラットフォームオプションを追加して再実行

docker compose run --platform linux/amd64 --rm web rails new . --force --no-deps --database=postgresql

下記の表示が返ってきて上手くいかない

unknown flag: --platform

compose.yamlにplatformの指定を追記する

services:
  db:
    image: postgres
    volumes:
      - ./tmp/db:/var/lib/postgresql/data
    platform: linux/amd64
    environment:
      POSTGRES_PASSWORD: password
  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0"
    volumes:
      - .:/myapp
    ports:
      - "3000:3000"
    depends_on:
      - db

再度rails newを実行

docker compose run web rails new . --force --no-deps --database=postgresql

rails関係のファイルが作成されたことが確認できた。

データベースの作成をしようとしたらエラー発生

rails newで作成されたファイルの中から、データベースのymlファイルを編集する。

config/database.yml
default: &default
  adapter: postgresql
  encoding: unicode
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  host: db
  username: postgres
  password: password

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

データベースを作成する

docker compose run web rails db:create

エラーが発生したので、実行ログを見てみる。

Could not find sprockets-rails-3.4.2, pg-1.5.6, puma-6.4.2, importmap-rails-2.0.1, turbo-rails-2.0.5, stimulus-rails-1.3.3, jbuilder-2.11.5, bootsnap-1.18.3, debug-1.9.2, web-console-4.2.1, capybara-3.40.0, selenium-webdriver-4.19.0, sprockets-4.2.1, msgpack-1.7.2, bindex-0.8.1, addressable-2.8.6, regexp_parser-2.9.0, xpath-3.2.0, rubyzip-2.3.2, websocket-1.2.10, public_suffix-5.0.4 in locally installed gems
Run `bundle install --gemfile /myapp/Gemfile` to install missing gems.

必要なgemが存在しないとのこと。
先ほどrails newをした際にgemfileに追記されたgemがinstallされていないのが原因とか?
bundle installしてみる

docker compose run web bundle install

再度データベースを作成してみるが、同じエラーが継続

Gemfileの変更内容がdockerイメージに反映されておらず、ローカルとコンテナのファイルに差異があるとか?
buildして、再度データベースを作成してみる。
実行結果

$ docker compose run web rails db:create
[+] Creating 1/0
 ✔ Container runteq_graduation_exam-db-1  R...                                         0.0s 
/rails/bin/docker-entrypoint: line 8: exec: rails: not found

ダメそう。

また、docker compose upしてみるとエラーが発生している。

/usr/local/bundle/ruby/3.3.0/gems/railties-7.1.3.2/lib/rails/application.rb:658:in `validate_secret_key_base': Missing `secret_key_base` for 'production' environment, set this string with `bin/rails credentials:edit` (ArgumentError)
web-1  | 
web-1  |         raise ArgumentError, "Missing `secret_key_base` for '#{Rails.env}' environment, set this string with `bin/rails credentials:edit`"

本番環境で使うsecret_key_baseが不足している?
この時点では開発環境の設定で環境を用意したつもりなのだけど、どういうことだ?

調べるとDockerfileの記述がいつの間にか変わっており、railsの環境がproduction設定になっていた。

# Set production environment
ENV RAILS_ENV="production" \
    BUNDLE_DEPLOYMENT="1" \
    BUNDLE_PATH="/usr/local/bundle" \
    BUNDLE_WITHOUT="development"

どうやらrails7.1の機能で、rails newの際に自動的に本番環境用のDockerfileを生成するようになっているらしい。
この機能で用意していたDockerfileが上書きされておかしくなったようだ。

development指定に変更して、BUNDLE_WITHOUTを削除してみる。
buildしてupしたところ、無事にコンテナが起動した。
再度データベース作成したらエラー

$ docker compose exec web rails db:create
OCI runtime exec failed: exec failed: unable to start container process: 
exec: "rails": executable file not found in $PATH: unknown

railsコマンドの前にbundle execをつけてみる。

$ docker compose exec web bundle exec rails db:create
Created database 'myapp_development'
Created database 'myapp_test'

行けたっぽい。

localhost::3000にブラウザでアクセスして、Railsアプリのページが表示されていることを確認できた!

herokuへのデプロイ設定

参考記事に従って、docker関連ファイルに変更を加える。
※後から気づいたが、herokuCLIを利用してデプロイする場合、ここでの本番環境に関する設定変更は不要だった。

Dockerfile
ENV設定をproductionに変更

# Set production environment
ENV RAILS_ENV="production" \
    BUNDLE_DEPLOYMENT="1" \
    BUNDLE_PATH="/usr/local/bundle"

いつの間にか追記されていた下2行は一旦コメントアウト

database.yml
production:
  <<: *default
  database: myapp_production
  # username: myapp
  # password: <%= ENV["MYAPP_DATABASE_PASSWORD"] %>
config/enviroments/production.rb
# Do not fallback to assets pipeline if a precompiled asset is missed.
config.assets.compile = true # false
# Disable serving static files from the `/public` folder by default since
# Apache or NGINX already handles this.
config.public_file_server.enabled = true # ENV["RAILS_SERVE_STATIC_FILES"].present?

herokuに会員登録して、月額費用を支払う設定を完了しておく。

Heroku CLIをインストールする。
macなのでhomebrew

brew tap heroku/brew && brew install heroku

heroku loginコマンドでアカウントログインを完了する。

作業中のアプリのディレクトリで、herokuのアプリケーションを作成する。

heroku create -a アプリ名

デプロイする。

git push heroku main

デプロイしたアプリにアクセスする。

heroku open

github actionsでデプロイを自動化

herokuのAPIキーをサイトから取得する。

githubにアクセスし、リポジトリのメニューからsettingsタブ、secrets and variablesのactionsでnew repository secretをクリック
2つのsecretを作成する。

  • HEROKU_API_KEY: herokuのAPIキーを内容に入れておく
  • HEROKU_APP_NAME:デプロイ先のherokuアプリ名を入れておく

ローカルの作業ディレクトリで.github/workflowsディレクトリを作成し、その中でdeploy.ymlファイルを作成する。

.github/workflows/deploy.yml
name: Deploy to Heroku
on:
  push:
    branches:
      - main

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Login to Heroku
        uses: akhileshns/heroku-deploy@v3.12.12 # This is the action
        with:
          heroku_api_key: ${{ secrets.HEROKU_API_KEY }}
          heroku_app_name: ${{ secrets.HEROKU_APP_NAME }}
          heroku_email: "nmt.1727@gmail.com"

作成したワークフローファイルをリモートリポジトリにプッシュすれば設定完了

mainブランチに変更を加えた際に自動でherokuへのデプロイを実行する設定にしている。
githubのリポジトリに行ってactionsタブから動作を確認できる。

controllerを作成しようとした際にエラー発生

コントローラーを作成しようとしたところ、エラー発生

/usr/local/bundle/ruby/3.3.0/gems/thor-1.3.1/lib/thor/actions/
create_file.rb:64:in `initialize': Permission denied @ rb_sysopen - 
/rails/app/controllers/line_bot_controller.rb (Errno::EACCES)

コントローラーを作成しようとした時に、書き込み権限が無いエラー

ディレクトリの所有者をls -laで確認してみる。

$ cd app/controllers/
mynameMacBook-Air:controllers myname$ ls -la
total 8
drwxr-xr-x   4 myname  staff  128  4  1 14:13 .
drwxr-xr-x  11 myname  staff  352  4  1 14:13 ..
-rw-r--r--   1 myname  staff   57  4  1 14:13 application_controller.rb
drwxr-xr-x   3 myname  staff   96  4  1 14:13 concerns

dockerのコンテナの中に入ってから、ls -laで確認してみる。

rails@f1bf5a5f353c:/rails$ cd app/
rails@f1bf5a5f353c:/rails/app$ cd controllers/
rails@f1bf5a5f353c:/rails/app/controllers$ ls -la
total 16
drwxr-xr-x  3 root root 4096 Mar 31 09:18 .
drwxr-xr-x 11 root root 4096 Mar 31 09:18 ..
-rw-r--r--  1 root root   57 Mar 31 09:18 application_controller.rb
drwxr-xr-x  2 root root 4096 Mar 31 09:18 concerns

rootが所有者になっている。

rails@f1bf5a5f353c:/rails/app/controllers$ whoami
rails

コンテナ内での作業者はrailsになっている。
rootが所有しているディレクトリでrailsが作業しようとして、権限が無いというのが現状?

DockerfileにUSER rails:railsという記述があり、これによって作業者がrailsになっているんだと思う。
この記述はRails7で自動的に追加されるもので、セキュリティ的にいい効果があるようだが、動くこと優先で削除してみる。

docker compose build
docker compose up

コンテナ起動中にエラー発生

/usr/local/bundle/ruby/3.3.0/gems/railties-7.1.3.2/lib/rails/application.rb:658:in `validate_secret_key_base': Missing `secret_key_base` for 'production' environment, set this string with `bin/rails credentials:edit` (ArgumentError)
web-1  | 
web-1  |         raise ArgumentError, "Missing `secret_key_base` for '#{Rails.env}' environment, set this string with `bin/rails credentials:edit`"

herokuへのデプロイ設定の時に変更していた本番環境の指定が原因なので、変更前に戻す。
Dockerfile

# Set production environment
ENV RAILS_ENV="development" \
    BUNDLE_DEPLOYMENT="1" \
    BUNDLE_PATH="/usr/local/bundle"
config/enviroments/production.rb
 # Disable serving static files from `public/`, relying on NGINX/Apache to do so instead.
    #config.public_file_server.enabled = true
    
# Do not fall back to assets pipeline if a precompiled asset is missed.
    config.assets.compile = false

buildしてupすると無事にコンテナが起動した。

コンテナ内の所有者と作業者を再確認

root@b961a7cb106f:/rails/app# cd controllers/
root@b961a7cb106f:/rails/app/controllers# ls -la
total 16
drwxr-xr-x  3 root root 4096 Apr  3 04:26 .
drwxr-xr-x 11 root root 4096 Mar 31 09:18 ..
-rw-r--r--  1 root root   57 Apr  1 05:13 application_controller.rb
drwxr-xr-x  2 root root 4096 Apr  2 11:46 concerns
root@b961a7cb106f:/rails/app/controllers# whoami
root

ディレクトリの所有者と作業者、両方ともrootになっている。

gemfileにgemを追加してbundle installをしようとすると、gemが追加されない。
どういうことだろうか?
gemfileに追記した状態でbuildしなおしてみるとエラー

=> ERROR [web build 3/6] RUN bundle install &&     rm -rf ~/.bundle/ "/usr/  0.3s
------
 > [web build 3/6] RUN bundle install &&     rm -rf ~/.bundle/ "/usr/local/bundle"/ruby/*/cache "/usr/local/bundle"/ruby/*/bundler/gems/*/.git &&     bundle exec bootsnap precompile --gemfile:
0.264 The dependencies in your gemfile changed, but the lockfile can't be updated
0.264 because frozen mode is set
0.264 
0.264 You have added to the Gemfile:
0.264 * line-bot-api
0.264 
0.264 Run `bundle install` elsewhere and add the updated Gemfile to version control.
0.264 If this is a development machine, remove the Gemfile.lock freeze by running
0.264 `bundle config set frozen false`.
------
failed to solve: process "/bin/sh -c bundle install &&     rm -rf ~/.bundle/ \"${BUNDLE_PATH}\"/ruby/*/cache \"${BUNDLE_PATH}\"/ruby/*/bundler/gems/*/.git &&     bundle exec bootsnap precompile --gemfile" did not complete successfully: exit code: 16

frozenモードを削除しようとしてみる。

bundle config set frozen false

効果なし。

解決を諦める

参考にした記事と使用するrailsのバージョンが違ったことで、Rails7.1で自動生成されるDockerfileとのぶつかり合いが起こり、そこからよく分からなくなった。
今の状況からどこを修正すれば解決できるか、悩んでも思いつかなかった為、別ディレクトリで新しく環境を作り直そうと思います。

参考記事・サイト

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4