5
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Rails6】Docker + Rails + MariaDB のローカル環境でアプリ開発を始めよう【おとなもこどもも、おねーさんも】

Last updated at Posted at 2021-02-02

はじめに

転職に向けたポートフォリオ作成にあたって、ローカルマシンにDockerの開発環境を構築した際の手順を記事にしました。
今回はローカル環境(development)についての内容ですが、本番環境(production)へのデプロイ方法も別の記事で投稿する予定です。

なお、先に申し上げておくのですが、私の環境ですと当記事の内容だけでは以下の問題にぶつかりました。

  • CSSファイルを編集するたびにページの表示がめちゃくちゃ遅い(webpackerを別コンテナで実行することで解決)
  • システムスペックが実行できない(chromeを別コンテナで実行することで解決)

最終的に、Rails6 + MariaDB + webpacker + chrome という4つコンテナを実行する開発環境となりました。

対策はこちら
【Rails6】Docker環境でWebpackerのコンパイルが遅い【対策】
【Rails6】Docker環境でRSpecのシステムスペックを実行する

開発環境

  • MacOS Catalina 10.15.7
  • docker 19.03.13
  • docker-compose 1.27.4
  • Ruby 2.7.1
  • Rails 6.0.3.4
  • MariaDB 10.4

作業ディレクトリの作成

最初に、アプリを新規作成するディレクトリを準備します。当記事ではアプリの名前を「sample_app」として進めていきます。構築される環境にあわせて適宜読み替えてください。

mkdir sample_app
cd sample_app

Dockerファイルの作成

Dockerfile
FROM ruby:2.7.1

RUN set -ex && \
    apt-get update -qq && \
    apt-get install -y && \
    curl -sL https://deb.nodesource.com/setup_14.x | bash - && \
    apt-get update -qq && \
    apt-get install -y nodejs && \
    curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
    echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
    apt-get update -qq && \
    apt-get install -y yarn

ENV APP_ROOT /sample_app
RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT

COPY Gemfile $APP_ROOT
COPY Gemfile.lock $APP_ROOT

RUN bundle install

COPY . $APP_ROOT

# 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"]

解説

FROM

Rubyイメージのバージョンを指定しています。

RUN set -ex ~

ここではまっさらなRubyイメージに、アプリ開発に必要なものをインストールしています。
冒頭のset -exは、ビルド状況を画面に出力するためのオプションです。

ENV ~ WORKDIR

  • ENV アプリケーションのルートディレクトリの定義をしています。
  • RUN イメージ内にディレクトリを作成しています。
  • WORKDIR 作業ディレクトリの定義をしています。(ここでは/sample_appになります)

別のアプリを作成する際、Dockerファイルを使いまわせるように、ENV APP_ROOT /sample_appのパスを書き換えるだけでいいようにしてあります。(これ以降の行の$APP_ROOT/sample_appに置き換わります。)

COPY

ローカル(PC)の作業ディレクトリにあるGemfileGemfile.lockをイメージ内にコピーしています。(Gemfileは別途作成します)

RUN bundle install

Railsでアプリ開発を行ったことがある方にはお馴染みのやつです。コピーしたGemfileを元に実行されます。

COPY . $APP_ROOT

ローカル(PC)のカレントディレクトリ(今いる場所、sample_appディレクトリを想定)にあるファイルを、イメージ内にコピーしています。

COPY ~ ENTRYPOINT

  • COPY ローカルのentrypoint.shをイメージ内にコピーしています。(entrypoint.shは別途作成します)
  • RUN イメージ内のentrypoint.shに実行する権限(+x)を与えています。
  • ENTRYPOINT コンテナ実行時に必ず実行されるコマンドの指定です。

EXPOSE

外部に公開するポートの指定です。Railsのアプリはポート番号3000でアクセス出来ますね!

CMD

Rails Server を実行して、サーバを起動しています。
"-b", "0.0.0.0"の部分ですが、Rails Server は実はデフォルトでは自分自身(localhost)しかアクセス出来ません。そこでこのオプションを付けることで、別のPCからもアクセスが可能になります。0.0.0.0は「すべて」みたいな意味があります。

Gemfileの作成

Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 6.0.3', '>= 6.0.3.4'

Gemfile.lock の作成

touch Gemfile.lock

touchコマンドは空のファイルを作成出来るコマンドです。(他にもファイルのタイムスタンプを更新するみたいな使い方も)

entrypoint.sh の作成

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

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

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

Railsサーバが起動されると、server.pidが自動生成され、停止時に自動削除されます。しかし、Railsサーバが異常終了などによって、server.pidが削除されなかった場合、このファイルがある状態ではサーバを起動出来ないので削除しています。

docker-compose.yml の作成

docker-composeは複数のコンテナを一度に起動したり停止したり出ます。ここでは、RubyとMariaDBのコンテナを起動する設定を行います。

docker-compose.yml
version: '3'
services:
  db:
    image: mariadb:10.4
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - '3306:3306'
    command: --default-authentication-plugin=mysql_native_password
    volumes:
      - mysql-data:/var/lib/mysql
  app:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
    volumes:
      - .:/sample_app
    ports:
      - "3000:3000"
    depends_on:
      - db
    stdin_open: true
    tty: true
    command: bundle exec rails server -b 0.0.0.0
volumes:
  mysql-data:

解説

db:で始まるセクションが MariaDB、app:で始まるセクションが Rubyについての記述です。

docker-compose.ymlについては素晴らしい記事があります!
docker-compose.ymlの書き方について解説してみた

Gemの永続化(任意)

はじめは上記のdocker-compose.ymlで開発を進めていたのですが、新たにGemをインストールしたのに有効にならない状態に悩まされました。調べるとGemを新たにインストールした場合、再度イメージのビルド(後ほど実行します)が必要とのこと。それはめんどくさいなーと思ってさらに調べていくと解決方法がありました!

結論だけ言いますが、Gemのインストールをガンガンやりたい人は、下記①②を追記してGemの永続化をオススメします!(①②は書かないでくださいね。笑)

docker-compose.yml
app:
〜中略〜
  volumes:
    - .:/sample_app
    - gem-data:/usr/local/bundle ①
〜中略〜
volumes:
  mysql-data:
  gem-data: ②

参考にさせていただいた記事(詳しくはこちら)
【Docker】Rails開発で知っておきたい!gemの永続化による作業効率アップの話

Dockerイメージ作成

docker-compose run app rails new . --force --no-deps --database=mysql --skip-test --webpacker
項目 解説
docker-compose run app Rubyのイメージを実行します
rails new . 新規アプリケーションを作成します。現在のディレクトリ(作業ディレクトリ)にファイルが作成されます。
--force ファイルを上書きします
--no-deps リンクした他のサービスを起動しないようにします
--database=mysql DBにMySQLを指定します
--skip-test RailsのデフォルトテストツールMinitestを生成しないようにします
--webpacker Webpackerに対応したアプリケーションを生成します

イメージのビルド

docker-compose build

ビルドってなんぞやって方はこちら
docker-compose up とか build とか start とかの違いを理解できていなかったのでまとめてみた

データベースの設定

database.yml
database.yml

default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: <%= ENV.fetch("MYSQL_USERNAME", "root") %>
  password: <%= ENV.fetch("MYSQL_PASSWORD", "password") %>
  host: <%= ENV.fetch("MYSQL_HOST", "db") %>

development:
  <<: *default
  database: sample_app_development

test:
  <<: *default
  database: sample_app_test

production:
  <<: *default
  database: sample_app_production

production環境をRDSとかで考えている方はこの時点で設定しちゃってもよいです。(接続情報はcredentialsで隠蔽してくださいね!)

テーブル作成とマイグレーション

docker-compose run app rails db:create
docker-compose run app rails db:migrate

後ろの方見たことあるやつ。

コンテナの起動

docker-compose up -d

-dはバックグラウンドで実行するオプションです。
このオプションがない場合、ざっくり言うとターミナルが操作不可になるので、つけることをオススメします。

アクセス

Yay!

Docker環境でコマンドを実行する場合

たとえば railsのコンソールを開きたい場合は下記のように実行します。

docker-compose run app rails c

appの部分はdocker-compose.ymlに記述したapp:という部分に対応しています。
docker-compose run appという詠唱によってrubyのコンテナを指定しているわけですね。
この名前は任意なので、docker-compose.ymlruby:と書いて、docker-compose run rubyにすることもできます。

その他参考にさせていただいたサイト・記事

ありがとうございます!

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?