背景
- Dockerコンテナでrailsの開発環境を作ろうとしています。
- 想定している開発マシンはMacかWindowsです。
- VagrantでCentOS7のVMを動かしてその上でDockerコンテナを作って開発します。
- コンテナで使用するOSもCentOS7とします。
- railsアプリのソースコードはMacやWindowsのファイルシステム上に置いて、ソースコードを編集したら、コンテナを再起動せずにアプリに反映できるようにします。
- MacとVagrant上のVM間はVagrantのshared_folderをtypeをNFSで使用します。
- vboxsfは遅いのでNFSを使用することにしました。
- WindowsとVagrant上のVM間はVagrantのshared_folderをtypeをrsyncで使用します。
- vboxsfが遅いのと、Windowsファイルシステム上のファイルではファイルパーミションを自由に変更できないため。
- Vagrant上のVMとDockerコンテナ間は
docker run -v
でファイル共有します。
- MacとVagrant上のVM間はVagrantのshared_folderをtypeをNFSで使用します。
Dockerコンテナ内でサービスを起動する際の注意点
以下の2点に注意が必要です
- ゾンビプロセスを回収する必要がある
-
docker run -link
によって設定された環境変数を参照する必要がある
ゾンビプロセスを回収する必要がある
Baseimage-docker: A minimal Ubuntu base image modified for Docker-friendlinessの"What important system services am I missing?"の"A correct init process"に詳しい説明がありますので、ご参照ください。
ゾンビプロセス回収の必要性を理解していなかったときに、DockerfileのENTRYPOINTでmonitを起動してそこからunicornを起動するようにしてみたのですが、 monit restart unicorn
とかでunicornを再起動するとゾンビプロセスが残ったままになってしまいました。
しかも docker exec -it コンテナ名 bash
でコンテナに入って kill -9
しても消えない状態でした。
docker run -link
によって設定された環境変数を参照する必要がある
ゾンビプロセスを回収するには systemd
を動かせば良いのではと思い、Dockerfileで CMD ["/sbin/init"]
を試してみました。確かにゾンビプロセスは回収されるようになったのですが、 docker run -link
によって設定された環境変数が参照できないことに気づきました。
例えば、MySQLのコンテナを docker run -p 3306:3306 --name mysql ...
として起動し、unicornのコンテナを docker run -link mysql:mysql ...
として起動すると MYSQL_PORT_3306_TCP_ADDR
といった環境変数が設定されます。
ところが、systemd用に *.service
ファイルを作って、そこでこの環境変数の値を参照しても空になってしまいました。
ふと考えると、そもそもsystemdは子プロセスとして起動することは想定していないので、親プロセスから環境変数を引き継ぐようにはなっていないのではないかと思い当たりました。
Inherit environment variables in systemd Docker container - Unix & Linux Stack Exchangeによると、 init
の引数に systemd.setenv=NAME=VALUE
のように指定すれば環境変数を引き継げるようです。が、 docker run -link mysql:mysql ...
で設定される環境変数は名前も値も動的なので、全て指定するのも大変です。
supervisordなら両方カバーしています
supervisordなら、ゾンビプロセスの回収もできますし、環境変数も引き継ぎます。dockerのサイトにUsing Supervisor - Docker Documentationという記事があるのは知っていたのですが、supervisordを選ぶのはこういう理由があったんですね。
supervisordからunicornを起動するならunicornherderが必要
これはRails - supervisord + unicornでhot restart (deploy) する - Qiitaの記事が詳しいのでご参照ください。
unicornをリロードする際はUSR2シグナルを送るのですが、別プロセスを起動して切り替えるので、supervisordから直接unicornだとまずいことになります。unicornherderを使えば解決します。
VagrantfileとDockerfileのサンプル
https://github.com/hnakamur/vagrant-docker-rails-development-example に置きましたので、よかったらご参照ください。ただし、Windowsでは未検証です。