🌊

Docker(Docker compose)でRails6.1 + Webpacker + MySQL構成の環境構築をする

2021/10/12に公開

株式会社TECH LUCKという会社で代表兼エンジニアをしている齊藤です。

DXプロジェクト、開発プロジェクト、Rails開発などでお困りごとがありましたら弊社HPからご相談をいただけますと幸いです。
以下のような問題に対応することが可能です。

  • プロジェクトでRailsエンジニアが足りなくて困っている
  • Railsのバージョンアップをしたいがノウハウ・リソースが足りなくて困っている
  • オフショア開発をしているが、要件の齟齬やコード品質が悪いので改善したい

また、Railsエンジニアも募集しておりますので、興味がありましたら弊社HPからご連絡いただけますと幸いです。

前提

本記事は表題の通り、Docker(Docker compose)でRails6.1 + Webpacker + MySQL構成の環境構築をしてみます。

Railsプロジェクトの作成

まずはRails6.1でDatabaseオプションでMySQLを指定して、新規アプリケーションの作成します。

bash
rails _6.1.4_ new rails_app -d mysql

# rails newの際にbundle installなどでエラーが起こった場合に必要です
rails webpacker:install

Dockerファイルの作成

次にアプリケーション直下に、以下の内容でDockerfileを作成します。

Dockerfile
FROM ruby:3.0.2
RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - && apt-get install -y nodejs
RUN npm install --global yarn

WORKDIR /myapp
COPY Gemfile /myapp/Gemfile
COPY Gemfile.lock /myapp/Gemfile.lock
RUN bundle install
COPY . /myapp

# Add a script to be executed every time the container starts.
COPY entrypoint.sh /usr/bin/
RUN chmod +x /usr/bin/entrypoint.sh
ENTRYPOINT ["entrypoint.sh"]
EXPOSE 3000

# Start the main process.
CMD ["rails", "server", "-b", "0.0.0.0"]

entrypoint.shの作成

次にアプリケーション直下にentrypoint.shを作成します。

entrypoint.sh
#!/bin/bash
set -e

# Remove a potentially pre-existing server.pid for Rails.
rm -f /myapp/tmp/pids/server.pid

# Then exec the container's main process (what's set as CMD in the Dockerfile).
exec "$@"

docker-compose.yml

次にアプリケーション直下にdocker-compose.ymlを作成します。

docker-compose.yml
version: '3.7'
services:
  db:
    image: mysql:8.0
    platform: linux/x86_64
    command: --default-authentication-plugin=mysql_native_password
    ports:
      - "4306:3306"
    volumes:
      - db:/var/lib/mysql
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
    security_opt:
      - seccomp:unconfined
  webpacker:
    build: .
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
    command: ./bin/webpack-dev-server
    environment:
      WEBPACKER_DEV_SERVER_HOST: 0.0.0.0
    ports:
      - "3035:3035"
  rails:
    build: .
    stdin_open: true
    tty: true
    volumes:
      - .:/myapp
      - bundle:/usr/local/bundle
    command: bash -c "rm -rf tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    depends_on:
      - db
    ports:
      - "3000:3000"
    environment:
      WEBPACKER_DEV_SERVER_HOST: webpacker
volumes:
  db:
    driver: local
  bundle:
    driver: local

volumesについて

volumesを共有する設定にしないと、Railsが起動しているコンテナで新しいgemをインストールした際に、Webpackerのコンテナでgemがインストールされていないというエラーが発生します。そのエラーを回避するために、webpackerrailsの両方のサービスでvolumesを指定して共有する設定にしています。

WEBPACKER_DEV_SERVER_HOSTについて

Railsがwebpackのサーバーに接続する際には、config/webpacker.ymlに記載されているhostとportを元に接続する。これを上書きするために、WEBPACKER_DEV_SERVER_*という環境変数を設定することでconfig/webpacker.ymlファイルの設定を上書きできるようにいる。それを利用して、docker-compose.yml内で環境変数WEBPACKER_DEV_SERVER_HOSTを指定し、webpack-dev-serverが起動しているコンテナに接続することができるようになる。

database.ymlの変更

DockerのMySQLに接続するため、databse.ymlの中身をdocker-compose.ymlで指定した値に変更します。変更する箇所はpasswordhostとなります。hostに関してはdocker-compose.ymlのserviceで指定したdbを指定し、passwordはdocker-compose.ymlMYSQL_ALLOW_EMPTY_PASSWORD: 'yes'としているためパスワード不要で接続することができます。

database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  host: db
  password:

development:
  <<: *default
  database: <データベース名>_development

test:
  <<: *default
  database: <データベース名>_test

docekr-composeでコンテナの作成〜起動

これまでの設定が終わったらコンテナの作成と起動を行います。

bash
docker-compose up

# バックグラウンドでDockerコンテナを起動したいは以下のコマンドで実行します。
docker-compose up -d

# バックグラウンドでDocekrコンテナを起動した場合は以下のコマンドでログの出力をします。
docker-compose logs -f web

上記でDocker環境でRailsを動かすことができます。
ただ、Dockerコンテナを起動しても、データベースが作成されていないため、以下のコマンドを実行してlocalhost:3000で画面を表示できるようにしましょう。

docker-compose exec rails rails db:create
docker-compose exec rails rails db:migrate

開発中のDockerに関する知識

Docker ComposeでRails関連のコマンド

Railsでアプリケーションを作成する上で必要なコマンドに関しては以下のようになります。

bash
docker-compose exec rails <実行したいコマンド>

# bundle install
docker-compose exec rails bundle install

# DB作成
docker-compose exec rails rails db:create

# マイグレーション実行
docker-compose exec rails rails db:migrate

# データの投入
docker-compose exec rails rails db:seed

pry-railsでのデバッグ方法

Dockerでアプリケーションを起動している場合、binding.pryを仕込んでも動作は止まりますが、ターミナルなどでは止まらずデバッグすることができません。デバッグをするにはアタッチが必要です。

bash
docker attach <コンテナID or コンテナ名>

このようにすると、そのタブでbinding.pryが止まりデバッグすることができるようになります。

特定のコンテナの再起動

例えば、Rails自体の設定を変更した時には、以下のコマンドで特定のコンテナだけ再起動することができる。
docker-compose up などをやり直さなくてもよい。

bash
docker-compose restart rails

作ったコンテナ、イメージ、ボリュームなどの一括削除

bash
docker-compose down --rmi all --volumes --remove-orphans

bundle installがされないエラー

キャッシュの影響でbundle installが実行されない場合があるとのこと。
この際に、railsのdockerコンテナはストップしてしまっている。
docker-compose exec の場合は、コンテナが起動しているところにログインしてコマンドを実行するということになるので、ストップしてしまっている場合には実行することができない。
そのため、docker-compose runでコンテナを起動させて、budle installしてあげるとうまくいく。

bash
docker-compose run --rm rails bundle install

その他

DockerfileのCMDとdocker-compose.ymlのcommandについて

docker-compose.ymlに実行コマンドを記載した場合、Dockerfileに記載されているCMDは無視される。

M1 Macの場合にnokogiri関連でエラーが出てくる場合の設定

RUN bundle installの前に、以下の1文を設定する。

RUN bundle config force_ruby_platform true
RUN bundle install

原因などは以下の記事を見るとすごい詳細に記述されている。
https://note.com/teslur/n/nea473755b5a5

参考記事

https://qiita.com/kobori_akira/items/1cd058f180206fd8d139

https://qiita.com/suin/items/19d65e191b96a0079417

https://fuqda.hatenablog.com/entry/2019/03/21/204118

https://qiita.com/suin/items/19d65e191b96a0079417

https://blog.naoty.dev/334/

https://qiita.com/soicchi/items/0bf3f97aaee245fa252b

https://note.com/teslur/n/nea473755b5a5

Discussion