Help us understand the problem. What is going on with this article?

rails開発環境をdockerで作ったメモ

More than 3 years have passed since last update.

やったこと

railsの開発環境をDockerで立ち上げてみた。

プロジェクトを作る

$ rails new -J --skip-bundle -T -d mysql rails_app

mysqlの起動

mysqlのコンテナを立ち上げておく。
使うのはdocker公式イメージ。
docker-composeとか使うのはとりあえず後。

$ docker run -d -p 3306:3306 --name mysqld -e MYSQL_ROOT_PASSWORD=ルートパスワード mysql

data containerを使うのも後。

db接続の設定

config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8
  pool: 5
  username: root
  password: コンテナ起動時に設定したパスワード
  host: mysqld

hostはmysqlコンテナ立ち上げ時に--nameで指定した名前にしておく。

Dockerfile

railsプロジェクトのトップにDockerfileを置く。

Dockerfile
FROM 2.1.5:onbuild

CMD ["bin/rails", "s"]

これだけ。使いたいversion名にする。CMDにはサーバ起動の命令を書いておく。

bundle install

build時にGemfile.lockが必須となるので、bundle install

build

$ docker build -t rails_app .

dbの作成

$ docker run --rm --link mysqld:mysqld rails_app bin/rake db:create

db:createだけすれば良いので、--rmで終了後にコンテナを自動で削除する。

--linkで、rails_appコンテナ内からホスト名mysqldでmysqlコンテナにアクセスできるように設定。

起動

$ docker run -d --name rails_app --link mysqld:mysqld -p 8080:3000 rails_app

これで、http://192.168.59.103:8080/ にアクセスするととりあえずwelcomeの画面は開ける。IPは、boot2docker ipで出力される値。

ホスト上のソースファイルをマウント

ただし、これだとホスト上でファイルを編集しても、docker imageをリビルドしない限りコンテナ上のアプリに反映されない。これでは開発はままならないので、ホスト上のrailsディレクトリをコンテナにマウントする。

$ docker run -v "$PWD":/usr/src/app --link mysqld:mysqld -p 8080:3000 rails_app

-vオプションで、アプリのコードがあるカレントをコンテナ上のアプリのディレクトリにマウント。

/usr/src/appは、ベースに使っているイメージ2.1.5:onbuildのDockerfileに記載されている、コードのデプロイ先。

scaffold

とりあえずscaffoldで適当なモデルを作り、ホスト上のコードに変更を加える。migrationも合わせてやっちゃう。

$ bin/rails g scaffold item name:string price:integer description:text
$ docker run --rm -v "$PWD":/usr/src/app --link mysqld:mysqld rails_app bin/rake db:migrate

http://192.168.59.103:8080/items にアクセスすると、Item一覧のページが見れるはず。リビルドなしでホスト上の変更が反映できたことがわかる。

データの永続化

アプリは起動したが、mysqlコンテナが消えるとデータも消えてしまうので、data container patternに従ってmysqlコンテナとデータコンテナを分ける。

$ docker create --name mysql_data -v /var/lib/mysql busybox
$ docker run -d -p 3306:3306 --name mysqld --volumes-from mysql_data -e MYSQL_ROOT_PASSWORD=password mysql
$ docker run --rm -v "$PWD":/usr/src/app --link mysqld:mysqld rails_app bin/rake db:create
mysql> show databases;
+-----------------------+
| Database              |
+-----------------------+
| information_schema    |
| mysql                 |
| performance_schema    |
| rails_app_development |
| rails_app_test        |
+-----------------------+
5 rows in set (0.00 sec)

ここで再びmysqlコンテナを再度立ち上げてみる。

$ docker stop mysqld
$ docker rm mysqld
$ docker run -d -p 3306:3306 --name mysqld --volumes-from mysql_data -e MYSQL_ROOT_PASSWORD=password mysql
mysql> show databases;
+-----------------------+
| Database              |
+-----------------------+
| information_schema    |
| mysql                 |
| performance_schema    |
| rails_app_development |
| rails_app_test        |
+-----------------------+
5 rows in set (0.00 sec)

コンテナを再度立ち上げているが、data自体は永続化されたままである。

docker-composeの出番です

ここまで来るといろいろとオプションとか面倒なので、docker-composeを使いたくなる。そこで、railsプロジェクトのトップに以下のファイルを置く。

docker-compose.yml
mysqldata:
  image: busybox
  volumes:
   - /var/lib/mysql
mysqld:
  image: mysql
  volumes_from:
   - mysqldata
  ports:
   - 3306:3306
  environment:
    MYSQL_ROOT_PASSWORD: password
app:
  build: ./
  ports:
   - 8080:3000
  links:
   - mysqld:mysqld
  volumes:
   - $PWD:/usr/src/app

docker-compose up -dで諸々全てが立ち上がる。データコンテナを作り直しているので、
docker-compose runを使ってdbをセットアップ。このコマンドは、

Runs a one-off command on a service.

とマニュアルに書いてあるので、docker-compose.ymlで定義した各service(ymlの第一階層に定義したmysqldとかappなどをserviceと呼ぶ)に対して特定コマンドを実行したいときに使うのだろう。

$ docker-compose run app bin/rake db:create
$ docker-compose run app bin/rake db:migrate

以降、docker-compose upをしても、volumes-fromで指定されたボリュームは保存されるので、mysqlのデータは永続化される。

ymlにMYSQLのパスワードを書いてしまっているのがいけてないなとは思う。が、docker-compose help upを見る限り、起動時に指定できそうな感じはしなかった。

まとめ

dockerを使って、rails+mysqlの開発環境を作ってみた。サンプルプロジェクトは、こちら。
https://github.com/hokuma/docker_rails_sample

これで、

$ git clone xxx
$ docker-compose up -d

だけでとりあえず開発環境は立ち上げられる。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした