DockerでRails+MySQLの環境構築

環境

Mac 13.1(22C65)
Docker 20.10.23
Docker Compose v2.15.1
Ruby 2.7.0
Rails 5.2.8.1
MySQL 5.7

Rails+MySQLの環境構築を行う

DockerでRailsMySQLの環境構築を行う。

Railsを動かすwebコンテナとMySQLを動かすdbコンテナを作る。 webコンテナのイメージはDockerfileを使ってビルドし、dbコンテナのイメージはDocker Hubのmysqlのイメージをそのまま使う。 コンテナはDocker Composeでまとめて操作する。


手順は以下の通り。

  1. 必要なファイルを作る
  2. Railsのプロジェクトを作成する
  3. イメージをビルドする
  4. データベースの接続設定を行う
  5. Docker Composeでコンテナを起動する
  6. データベースを作成する
  7. Webサーバーにアクセスして、Railsのページを確認する

1. 必要なファイルを作る

Rails+MySQL環境を構築するために必要なファイルを作る。

作るファイルは以下の4つ。

  • Dockerfile
  • docker-compose.yml
  • Gemfile
  • Gemfile.lock

Dockerfile

webコンテナのイメージを作るためにDockerfileを作成する。

FROM ruby:2.7.0

RUN apt-get update -qq && apt-get install -y build-essential nodejs default-mysql-client

RUN mkdir /src

WORKDIR /src

COPY Gemfile /src/Gemfile
COPY Gemfile.lock /src/Gemfile.lock

RUN bundle install

COPY . /src


FROMでベースイメージにrubyを指定する。

FROM ruby:2.7.0


RUNLinuxのコマンドを実行する。 apt-get update -qqでパッケージをインストールする前にアップデートする。-qqはログを表示しないためのオプション。 apt-get install -yで必要なパッケージをインストールする。-yはインストール時のいくつかの質問をすべてyesで省略するオプション。

RUN apt-get update -qq && apt-get install -y build-essential nodejs default-mysql-client

build-essentialは開発に必要なビルドツールを提供するパッケージ。 nodejsRailsのフロント部分のために必要なパッケージ。 default-mysql-clientMySQLを使うために必要なパッケージ。


コンテナ内にsrcディレクトリを作成する。

RUN mkdir /src


ワーキングディレクトリをsrcにする。

WORKDIR /src


ホストのGemfileとGemfile.lockをコンテナの/src配下にコピーする。GemfileとGemfile.lockについては後述。

COPY Gemfile /src/Gemfile
COPY Gemfile.lock /src/Gemfile.lock


コンテナ内でGemをインストールする。Gemについては後述。

RUN bundle install


ホスト側に作られたRailsのプロジェクトをコンテナにコピーする。

COPY . /src


docker-compose.yml

Docker Composeを使うための、docker-compose.ymlは以下の内容を記述する。

version: '3'

services:
  web:
    build:
      dockerfile: Dockerfile
      context: .
    command: bundle exec rails s -p 3000 -b '0.0.0.0'
    ports:
      - '3000:3000'
    volumes:
      - type: bind
        source: .
        target: /src
    depends_on:
      - db

  db:
    image: mysql:5.7
    ports:
      - '3306:3306'
    environment:
      MYSQL_ROOT_PASSWORD: password
    volumes:
      - type: volume
        source: mysql
        target: /var/lib/mysql

volumes:
  mysql:

最初のversion:はDocker Composeのバージョンを指定。 最後のvolumes:はデータベースのデータが消えてしまわないようにボリュームを作成する。

間のservices:にwebコンテナとdbコンテナの設定を書いていく。

webコンテナ

build:でビルドするDockerfileを指定する。

build: 
    dockerfile: Dockerfile
    context: .


command:はコンテナを起動したときに実行するコマンドを指定する。ここにはRailsのサーバーを起動するコマンドを記述。

command: bundle exec rails s -p 3000 -b '0.0.0.0'

bundle execはインストールされたgemのコマンドを実行するコマンド。rails s -p 3000Railsのサーバーをポート番号3000で起動し、 -b '0.0.0.0'でコンテナの外からサーバーにアクセスできるようにする。


ports:でホストのポート番号と、コンテナ内のポート番号を紐づける。ここではホストでRailsのサーバーのポート番号を3000に指定した時に、コンテナ内のサーバーの3000番ポートにアクセスする。

ports:  
    - '3000:3000'


volumes:ではバインドマウントを設定する。バインドマウントはホストとコンテナでファイルを共有するための仕組み。これによってホストのソースコードを更新したらコンテナに反映されるようにする。

voluems:  
    - type: bind
      source: .
      target: /src


depends_on:はwebコンテナをdbコンテナに依存させるための記述。これによってdbコンテナが起動してからwebコンテナを起動し、反対にwebコンテナが終了してからdbコンテナを修了させるようにする。

depends_on:  
    - db


dbコンテナ

image:でDocker Hubのイメージを指定する。

images: mysql:5.7


ports:は3306に指定する。

ports:  
    - '3306:3306'


environment:でコンテナで使用する環境変数を指定する。

environment:
    MYSQL_ROOT_PASSWORD: password


volumes:でボリュームをマウントする。これによってコンテナを終了してもデータベースのデータを保持できる。

volumes:
    - type: volume
    source: mysql
    target: /var/lib/mysql


Gemfile

RailsはGemとBundlerを使ってインストールする。

GemとはRubyのライブラリのこと。RailsもGemの1つ。

Bundlerとはgemを一括で管理するためのGemのこと。

GemfileはBundlerを使ってGemの管理を行うためのファイル。インストールしたいGemとそのバージョンを記述すれば、bundle installで一括でインストールできる。


source 'https://rubygems.org'
gem 'rails', '5.2.1'

sourceはgemのダウンロード元を指定する。 gem 'rails', '5.2.1'はバージョンが5.2.1のrailsのgemをインストールするための記述。

Gemfile.lock

Gemfile.lockはインストールしたGemとバージョンと依存関係が記述されるファイル。 Railsをインストールする前は空のGemfile.lockを作成し、インストール後も開発者が直接編集することはない。

2. Railsのプロジェクトを作成する

必要なファイルを用意できたら、以下のコマンドでRailsのプロジェクトを作成する。

docker compose run web rails new . --force --database=mysql

docker compose run webなので、webコンテナを起動して一度だけ後ろに続くコマンドを実行する。

webの後ろのrails new . --force --database=mysqlRailsのコマンドとオプションで、Railsのプロジェクトを作成している。

rails new .Railsのプロジェクトを現在のディレクトリに作成する。ここでの現在のディレクトリはコンテナ内の/srcを指す。 --forceは既存のファイルが存在している場合上書きするオプション。 --database=mysqlRailsで使用するデータベースをMySQLに指定するオプション。


Railsのプロジェクトがインストールされると、以下のようなディレクトリ構成になる。

.
├── app/
├── bin/
├── config/
├── db/
├── lib/
├── log/
├── public/
├── storage/
├── test/
├── tmp/
├── vendor/
├── .gitignore
├── .ruby-version
├── config.ru
├── docker-compose.yml
├── Dockerfile
├── Gemfile
├── Gemfile.lock
├── package.json
├── Rakefile
└── README.md


GemfileとGemfile.lockは以下のように更新される。

ssource 'https://rubygems.org'
git_source(:github) { |repo| "https://github.com/#{repo}.git" }

ruby '2.7.0'

# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '~> 5.2.8', '>= 5.2.8.1'
# Use mysql as the database for Active Record
gem 'mysql2', '>= 0.4.4', '< 0.6.0'
# Use Puma as the app server
gem 'puma', '~> 3.11'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 5.0'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# See https://github.com/rails/execjs#readme for more supported runtimes
# gem 'mini_racer', platforms: :ruby

# Use CoffeeScript for .coffee assets and views
gem 'coffee-rails', '~> 4.2'
# Turbolinks makes navigating your web application faster. Read more: https://github.com/turbolinks/turbolinks
gem 'turbolinks', '~> 5'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.5'
# Use Redis adapter to run Action Cable in production
# gem 'redis', '~> 4.0'
# Use ActiveModel has_secure_password
# gem 'bcrypt', '~> 3.1.7'

# Use ActiveStorage variant
# gem 'mini_magick', '~> 4.8'

# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development

# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false

group :development, :test do
  # Call 'byebug' anywhere in the code to stop execution and get a debugger console
  gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
end

group :development do
  # Access an interactive console on exception pages or by calling 'console' anywhere in the code.
  gem 'web-console', '>= 3.3.0'
  gem 'listen', '>= 3.0.5', '< 3.2'
  # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

group :test do
  # Adds support for Capybara system testing and selenium driver
  gem 'capybara', '>= 2.15'
  gem 'selenium-webdriver'
  # Easy installation and use of chromedriver to run system tests with Chrome
  gem 'chromedriver-helper'
end

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
GEM
  remote: https://rubygems.org/
  specs:
    actioncable (5.2.8.1)
      actionpack (= 5.2.8.1)
      nio4r (~> 2.0)
      websocket-driver (>= 0.6.1)
    actionmailer (5.2.8.1)
      actionpack (= 5.2.8.1)
      actionview (= 5.2.8.1)
      activejob (= 5.2.8.1)
      mail (~> 2.5, >= 2.5.4)
      rails-dom-testing (~> 2.0)
    actionpack (5.2.8.1)
      actionview (= 5.2.8.1)
      activesupport (= 5.2.8.1)
      rack (~> 2.0, >= 2.0.8)
      rack-test (>= 0.6.3)
      rails-dom-testing (~> 2.0)
      rails-html-sanitizer (~> 1.0, >= 1.0.2)
    actionview (5.2.8.1)
      activesupport (= 5.2.8.1)
      builder (~> 3.1)
      erubi (~> 1.4)
      rails-dom-testing (~> 2.0)
      rails-html-sanitizer (~> 1.0, >= 1.0.3)
    activejob (5.2.8.1)
      activesupport (= 5.2.8.1)
      globalid (>= 0.3.6)
    activemodel (5.2.8.1)
      activesupport (= 5.2.8.1)
    activerecord (5.2.8.1)
      activemodel (= 5.2.8.1)
      activesupport (= 5.2.8.1)
      arel (>= 9.0)
    activestorage (5.2.8.1)
      actionpack (= 5.2.8.1)
      activerecord (= 5.2.8.1)
      marcel (~> 1.0.0)
    activesupport (5.2.8.1)
      concurrent-ruby (~> 1.0, >= 1.0.2)
      i18n (>= 0.7, < 2)
      minitest (~> 5.1)
      tzinfo (~> 1.1)
    addressable (2.8.4)
      public_suffix (>= 2.0.2, < 6.0)
    archive-zip (0.12.0)
      io-like (~> 0.3.0)
    arel (9.0.0)
    bindex (0.8.1)
    bootsnap (1.16.0)
      msgpack (~> 1.2)
    builder (3.2.4)
    byebug (11.1.3)
    capybara (3.39.2)
      addressable
      matrix
      mini_mime (>= 0.1.3)
      nokogiri (~> 1.8)
      rack (>= 1.6.0)
      rack-test (>= 0.6.3)
      regexp_parser (>= 1.5, < 3.0)
      xpath (~> 3.2)
    chromedriver-helper (2.1.1)
      archive-zip (~> 0.10)
      nokogiri (~> 1.8)
    coffee-rails (4.2.2)
      coffee-script (>= 2.2.0)
      railties (>= 4.0.0)
    coffee-script (2.4.1)
      coffee-script-source
      execjs
    coffee-script-source (1.12.2)
    concurrent-ruby (1.2.2)
    crass (1.0.6)
    date (3.3.3)
    erubi (1.12.0)
    execjs (2.8.1)
    ffi (1.15.5)
    globalid (1.1.0)
      activesupport (>= 5.0)
    i18n (1.14.1)
      concurrent-ruby (~> 1.0)
    io-like (0.3.1)
    jbuilder (2.11.5)
      actionview (>= 5.0.0)
      activesupport (>= 5.0.0)
    listen (3.1.5)
      rb-fsevent (~> 0.9, >= 0.9.4)
      rb-inotify (~> 0.9, >= 0.9.7)
      ruby_dep (~> 1.2)
    loofah (2.21.3)
      crass (~> 1.0.2)
      nokogiri (>= 1.12.0)
    mail (2.8.1)
      mini_mime (>= 0.1.1)
      net-imap
      net-pop
      net-smtp
    marcel (1.0.2)
    matrix (0.4.2)
    method_source (1.0.0)
    mini_mime (1.1.2)
    mini_portile2 (2.8.2)
    minitest (5.18.1)
    msgpack (1.7.1)
    mysql2 (0.5.5)
    net-imap (0.3.6)
      date
      net-protocol
    net-pop (0.1.2)
      net-protocol
    net-protocol (0.2.1)
      timeout
    net-smtp (0.3.3)
      net-protocol
    nio4r (2.5.9)
    nokogiri (1.15.2)
      mini_portile2 (~> 2.8.2)
      racc (~> 1.4)
    public_suffix (5.0.1)
    puma (3.12.6)
    racc (1.7.1)
    rack (2.2.7)
    rack-test (2.1.0)
      rack (>= 1.3)
    rails (5.2.8.1)
      actioncable (= 5.2.8.1)
      actionmailer (= 5.2.8.1)
      actionpack (= 5.2.8.1)
      actionview (= 5.2.8.1)
      activejob (= 5.2.8.1)
      activemodel (= 5.2.8.1)
      activerecord (= 5.2.8.1)
      activestorage (= 5.2.8.1)
      activesupport (= 5.2.8.1)
      bundler (>= 1.3.0)
      railties (= 5.2.8.1)
      sprockets-rails (>= 2.0.0)
    rails-dom-testing (2.0.3)
      activesupport (>= 4.2.0)
      nokogiri (>= 1.6)
    rails-html-sanitizer (1.6.0)
      loofah (~> 2.21)
      nokogiri (~> 1.14)
    railties (5.2.8.1)
      actionpack (= 5.2.8.1)
      activesupport (= 5.2.8.1)
      method_source
      rake (>= 0.8.7)
      thor (>= 0.19.0, < 2.0)
    rake (13.0.6)
    rb-fsevent (0.11.2)
    rb-inotify (0.10.1)
      ffi (~> 1.0)
    regexp_parser (2.8.1)
    rexml (3.2.5)
    ruby_dep (1.5.0)
    rubyzip (2.3.2)
    sass (3.7.4)
      sass-listen (~> 4.0.0)
    sass-listen (4.0.0)
      rb-fsevent (~> 0.9, >= 0.9.4)
      rb-inotify (~> 0.9, >= 0.9.7)
    sass-rails (5.1.0)
      railties (>= 5.2.0)
      sass (~> 3.1)
      sprockets (>= 2.8, < 4.0)
      sprockets-rails (>= 2.0, < 4.0)
      tilt (>= 1.1, < 3)
    selenium-webdriver (4.9.0)
      rexml (~> 3.2, >= 3.2.5)
      rubyzip (>= 1.2.2, < 3.0)
      websocket (~> 1.0)
    spring (2.1.1)
    spring-watcher-listen (2.0.1)
      listen (>= 2.7, < 4.0)
      spring (>= 1.2, < 3.0)
    sprockets (3.7.2)
      concurrent-ruby (~> 1.0)
      rack (> 1, < 3)
    sprockets-rails (3.4.2)
      actionpack (>= 5.2)
      activesupport (>= 5.2)
      sprockets (>= 3.0.0)
    thor (1.2.2)
    thread_safe (0.3.6)
    tilt (2.2.0)
    timeout (0.3.2)
    turbolinks (5.2.1)
      turbolinks-source (~> 5.2)
    turbolinks-source (5.2.0)
    tzinfo (1.2.11)
      thread_safe (~> 0.1)
    uglifier (4.2.0)
      execjs (>= 0.3.0, < 3)
    web-console (3.7.0)
      actionview (>= 5.0)
      activemodel (>= 5.0)
      bindex (>= 0.4.0)
      railties (>= 5.0)
    websocket (1.2.9)
    websocket-driver (0.7.5)
      websocket-extensions (>= 0.1.0)
    websocket-extensions (0.1.5)
    xpath (3.2.0)
      nokogiri (~> 1.8)

PLATFORMS
  ruby

DEPENDENCIES
  bootsnap (>= 1.1.0)
  byebug
  capybara (>= 2.15)
  chromedriver-helper
  coffee-rails (~> 4.2)
  jbuilder (~> 2.5)
  listen (>= 3.0.5, < 3.2)
  mysql2 (>= 0.4.4, < 0.6.0)
  puma (~> 3.11)
  rails (~> 5.2.8, >= 5.2.8.1)
  sass-rails (~> 5.0)
  selenium-webdriver
  spring
  spring-watcher-listen (~> 2.0.0)
  turbolinks (~> 5)
  tzinfo-data
  uglifier (>= 1.3.0)
  web-console (>= 3.3.0)

RUBY VERSION
   ruby 2.7.0p0

BUNDLED WITH
   2.1.2

Gemfileには、Railsを使うためのgemが一覧として記述されており、Gemfile.lockには実際にインストールされたgemとそのバージョンが記述されている。

複数人で開発する場合バージョンを揃える必要があるので、このGemfile.lockを共有する。

3. イメージをビルドする

RailsのプロジェクトをインストールしたことでGemfileが更新されているので、以下のコマンドで再度ビルドする。

docker compose build

4. データベースの接続設定を行う

Railsのプロジェクトが作られると、configディレクトリが作られ、その配下にdatabase.ymlが作られる。このファイルによってデータベースの接続設定を行う。

# MySQL. Versions 5.1.10 and up are supported.
#
# Install the MySQL driver
#   gem install mysql2
#
# Ensure the MySQL gem is defined in your Gemfile
#   gem 'mysql2'
#
# And be sure to use new-style password hashing:
#   https://dev.mysql.com/doc/refman/5.7/en/password-hashing.html
#
default: &default
  adapter: mysql2
  encoding: utf8
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password:
  host: localhost

development:
  <<: *default
  database: src_development

# Warning: The database defined as "test" will be erased and
# re-generated from your development database when you run "rake".
# Do not set this db to the same as development or production.
test:
  <<: *default
  database: src_test

# As with config/secrets.yml, you never want to store sensitive information,
# like your database password, in your source code. If your source code is
# ever seen by anyone, they now have access to your database.
#
# Instead, provide the password as a unix environment variable when you boot
# the app. Read http://guides.rubyonrails.org/configuring.html#configuring-a-database
# for a full rundown on how to provide these environment variables in a
# production deployment.
#
# On Heroku and other platform providers, you may have a full connection URL
# available as an environment variable. For example:
#
#   DATABASE_URL="mysql2://myuser:mypass@localhost/somedatabase"
#
# You can use this database configuration with:
#
#   production:
#     url: <%= ENV['DATABASE_URL'] %>
#
production:
  <<: *default
  database: src_production
  username: src
  password: <%= ENV['SRC_DATABASE_PASSWORD'] %>


この部分のpassword:host:を変更する。

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

passwordはdocker-compose.ymlのdb:environment:MYSQL_ROOT_PASSWORDと合わせる。 dbはdocker-compose.ymlのservices:db:

5. Docker Composeでコンテナを起動する

docker compose up -dでコンテナを起動する。

docker compose up -d


もしコンテナが起動してもすぐにExitedになってしまう場合はdocker compose upでログを表示するように実行する。

6. データベースを作成する

docker compose run web rails db:createでデータベースを作成する。

docker compose run web rails db:create

db:createはデータベースを作成するRailsのコマンド。

7.Railsのページが表示されているか確認する。

docker-compose.ymlでwebコンテナのポートを3000に指定しているので、http://localhost:3000Railsのページが表示されるか確認する。表示されれば環境構築の完了。