Docker(Docker compose)でRails6.1 + Webpacker + MySQL構成の環境構築をする
株式会社TECH LUCKという会社で代表兼エンジニアをしている齊藤です。
本記事は表題の通り、Docker(Docker compose)でRails6.1 + Webpacker + MySQL構成の環境構築をしてみます。
Railsプロジェクトの作成
まずはRails6.1でDatabaseオプションでMySQLを指定して、新規アプリケーションの作成します。
rails _6.1.4_ new rails_app -d mysql
# rails newの際にbundle installなどでエラーが起こった場合に必要です
rails webpacker:install
Dockerファイルの作成
次にアプリケーション直下に、以下の内容で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
を作成します。
#!/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
を作成します。
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がインストールされていないというエラーが発生します。そのエラーを回避するために、webpacker
とrails
の両方のサービスで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
で指定した値に変更します。変更する箇所はpassword
とhost
となります。host
に関してはdocker-compose.yml
のserviceで指定したdb
を指定し、passwordはdocker-compose.yml
でMYSQL_ALLOW_EMPTY_PASSWORD: 'yes'
としているためパスワード不要で接続することができます。
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でコンテナの作成〜起動
これまでの設定が終わったらコンテナの作成と起動を行います。
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でアプリケーションを作成する上で必要なコマンドに関しては以下のようになります。
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
を仕込んでも動作は止まりますが、ターミナルなどでは止まらずデバッグすることができません。デバッグをするにはアタッチが必要です。
docker attach <コンテナID or コンテナ名>
このようにすると、そのタブでbinding.pry
が止まりデバッグすることができるようになります。
特定のコンテナの再起動
例えば、Rails自体の設定を変更した時には、以下のコマンドで特定のコンテナだけ再起動することができる。
docker-compose up
などをやり直さなくてもよい。
docker-compose restart rails
作ったコンテナ、イメージ、ボリュームなどの一括削除
docker-compose down --rmi all --volumes --remove-orphans
bundle installがされないエラー
キャッシュの影響でbundle install
が実行されない場合があるとのこと。
この際に、railsのdockerコンテナはストップしてしまっている。
docker-compose exec の場合は、コンテナが起動しているところにログインしてコマンドを実行するということになるので、ストップしてしまっている場合には実行することができない。
そのため、docker-compose runでコンテナを起動させて、budle installしてあげるとうまくいく。
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
原因などは以下の記事を見るとすごい詳細に記述されている。
参考記事
Discussion