背景
Dockerとは、Linux環境をコンテナという単位で管理できるプログラムです。これを利用すると、複数人数で開発する時に各PCでの環境構築する際の手間を減らせます。
RailsとはRuby on Railsの略称であり、Rubyというプログラミング言語でwebアプリを作るためのフレームワークです。
これを利用すると webアプリ(データを登録、編集したりするwebサイト)を比較的早く作れます。
MySQLとは、データベース(以下DB)を扱うプログラムの1つです。
Railsアプリで扱うデータを保存するのに使います。
gitとはバージョン管理プログラムの1つです。
これを利用すると、githubやbitbucketなどを通して、他の人とプロジェクトを共有できます。
現行最新のRails 5.2.1とMySQL8のDockerでの連携に手間取ったので、備忘録を兼ねて方法を共有します。
使ったもの
docker-compose
dockerコマンドだけで連携を実現するのは難しいので、docker-composeというdockerの便利プログラムを使います。docker.ceとdocker-composeをインストールしてください。
docker.ce
Ubuntu向け: Get Docker CE for Ubuntu
Windows向け: Install Docker for Windows
Mac向け: Install Docker for Mac
docker-compose
Install Docker Compose
この記事の動作確認を行った環境はこちらです。
$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 18.04.1 LTS Release: 18.04 Codename: bionic $ docker --version Docker version 18.06.1-ce, build e68fc7a $ docker-compose --version docker-compose version 1.22.0, build f46880fe
git
バージョン管理プログラムです。インストールしてください。
Git - Downloads
プロジェクト新規作成時の操作
Railsプロジェクトの作成にDockerを利用することで、PCにRubyが入っていなくてもRailsプロジェクトを新規作成できます。今回は例として、rails-docker-practiceというフォルダでプロジェクトを構築します。
まず、構築する元となるフォルダを作成し、その中に入ります。
個人的な好みで、この記事ではgitprojectsというフォルダの中にプロジェクト作成します。
mkdir ~/gitprojects/rails-docker-practice cd ~/gitprojects/rails-docker-practice
空のGemfile.lockを含むwebフォルダを作成します。このwebフォルダの中にRailsアプリを構築します。
mkdir web touch web/Gemfile.lock
webフォルダの中に、RailsをインストールするためのGemfileを作成します。
~/gitprojects/rails-docker-practice/web/Gemfile
source 'https://rubygems.org' gem 'rails', '~> 5.2.1'
webフォルダのGemfileとGemfile.lockを利用してrubyコンテナを作成するためのGemfileを作成します。
~/gitprojects/rails-docker-practice/Dockerfile
FROM ruby:2.5.3 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /web WORKDIR /web ADD web/Gemfile /web/Gemfile ADD web/Gemfile.lock /web/Gemfile.lock RUN bundle install ADD web /web
webフォルダをRailsのrubyコンテナとしてとして、dbフォルダをMySQLコンテナのデータ置き場として連携するためのdocker-compose.ymlを作ります。
~/gitprojects/rails-docker-practice/docker-compose.yml
version: '3' services: db: image: mysql command: mysqld --default-authentication-plugin=mysql_native_password environment: MYSQL_USER: root MYSQL_ROOT_PASSWORD: password ports: - '3316:3306' volumes: - ./db/mysql/volumes:/var/lib/mysql web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - ./web:/web ports: - "3000:3000" depends_on: - db
MySQL8からデフォルトの設定ではパスワード認証を使わないようになっているため、上記のdocker-compose.ymlで「command: mysqld --default-authentication-plugin=mysql_native_password」 をdbに記述してパスワード認証を有効にしています。
これがないと、下記のようなエラーが表示されて、RailsとMySQLを連携できません。
Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib/x86_64-linux-gnu/mariadb18/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory Couldn't create database for {"adapter"=>"mysql2", "encoding"=>"utf8", "pool"=>5, "username"=>"root", "password"=>"password", "host"=>"db", "database"=>"web_development"} rake aborted! Mysql2::Error: Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib/x86_64-linux-gnu/mariadb18/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory
Dockfile、Gemfile、docker-compose.ymlを作ったら、下記のコマンドを実行してMySQLを使うRailsのプロジェクトを作ります。
Gemfileの上書き時の警告が出なくても良いと思うので、「--force」オプションを付けています。
コンテナをビルドする時にbundle installしないとインストールした内容が破棄されてしまうので、「--skip-bundle」オプションを付けて、Railsプロジェクト作成時のbundle installを行わないようにしています。
docker-compose run web rails new . -d mysql --force --skip-bundle
上記のコマンドでwebフォルダにRailsのファイルが、dbフォルダにMySQLのデータファイルが作成されます。 Dockerのコンポーネントによって作られたファイルは所有権がrootになっていて扱いにくいので、下記のコマンドでwebとdbフォルダを所有権を自分に変更します。
sudo chown -R $USER:$USER web db
dbフォルダの所有権を変更していないと、docker-composeコマンドでコンテナを作り直すときに下記のようなエラーが出ます。
sudoを付けてdocker-compseコマンドを実行すれば良いのですが、sudoを付けたり付けなかったりするのが手間なので、上記のコマンドで権限を変えておくのが良いと思います。
Railsのプロジェクトができたら、Dockerを通してMySQLに接続するために、database.ymlのパスワードとホストを下記のように変更します。
~/gitprojects/rails-docker-practice/web/config/database.yml
# password: password: password # host: localhost host: db
上記のdatabase.ymlの変更は、sedコマンドを利用して下記のようなコマンドでも行なえます。
sed -i -e 's/password:$/password: password/g' web/config/database.yml sed -i -e 's/host: localhost$/host: db/g' web/config/database.yml
Railsプロジェクトのフォルダに「.git」ディレクトリが勝手に作られますが、不要なので消しておきます。
sudo rm -r web/.git
rails newで更新されたGemfileに書かれているライブラリをDockerコンテナで扱うために、コンテナを作り直します。
(作り直しはGemfileを更新する度に必要になります。)
docker-compose build
Railsプロジェクトができたのでdb:createでDBの作成をしようとすると、下記のようなエラーが出ることがあります。
Starting docker-test_db_1 ... done Mysql2::Error: Failed to create schema directory 'web_development' (errno: 13 - Permission denied): CREATE DATABASE `web_development` DEFAULT CHARACTER SET `utf8` Couldn't create database for {"adapter"=>"mysql2", "encoding"=>"utf8", "pool"=>5, "username"=>"root", "password"=>"password", "host"=>"db", "database"=>"web_development"} rake aborted! ActiveRecord::StatementInvalid: Mysql2::Error: Failed to create schema directory 'web_development' (errno: 13 - Permission denied): CREATE DATABASE `web_development` DEFAULT CHARACTER SET `utf8`
コンテナを止めるとMySQLの初期化が済むからか上記のエラーが出なくなるので、下記のコマンドでコンテナを止めます。
docker-compose down
MySQLコンテナの初期化が済んでいれば、下記のコマンドでRails用のDBを作成できます。
docker-compose exec web rake db:create
以上の操作でRailsのプロジェクト作成とDBの作成ができました。
下記のコマンドでRailsとMySQLのコンテナを動かします。
docker-compose up
上記のコマンドを実行している状態でブラウザから http://localhost:3000 にアクセスすると、Railsアプリのトップページを確認できます。
dbフォルダが作成されますが、DBに関するデータは各PCで作成すればgitに含まなくても良いので、gitignoreに記述てgitの管理から除外します。
~/gitprojects/rails-docker-practice/.gitignore
db/
上記の.gitignoreを作成してから下記のようなコマンドでgitprojectを開始すれば、必要最低限のものだけがgitの管理対象になって良いと思います。
git init git add . git commit -m 'Initial commit'
Rails + MySQLのDockerプロジェクトを新規作成できました。
既に作成しているプロジェクトをDocker化する操作
既存のRailsプロジェクトがprojectAとして存在しているのを例に説明します。先ほど紹介した新規プロジェクト作成と被る部分もありますが、「それは前の章を見てね」だと読みにくくなりそうなので、冗長になることを承知でエラーは省きながら同じ手順も記述します。
まず、projectAのフォルダ名をwebに変更し、新しく作ったprojectAというフォルダの中に移動します。
mv projectA web mkdir projectA mv web projectA
projectAに入り、今までのprojectAのgitフォルダを、新しいprojectAのルートフォルダに移動します。
cd projectA mv web/.git ./
先ほどのプロジェクトを新規作成する説明でも紹介したのと同じDockerfile、docker-compose.yml、.gitignoreを作成します。
既にRailsプロジェクトができているので、Gemfileの作成は不要です。
projectA/Dockerfile
FROM ruby:2.5.3 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /web WORKDIR /web ADD web/Gemfile /web/Gemfile ADD web/Gemfile.lock /web/Gemfile.lock RUN bundle install ADD web /web
projectA/docker-compose.yml
version: '3' services: db: image: mysql command: mysqld --default-authentication-plugin=mysql_native_password environment: MYSQL_USER: root MYSQL_ROOT_PASSWORD: password ports: - '3316:3306' volumes: - ./db/mysql/volumes:/var/lib/mysql web: build: . command: bundle exec rails s -p 3000 -b '0.0.0.0' volumes: - ./web:/web ports: - "3000:3000" depends_on: - db
projectA/.gitignore
db/
ここまでできたらこのようなフォルダ構成になります。
projectA |- web: Railsプロジェクト |- Dockerfile |- docker-compose.yml |- .gitignore |- .git
Dockerを通してMySQLに接続するために、Railsのdatabase.ymlのパスワードとホストを下記のように変更します。
projectA/web/config/database.yml
# password: password: password # host: localhost host: db
上記のdatabase.ymlの変更は、sedコマンドを利用して下記のようなコマンドでも行なえます。
sed -i -e 's/password:$/password: password/g' web/config/database.yml sed -i -e 's/host: localhost$/host: db/g' web/config/database.yml
MySQLコンテナ初期化のために、ビルドして実行した後にコンテナを終了します。
docker-compose build docker-compose up docker-compose down
MySQLにRailsのDBを作ります。
docker-compose run web rake db:setup
以上の操作でRailsのプロジェクト作成とDBの初期化ができました。
下記のコマンドでRailsとMySQLのコンテナを動かします。
docker-compose up
上記のコマンドを実行している状態でブラウザから http://localhost:3000 にアクセスすると、Railsアプリのトップページを確認できます。
上記の.gitignoreを作成してから下記のようなコマンドでgitprojectを開始すれば、必要最低限のものだけがgitの管理対象になって良いと思います。
git init git add . git commit -m 'Initial commit'
既存のRailsプロジェクトをMySQLのDockerプロジェクトに変更できました。
開発に参加する人が行う操作
MySQLコンテナ初期化のために、ビルドして終了します。docker-compose build docker-compose down
RailsのDBを作成します。
docker-compose run web rake db:setup
RailsとMySQLを動かします。
docker-compose up
上記のコマンドを実行すると、 http://localhost:3000 にアクセスしたら、Railsが動いていることを確認できると思います。
この状態になれば、webフォルダのRails関係のファイルを編集するなど、開発が行えると思います。
開発時に利用するであろうコマンド
コンテナが動いているときはexec、動いていなければrun
「docker-compose up」や「docker-compose start」などで、コンテナが既に動いている場合docker-compose exec ..例:
docker-compose exec rake db:migrate
コンテナがまだ動いていない場合
docker-compose run ..例:
docker-compose run rake db:migrate
これより先の例はrunコマンドを使いますが、コンテナが動いているなら上記の例のように「exec」に置き換えられます。
「rails」コマンドを実行する
docker-compose run web rails ..例:
docker-compose run web rails g model user name:string
「rake」コマンドを実行する
docker-compose run web rake ..例:
docker-compose run web rake db:migrate
MySQLに入る
rakeのdbconsoleを利用します。docker-compose run web rake dbconsole
コンテナをビルドしなおす
Gemfileを更新した後などに実行します。自分の環境では「docker-compose build」だけでは、下記のエラーが発生することがありました。
db uses an image, skipping Building web Traceback (most recent call last): File "site-packages/docker/utils/build.py", line 96, in create_archive PermissionError: [Errno 13] Permission denied: '/home/asuki/gitprojects/rails-docker-practice/db/mysql/volumes/ca-key.pem' During handling of the above exception, another exception occurred: Traceback (most recent call last): File "bin/docker-compose", line 6, in File "compose/cli/main.py", line 71, in main File "compose/cli/main.py", line 127, in perform_command File "compose/cli/main.py", line 282, in build File "compose/project.py", line 378, in build File "compose/service.py", line 1067, in build File "site-packages/docker/api/build.py", line 154, in build File "site-packages/docker/utils/build.py", line 31, in tar File "site-packages/docker/utils/build.py", line 100, in create_archive OSError: Can not read file in context: /home/asuki/gitprojects/rails-docker-practice/db/mysql/volumes/ca-key.pem [32413] Failed to execute script docker-compose
上記の対策として、sudoを付けてビルドを実行する
sudo docker-compose buildもしくは、dbフォルダの所有権を変える
chmod $USER:$USER -R db docker-compose buildのどちらかでビルドできました。
ビルド時に発生するエラーの回避方法について、もっと良いやり方がありましたら教えていただけると嬉しいです。
まとめ
MySQLに関連するエラーに戸惑いましたが、DockerでRailsプロジェクトを動かし、gitで管理できるようになりました。何かの参考になれば嬉しいです。
なお、記事の内容に誤りや不備があったり、もっと良い方法がありましたら、情報をいただけるとありがたいです。
参考
[Rails] DockerでRails + MySQLの開発環境をつくる手順今更だけどdocker composeのベストプラクティス
更新履歴
2019/02/18 MySQLコンテナ初期化の手順にdocker-compose upコマンドを追加しました。2023/05/12 著作権侵害警告を受けたので、ロゴ画像の利用を止めました。
0 件のコメント :
コメントを投稿