こんにちは!りゅうです。
今回も前回に引き続き、Dockerの記事を書いてみました。内容はタイトルの通りDocker+MySQL+Railsの開発環境を作るのですが、焦点はdocker-compose.ymlを使うことです。
Railsのことも触れましたが、自分は初めてだったので不足しているところは色々調べながら書いていきました。
この記事で実現したいこと
docker-compose.ymlの基本的な扱い方、書き方、内容が理解できるようになること
Railsの初歩的な部分を理解できるようになること
前回と同様Dockerが使える環境を前提として書いています。
こちら(Udemy講座)を参考にしました。解説が丁寧でとても分かりやすい講座でした。
米国AI開発者がゼロから教えるDocker講座
今回使っていくdocker-compose.ymlはDockerfileと比較すると…
・複数のコンテナを一つにまとめることができる
・コンテナの中身というよりは、コンテナをどのように使っていくかなどを定義する
・コンテナの立ち上げが楽になる
こんな感じだと思います。
docker-compose.ymlはDockerfileも合わせて使っていたりします。
早速、開発環境の作成に必要なファイルを4つ用意していきます。
Dockerfile
Railsのコンテナにどんなものを用意するか記載しています。
Gemfile
Railsで使用するgem(Rubyのライブラリ)が一覧で書かれたファイルです。これに従ってgemがインストールされます。
ここでは使用するRailsのみ記載し、あとは実行する中で色々勝手に追記されています。
Gemfile.lock
Gemfileでインストールしたgemのバージョン情報などが書かれています。ファイルだけ用意し、特に中身の編集はしません。
docker-compose.yml
今回の主役です。ここにはRailsのコンテナとMySQLのコンテナを立ち上げる時の情報を記載しています。
ファイルを作成した後の環境構築フォルダ直下はこんな感じです。
まずはDockerfileから記述していきます。
Dockerfileについては前回の記事で基本的な書き方について書いてみたので、良かったら合わせて読んでみてください。
FROM ruby:2.5 RUN apt-get update && apt-get install -y \ build-essential \ libpq-dev \ nodejs \ default-mysql-client \ yarn WORKDIR /RailsMySQLSample COPY Gemfile Gemfile.lock /RailsMySQLSample/ RUN bundle install
Dockerfileをビルドした時の流れとしては、rubyのベースイメージを取得、そのあと必要な開発ツールをインストールしています。
WORKDIR以降でコンテナを立ち上げる前にGemfile、Gemfile.lockをコピーし、bundle installで不足したgemがあればインストールをしています。
続いてGemfileとGemfile.lock
source 'https://rubygems.org' gem 'rails', '~>5.2'
railsの5.2以上のバージョンを https://rubygems.org から取得するよう定義します。
Gemfile.lockは空ファイルでOKです。
最後にdocker-compose.yml
version: '3' services: web: build: . ports: - '3000:3000' volumes: - '.:/RailsMySQLSample' tty: true stdin_open: true
Railsコンテナ部分のみで、DB情報はあとで追加していきます。
記述の仕方はJson形式で書かれています。.ymlがJsonの上位互換みたいな感じでJsonでできることはほぼできるようです。あとはインデントの深さで意味付けされています。
要素名 | 要素の説明 | 指定内容の説明 |
version | docker-composeのバージョンを指定 | バージョンの数字 |
services | この後にコンテナ情報をインデント一つ下げて定義 | – |
web | コンテナの名前、任意でOK | webアプリのコンテナは大体webと定義 |
build | ビルド時のDockerfileがあるパスを指定 | カレントディレクトリをビルド時のパスとして指定 |
ports | ホストとコンテナのポート番号を指定 ホスト:コンテナ | ホストもコンテナも3000を指定 (Railsのデフォルトポートが3000みたいです) |
volumes | コンテナの参照先を指定 ホスト:コンテナ | ホスト側のカレントディレクトをコンテナのRailsMySQLSampleで参照 |
tty | 出力表示をきれいにするか -tオプションと同様 true/falseを指定 | trueなのでする |
stdin_open | 入力操作できるようにするか -iオプションと同様 true/falseを指定 | trueなのでする |
必要なファイルを準備できたら、docker-composeのコマンドを使ってビルドしてみます。
ターミナルを開き、以下のコマンドでビルド、コンテナ起動ができます。
docker-compose up -d --build
コマンド/オプション名 | 説明 |
up | コンテナを起動 対象のイメージがない場合は自動でビルド |
-d | バックグラウンドでコンテナ起動 指定しない場合、コンテナ起動中、起動に使ったターミナルは操作できない |
–build | コンテナを起動する前に強制的に再ビルドし直してくれる ソースを修正したときなどに指定する |
以下のコマンドでビルドとコンテナ起動を別々にできます。
docker-compose build docker-compose up -d
ビルド、起動したらコンテナが立ち上がっているか確認してみます。
docker ps
起動が確認できたら、以下のコマンドでコンテナの中に入って操作をしてみます。
docker-compose exec web bash
docker-compose execは
docker-compose exec コンテナ名 実行コマンド
でコマンドの実行ができます。 コンテナ名(web)はdocker-compose.ymlの「services:」の後に定義したやつです。
docker-compose.yml で「tty:」と「stdin_open:」 が未定義の場合、以下のコマンドで全く同じ動作をしてくれます。
docker-compose exec -it コンテナ名 実行コマンド
それなので定義しておいた方が楽そうですね。
コンテナに入れたら、Gemfileに書いたRailsがちゃんと入っているか確認してみます。
rails -v
Gemfileに指定した5.2以上のバージョンで入っていました。
Railsが確認できたら以下のコマンドでRailsアプリ開発に必要なものを入れてみます。
rails new . --force -d mysql --skip-bundle
コマンド/オプション名 | 説明 |
new | Railsアプリに必要なものを指定したディレクトリにインストール カレントディレクトリを指定 |
-d | 使用するデータベースの指定 MySQLを使うのでmysqlと指定 |
–skip-bundle | bundle installを行わない(gemのインストール) Dockerfile内でコンテナビルド時にbundle installを指定するので、ここでは行わない |
コマンドを実行すると色々と作り始めました。
今回「rails new . 」で指定したコンテナのカレントディレクトリRailsMySQLSample、これはホストのDockercompose.ymlなどがあるディレクトリをマウント(参照)しているので、ホスト側に色々と作られていました。
ここまででDBなしのRails開発環境ができました。
続いてDBコンテナを作成していくので、一旦exitでコンテナからは抜けます。
先ほど色々作られた中からconfig>database.ymlを探して修正していきます。
10行目を過ぎたあたりに以下のような記述が見つかると思います。
default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password: host: localhost
この記述を少し修正していきます(下3つ修正)。
default: &default adapter: mysql2 encoding: utf8 pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> username: root password:<%= ENV.fetch("DATABASE_PASSWORD") %> host: db port: 3306
password: には環境変数 DATABASE_PASSWORD からパスワードを取得してくるように指定しています。環境変数へのパスワードはこの後修正するdocker-compose.ymlで定義していきます。
host: localhostにはこれから作成するDBコンテナの名前「db」を指定しています。
port: を追記し、MySQLのデフォルトポート3306を指定しています。
最初に作ったdocker-compose.ymlにDBコンテナを作成することと、webコンテナがDBコンテナへ接続できるように修正していきます。
version: '3' volumes: data: services: web: build: . ports: - '3000:3000' volumes: - '.:/RailsMySQLSample' tty: true stdin_open: true environment: - 'DATABASE_PASSWORD=password' depends_on: - db links: - db db: image: mysql:5.7 ports: - '3306:3306' volumes: - 'data:/var/lib/mysql' environment: MYSQL_ROOT_PASSWORD: password
追記した箇所
2,3行目(DBコンテナのマウント先、24行目でマウントの定義)
volumes: data:
volumes: はdocker内に定義された領域のようです。そのためマウント先のdataフォルダはホスト側にあるわけではないそうです。
13~18行目(webコンテナとDBコンテナの接続)
environment: - 'DATABASE_PASSWORD=password' depends_on: - db links: - db
environment:にDB接続時のパスワードを指定しています。database.ymlに使われるやつです。
depends_on:はdbコンテナが起動してからwebコンテナを起動するという指定です。
links:でwebコンテナとdbコンテナを繋げています。
19~26行目(DBコンテナ部分)
db: image: mysql:5.7 ports: - '3306:3306' volumes: - 'data:/var/lib/mysql' environment: MYSQL_ROOT_PASSWORD: password
DBコンテナの基本情報になるポート、マウント先、rootユーザのパスワードを指定しています。
ここまででホスト側で用意するものは一通り完成しました!あとはコマンド入力をしながら作業を進めていきます。
今あるコンテナはRailsのみのコンテナなので、一旦コンテナは以下のコマンドで削除します。
docker-compose down
古いコンテナが残ったままビルド、起動し直すと古いデータの一部が残っていたりするので、意図した通り動かすためにはコンテナを削除して作り直すのがいいんだと思います。
コンテナを削除したらwebコンテナを起動したときに使ったコマンド
docker-compose up -d --build
でビルド、起動し直しです。
再びコンテナに入っていきます。
docker-compose exec web bash
以下のrailsコマンドでDBを作ります。
rails db:create
database.ymlの20行目を過ぎたあたりにDB名を定義しているところがあります。DB名を変更したい場合はここで変えられます。
簡易アプリの作成をしていきます。
rails g scaffold というrailsのコマンドを使用してみます。
引数には「見出し 項目名1:型 項目名2:型…」のような感じで指定です。
rails g scaffold Member Name:string Sex:string
上記の指定で以下のような画面の入力項目やコントローラ・モデルも自動で用意してくれます。
次にDBへテーブルやカラムの反映を行うため、以下のコマンドでマイグレーションを実行してみます。
rails db:migrate
実行後DBコンテナに反映されていました。
最後に以下のコマンドでサーバを起動し、localhost:3000にアクセスしてみます。
rails s -b 0.0.0.0
-b 0.0.0.0はwebコンテナが持っている全てのネットワークインターフェースと結び付けをしてくれるので、コンテナ外部からでもコンテナのlocalhostにアクセスができるようになるようです。(ネットワーク苦手なので学習が必要…)
問題なくアクセスできると、Railsのデフォルト画面が表示できると思います。
rails g scaffold コマンドの見出し名(ここではMember)を複数形にした/membersをポート3000の後に指定すると以下の画面が表示できると思います。
学習したことを一通り書いてみましたが、思いのほか長くなってしまいました…。
今回は記載する内容が多かった分、理解が曖昧で記事にアウトプットするには何度も見直しや深堀が必要でした。ですがその甲斐あってDockerの基礎はより自分のものにできたと感じています。
改めて今回大変お世話になったこちらのUdemy講座、Dockerの理解を深めるのに非常におすすめだと個人的には感じているので、是非ご視聴してみてください。
米国AI開発者がゼロから教えるDocker講座
今回は以上になります。
最後までご覧いただき、ありがとうございました。