About
そろそろやっておきたいと思ったので試しました。
環境
$ docker -v Docker version 1.13.1, build 092cba3 $ docker-compose -v docker-compose version 1.11.1, build 7c5d5e4
検証
基本的にドキュメントを見ながら作りました。アレンジした部分とかもあったので、一部修正しつつやりました。
Quickstart: Compose and Rails - Docker
適当なRailsアプリを作る
db接続必須なアプリを作ります。
$ gem install rails $ rails new . -d postgresql $ rails g scaffold Member name:string comment:text
試しにローカルで動かすには
$ rails db:setup $ rails s
でサーバが起動します(postgresqlがローカルで動いていれば)。
Dockerfileを作る
次にドキュメント見つつ、dockerファイルを作ります。
FROM ruby:2.4.0 RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs RUN mkdir /myapp WORKDIR /myapp ADD Gemfile /myapp/Gemfile ADD Gemfile.lock /myapp/Gemfile.lock RUN bundle install ADD . /myapp
nokogiriのinstallが長い。。。これでアプリのdocker化の準備ができました。
docker-compose.ymlを作る
次にdocker-compose.ymlを作成します。とりあえず動くレベルであれば下記のようなファイルで出来ました。
version: '2' services: db: image: postgres environment: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres web: build: . command: bash -c "sleep 3 && bundle exec rails db:setup && bundle exec rails s -p 3000 -b '0.0.0.0'" volumes: - .:/myapp ports: - "3000:3000" depends_on: - db
docker-hubで用意されているpostgresはローカル外からの接続はパスワード認証(md5)になっています。事前にユーザを作るためにはenviroment
を設定し、指定したユーザで接続できるようにしておく必要があります。従って、アプリのconfig/database.yml
を修正しておきます。
default: &default adapter: postgresql encoding: unicode database: dockerized-rails_development username: postgres password: postgres host: db
また、先程のcommand
のところでsleep 3
しているのは、db側が起動しきらない状態でdb:setup
が実行されるのを防ぐためです。
https://hub.docker.com/_/postgres/
はまったところ
よくわからないけど、突然動かなくなる現象
コード何も変わってないのになんで動かなくなるの?って現象に複数回遭遇したの辛かったです(ヽ´ω`)
tmp/pids/server.pid
が削除されなくてwebが起動しない(これはまだマシ- webサーバからdbサーバへの名前解決ができなくてpostgresへ接続できなくなる
なんというか、試しに遊ぼうと思ったところでこれ食らうと辛い。下記のエラーはpostgresのimageを1回消したら直りました。
いろいろ調べると根本的な原因は不明なのですが、docker-compose up
時にクラスタ?用のbridgeを作ってそこにエントリを追加することで名前解決できるようですが、そこがうまくいかなくなっていたようです。下記はうまく言っているときのパターンです。
$ docker network inspect dockerizedrails_default [ { "Name": "dockerizedrails_default", "Id": "401cbf3c701784ed8fd9204c621b100204fa71e1030c515ac62a3bf522d0acd4", "Created": "2017-02-13T14:55:07.449826039Z", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": null, "Config": [ { "Subnet": "172.19.0.0/16", "Gateway": "172.19.0.1" } ] }, "Internal": false, "Attachable": false, "Containers": { "7198b19232101a6e9a7d47323671936462b1d84629d8ed23f14edc96f48add27": { "Name": "dockerizedrails_db_1", "EndpointID": "fbbafefd89123131d180a8c783ca5cc432a65eb6ba7a7d243bb0ef1ca1b200bc", "MacAddress": "02:42:ac:13:00:02", "IPv4Address": "172.19.0.2/16", "IPv6Address": "" }, "b7fdfec2847f015975457920c97c6b278e8fc69860ee9b479a3bfdc53480c17c": { "Name": "dockerizedrails_web_1", "EndpointID": "01d495e58753902424cd71ef1564341df48ef0264f804d2bc9f8a73a648fa560", "MacAddress": "02:42:ac:13:00:03", "IPv4Address": "172.19.0.3/16", "IPv6Address": "" } }, "Options": {}, "Labels": {} } ]
なんか名前解決してくれそうなものがありますね。
まとめ
久しぶりにdocker触り始めたので、しっかり基礎からやっていきます!
蛇足
network周りが気になったのでもうちょっと調べました。
$ docker exec -ti dockerizedrails_web_1 ping db PING db (172.19.0.2): 56 data bytes 64 bytes from 172.19.0.2: icmp_seq=0 ttl=64 time=0.073 ms 64 bytes from 172.19.0.2: icmp_seq=1 ttl=64 time=0.105 ms
digをコンテナに入れてみると
root@b7fdfec2847f:/myapp# dig db ; <<>> DiG 9.9.5-9+deb8u9-Debian <<>> db ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13249 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;db. IN A ;; ANSWER SECTION: db. 600 IN A 172.19.0.2
おお、名前引けてる。これはどこで管理しているのか。。。
# cat /etc/resolv.conf nameserver 127.0.0.11 options ndots:0
127.0.0.11っていうのは何やつなんだろう?🤔
きっとlibnetwork当たりでやってるんだろうなってところで一旦諦めました。。。たぶん内部DNSを自前実装しているのかな。
docker/network.go at master · docker/docker · GitHub