#1.これからDocker導入します、という方は、まず、こちらを見ていただけると幸いです。
①Dockerを初めて導入して基本操作する (2020.4時点)
本稿は、
Dokerコンテナイメージを作成して、
コマンド「docker-compose up 」でRails s起動するという流れです。
自分と同じように、
何していいかわからないゼロスタートの方になるべくわかるようにしたいと思っています。
#2.前提
Docker for Macアプリをインストールしている
Dockerサービスが起動している
DockerHubでサインインしている
VSCodeで編集
ターミナル使用
Sequelpro使用
<環境>
macOS : Catalina 10.15.3
Docker version : 19.03.8
ruby : 2.5.1
Rails : 5.2.4.1
MYSQL :5.6
<参考>
Dockerはこう書くとこう動くよ、というのがわかりやすい、こちらの動画ををおすすめします!
Docker超入門 Part01〜Part04
https://youtu.be/7mwoTs0LoYA
今から追いつくDocker講座!AWS ECSとFargateで目指せコンテナマスター!〜シリーズ1回目〜
https://youtu.be/DS5HBTMG1RI
では、はじめていきましょう!
#3.Dockerfile を新規作成して編集する
今回はVSCodeを使って進めます。
ローカルで作業中のRailsアプリを開き、Dockerfileをアプリのディレクトリの一番上位に新規作成します。
新規作成するファイル名は「 Dockerfile 」 です。
Dockerfileに、ベースとするDockerイメージ(Ruby)に対して実行する内容を記述します。
このように記述してみます。
#FROM(フロム)はDocker に対して ベースとなるRubyイメージを指定する
FROM ruby:2.5.1
#run(ラン)はdocker-compose buildコマンドで実行される
#Railsの起動に必要となるnodejsをインストールする
#apt-getコマンドはUbuntuパッケージ管理システム=APTライブラリを利用してパッケージ操作・管理するコマンド
#①updateで常に新しいパッケージinstall →②-qqはエラー以外は表示しない →③常にyesの-y指定
#→④ubuntuのbuild-essential(OS基礎開発パッケージ) → ⑤libpq-dev(OS開発パッケージ)
#→⑥nodejs(サーバーサイドのJavaScript) の順番でインストールする
# \ バックスラッシュでコードを改行して見易くする (\ はoption+¥です)
RUN apt-get update -qq && \
apt-get install -y build-essential \
libpq-dev \
nodejs
#今回はapp_nameという名前のディレクトリ(場所)を作ります
#mkdir(メイクディレ)=(make directory)
#ディレクトリ名は自由です
RUN mkdir /app_name
/#WORKDIR(ワークディレ)は、RUNやADDなどの命令実行するカレントディレクトリ
#カレントディレクトリ(作業位置)をapp_nameに移動(cdコマンドと同じ)
WORKDIR /app_name
/#COPY(コピー)はローカル側のファイルをdockerイメージ側の指定したディレクトリにコピーする
#ローカルのGemfileをapp_name/Gemfileにコピーする
#ローカルのGemfile.lock をapp_name/Gemfile.lockにコピーする
#docker-compose build 実行する前に、ローカルのGemfile.lock内を全削除しておきます(エラー対策)
COPY Gemfile /app_name/Gemfile
COPY Gemfile.lock /app_name/Gemfile.lock
#gem install bundler インストールを実行する
#bundle install を実行する
RUN gem install bundler
RUN bundle install
#ADD(アド)はローカル側のファイルをdockerイメージ側の指定したディレクトリに追加(コピー)する
#ローカルの(.)カレントディレクトリをコンテナのapp_nameディレクトリに追加(コピー+解凍)する
ADD . /app_name
プラスウイングTVさんの「Docker超入門 Part01 - Dockerを使った開発環境構築」がとてもわかりやすかったので引用させていただきます。(ありがとうございます!)
https://youtu.be/7mwoTs0LoYA
・Rails の環境構築の元になるRuby、Rails、Nodejs、MySQLは、DockerHub上にあって勝手にそこから引っ張ってきてくれる。
・DockerHubでrubyを検索 すると、真ん中あたりにruby2.5ありました。
これをFROMに書けば勝手にベースにしてくれるのですね、すごい楽ちん!
##Dockerfile作成 Qiitaで参考になった記事
Dockerfileを書くためのベストプラクティス【参考訳】v18.09https://qiita.com/zembutsu/items/a96b68277d699f79418d
Docker × Ruby on Rails × MySQLの環境構築https://qiita.com/tatsuo-iriyama/items/0bf3b08de03280314c91
Ruby on Rails 「途中まで作ったアプリにDockerを導入したい」に挑戦してみるhttps://qiita.com/majorboy/items/9fbfc78fc7bbc1f35e77#comment-60a244ed29cedf06555d
Docker × Ruby on Rails × MySQLの環境構築https://qiita.com/tatsuo-iriyama/items/0bf3b08de03280314c91
Docker で環境変数をホスト OS 側からゲスト OS (コンテナ)に渡す方法(各種)https://qiita.com/KEINOS/items/518610bc2fdf5999acf2
Docker入門 ~Dockerfile編~ https://qiita.com/takaday/items/08c8269dc926af8cb661
Dockerfile のコマンド一覧https://qiita.com/FumiyaShibusawa/items/a0be39d28139a044157d
Bundlerの使い方 https://qiita.com/oshou/items/6283c2315dc7dd244aef
[Ubuntu] apt-get まとめhttps://qiita.com/white_aspara25/items/723ae4ebf0bfefe2115c
##Dockerfile作成 ググって参考になった記事
公式チュートリアル https://docs.docker.com/compose/rails/#connect-the-database
Dockerfile のベストプラクティス http://docs.docker.jp/engine/articles/dockerfile_best-practice.html
Dockerfile リファレンス http://docs.docker.jp/engine/reference/builder.html
Linuxのコマンド(とか)の呼び方をこじらせるhttps://unskilled.site/独学でプログラミングを勉強するとlinuxのコマンド/
build-essentialとは https://qiita.com/h_tyokinuhata/items/431a56fb054145468c16
Ubuntuとは?https://eng-entrance.com/what-is-ubuntu
パッケージ: build-essential (12.4ubuntu1) https://packages.ubuntu.com/ja/bionic/build-essential
パッケージ: libpq-dev https://packages.ubuntu.com/ja/bionic/libpq-dev
mkdirコマンドの詳しいまとめhttps://eng-entrance.com/linux-command-mkdir
なぜ、Ruby on Railsの動作にNode.jsが必要なのか https://www.xenos.jp/~zen/blog2/index.php/2019/03/19/post-1831/
#4.docker-compose.ymlを編集する
・DockerComposeは、複数コンテナを定義して同時起動するオーケストレーションツールです。
・docker-compose.ymlは設定記述用途のYAMLファイル形式でCompose ファイルと呼ばれ、
サービス(services) 、 ネットワーク(networks) 、 ボリューム(volumes) を定義し、
アプリケーション全ての依存関係(データベース、キュー、キャッシュ、ウェブ・サービス、API 等)を設定します。
docker-compose.ymlをRailsアプリのディレクトリの一番上位に新規作成します。
このように記述してみます。
#docker-composeのバージョン(2020.4.12時点では"3"で問題なさそう)
version: '3'
#servicesは各コンテナを定義します
services:
#dbは1つのコンテナ名です(1コンテナ1プロセス)
#ローカルmysql version確認 → mysql Ver 14.14 Distrib 5.6.47
#DockerHubでmysql5.6を確認できたので5.6と記述
db:
image: mysql:5.6
#environmentは環境変数を追加します
#環境変数MYSQL_ROOT_PASSWORDに、今回はpasswordと入れます(パスは自由)
#パスワードの直打ちは危険なので、環境変数を使って秘匿します
environment:
MYSQL_ROOT_PASSWORD: 'password'
#portsは公開用のポートで、ホスト側とコンテナ側の両方のポートを指定します( ホスト側:コンテナ側 )
#ローカルMYSQLはポート確認すると3306を使用中なので、ホスト側は4306にします(4にした深い意味はありません)
#ローカル側MYSQLは大抵は自動で3306になっているそうです
#Sequelproにて4036(例として)を指定すると、DockerのMYSQLがSequelproで見れるようになります。
ports:
- "4306:3306"
#webは1つのコンテナ名です(1コンテナ1プロセス)
#buildはdockercompose.ymlを基点に指定フォルダー配下のDockerfileを元にコンテナを作成します。
#指定は . ルート (つまり、ルート直下に置いた先ほど作成したDockerfileを参照する、という記述です)
web:
build: .
#commandは任意にコマンドを上書きできます。
#bashはOSカーネルとユーザの橋渡しするプログラムシェルです
#起動停止の繰り返しで起こるエラー「A server is already running.」の原因、pidをbuildのたび削除する(unicorn master KILLと同じですね)
#Rails serverを立ち上げた際にURL(http://0.0.0.0:3000)にアクセス=localhost:3000
command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
#volumesではパスを指定するとDockerエンジンはボリュームを作成します
#カレントディレクトリ(.)をapp_nameディレクトリにマウントします。
volumes:
- .:/app_name
#portsは公開用のポートのことでホスト側とコンテナ側の両方のポートを指定します( ホスト側:コンテナ側 )
#localhost:3000にアクセスするとコンテナの3000ポートにつながります
ports:
- "3000:3000"
#depends_onはサービス間の依存関係を指定します
#webコンテナ側からdbコンテナにdbの名前で接続できるようになります
#docker-compose up を実行したら、web:コンテナのプロセスを開始するより前にdb:コンテナのプロセスを先に実行します
depends_on:
- db
##DockerHubでMYSQLを調べる
DockerHubで検索すると、MYSQLイメージが見つかります。
##ローカルでMYSQLのバージョンとポートを調べる
mysql -u root
でローカルのMYSQLに入ります。
mysql> これがでたら
mysql> show variables like 'port'; を実行します
すると、バージョンとポートの情報が見れます。
私のRailsアプリ(ローカル)のMYSQLは、version:5.6.46、ポートは3306番でした。
##docker-compose.yml作成 Qiitaで参考になった記事
Docker ドキュメント日本語化プロジェクトhttp://docs.docker.jp/compose/toc.html#
YAMLとは何か? - いつもRailsの設定ファイルで出てくるやつの正体https://qiita.com/Yama-to/items/587544993fb62610528a
MySQLのバージョン確認方法https://qiita.com/haxpig/items/b270acb9550efddd5fe5
今さら聞けない!OSとは何か?https://www.sejuku.net/blog/6084
bash 入門https://rat.cis.k.hosei.ac.jp/article/linux/bash_intro.html
【初心者向け】Linuxカーネルって一体なんだ?https://qiita.com/uguis410/items/17ec1e447e9716bfdca7
docker-compose upしたときに「A server is already running.」って言われないようにするhttps://qiita.com/paranishian/items/862ce4de104992df48e1
Bundle installからRails serverを起動するまでhttps://wonderful-tereshkova-38f91d.netlify.com/Bundle%20installからRails%20serverを起動するまで/
rails sとは localhostとはhttps://qiita.com/MIRAI1221/items/29f764db4f50bb44e3f4
MacでMySQL使用準備あれこれhttps://qiita.com/E-11/items/a230f6564614eeddef8c
docker-compose up したコンテナを起動させ続ける方法https://qiita.com/sekitaka_1214/items/2af73d5dc56c6af8a167
#5.database.yml を編集する
Railsアプリには config/database.yml が既に存在しています。
このファイルを編集します。
・MYSQLにパスワードを設定します。
password: password (←これ) #docker-compose.ymlのMYSQL_ROOT_PASSWORD
・データベースが動作しているホスト名を設定します。
host: db (←これ )#docker-compose.ymlのservice名の db
このように記述します。
default: &default
adapter: mysql2
encoding: utf8
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
nickname: root
password: password #(←ここ、passwordを追記します)
socket: /tmp/mysql.sock
host: db #(←ここ、host:dbを追記します)
これで準備は完了しました!....のはずでした。
##エラー発生です!
無事にDockerコンテナイメージを構築できるか、祈りながらコマンド実行!
docker-compose build
はい、Dockerさん、なんか怒ってます。
You must use Bundler 2 or greater with this lockfile.
(このロックファイルでは、Bundler 2以上を使用する必要があります。)
ERROR: Service ‘web’ failed to build: The command ‘/bin/sh -c bundle install’ returned a non-zero code: 20
振り返ると、コンテナくじらさんはこう言ってたようです。
Dockerfile36行でバンドラーのバージョン指定がなかったから、最新の2系をインストールしたよ!
Dockerfile37行でバンドルインストールしろって言うから実行したけど無理でしたよ。
##バンドラー問題を解決した方法
お世話になった記事です(ありがとうございました!)
Railsの既存AppをDockerに切り替える際に役立つ記事
https://qiita.com/mylevel/items/ff86875df64e3d002fc9
・エラー解決でやったこと
1. Dockerfileに RUN gem install bundler -v 1.3.0 と1系のバージョン指定した
2. ローカルのGemfile.lockを command+A+✖️で全削除した
3. docker-compose build コマンドを実行
docker-compose build
これでエラーを解決できました。
#6.build コマンドで imageを構築する
buildコマンドを実行します。
buildコマンドは指定したDockerfileを読み込み、1行1行命令を実行しながらイメージを構築します。
docker-compose build
ターミナルはこんな感じです。
無事、最後のSTEPまで成功しました。
#7.DockerコンテナのMYSQLにDB(db:create)を作成し、テーブル作成(db:migration)する
DockerコンテナのMYSQLにRailsアプリのDB作を作成します。
docker-compose run web bundle exec rake db:create
##エラー発生です!
また怒られました。今度は、くじらデーモン閣下。
user@keisukeagamiAir nomadcafe % docker-compose run web bundle exec rake db:create
Starting nomadcafe_db_1 ... done
Error response from daemon: Mounts denied:
The path /Applications/nomadcafe
is not shared from OS X and is not known to Docker.
You can configure shared paths from Docker -> Preferences... -> File Sharing.
See https://docs.docker.com/docker-for-mac/osxfs/#namespaces for more info.
google様の通訳:
デーモンからのエラー応答:マウントが拒否されました:
パス/ Applications / nomadcafe
OS Xからは共有されず、Dockerには認識されません。
Docker-> Preferences ...-> File Sharingから共有パスを設定できます。
詳細については、https://docs.docker.com/docker-for-mac/osxfs/#namespacesを参照してください。
##デーモンからマウントを拒否される問題を解決した方法
お世話になった記事です(ありがとうございました!)
Docker for Macでコンテナとのボリュームマウントに苦労した話
https://qiita.com/harukisan/items/31f15780760ab2f3d213
・エラー解決でやったこと
1.Docker for macアプリ > Resources > FILESHARINDに移動
2.一番下の+ボタンを押して、ローカルのRailsアプリファイルを指定
3.Apply&Restartをおしてリロードを完了
Docker for macを開きます。
(デスクトップ上端メニューバーのwifiやbluetoothあたりにある、くじらアイコンを触ってpreferences...を選択します)
作業しているRailsアプリのファイルを選択します。
選択したらリロードします。
Apply&Restartボタンを押して、リロードしました。
あらためて、DockerコンテナのMYSQLにRailsアプリのDB作を作成します。
docker-compose run web bundle exec rake db:create
続いて、マイグレーションしてテーブルを作ります。
Dockerコンテナはlocalとは環境が異なりますので、DB作成とマイグレーションが必要です。
Dockerコンテナでのrailsコマンドは通常のコマンドの前に 「docker-compose run web」をつけて実行します。
docker-compose run web bundle exec rake db:migrate
#8.コンテナを起動する docker-compose up (or start)
image構築、コンテナ構築、コンテナ起動をやってくれるコマンドを実行してみます。
docker-compose up
すると、ターミナルはこんな感じです。
最後に、Rails sのときと同じ見覚えのある単語が出てきました!
無事、アプリが起動しました!
#9.最後に
当方、
実務未経験+初学者+テッ○キャンプ卒業+転職活動中であります。
まだまだ、素人同然なので、間違いがございましたらご教示いただけるとありがたいです。
たくさんのQiita記事でコードを見合わせたり、エラー解決記事が投稿されてたり、そのおかげでここまで実装できました。
記事を投稿してくださった先輩方に感謝しております。
この先も本番環境でのdocker実装に向けて進みつつ、わかりやすい記事を寄稿していきたいと考えています
##ローカル・Dockerで開発環境を整えるまでの続編
②Dockerを初めて導入してRails sする (2020.4時点)
③Docker MYSQLにデモデータ(seed_fu)を投入する!(2020.4時点)
④ローカルDocker環境でデータ永続化、entrypointでseed_fuをやり直しする(2020.4.時点)
⑤AWS仮想サーバを利用する、AWSアカウント作成 + EC2インスタンス作成(2020.4時点)
こちらも続けて見ていただけると流れがわかると思います。