■ウェブサーバーはapacheとPHPをyumではなくtarbollからbuildして使っている。ちょくちょくバージョンアップをしたり、テスト実行していたりするのだけど、テスト環境と公開環境を分けるのが面倒で、不安定だったら前のバージョンに入れ替えないとならないし、ちょっと雑な運用という気はしていました。できれば安定した構成でどこかに切り分けて置いておけるといいのですが、サーバーを2つ立てるのも大仰な感じはします。そこまでクリティカルなサーバーでもないし。そんなところで遅まきながらDockerを知ったので、ウェブサーバーをパッケージ化することにしました。
DockerfileにはPHPとapacheの取り込みを記述して、ポートマッピングとコンテンツディレクトリ、ログ出力先のボリュームマウントをオプションで指定してrunさせるようにしました。これは結構簡単。コンテンツとログを後付けでマウントしたのは可変部分だからです。Dockerにおけるコンテナ化は固定部分をあらかじめパッケージにすることであって、仮想環境の代替物ではないと認識しています。
ただ、起動は簡単だったのですが、アクセスログを確認したところ、リモートアドレスが全部172.17.42.1になっていました。Dockerで外部ネットワークからアクセス可能なようにポートマッピングを指定して起動するときはbridgeモードで動作しているのですが、この時ホストOS空間に作られるブリッジインターフェースのdocker0に割り当てられたアドレスが172.17.42.1で、コンテナ内部には172.17.42.1から送られたパケットが届いていると認識されている模様。
パケット転送の一種ですが、転送するときに送信元のアドレスが172.17.42.1に置き換えられてしまうのが原因です。ホストOS空間からdocker0への転送はiptablesで制御されていることは解ったのですが、その先がよく解りません。探り探り設定を変えていたのですが、どうやらdocker run --net="host"で起動すれば良いらしい。Dockerのネットワーク設定の説明ではホストOSのNICをそのまま使うとあるのですが、それでどう使えるのかよく解りませんでした。デフォルトのbridgeモードとhostモードの違いはネットワークの転送がされるかどうかの違いのようです。ただ、そのまま使えるといっても生成されるdocker0に割り当てられるネットワークがクセもので、使いにくいです。
docker0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.17.42.1 netmask 255.255.0.0 broadcast 172.17.255.255
アドレスが172.17.42.1/255.255.0.0になっていて、ホストOSがあるネットワークドメインと合致しません。別途ルーティングを設定するのも大変なのと、うちで使っているブロードバンドルーターのルーティング機能がそこまで賢くないのも問題です。とりあえずdocker0に届けば良いらしいのでものは試しとエリアスを足しました。元のアドレスは副作用が解らないので残します。
ifconfig docker0:1 192.168.0.100 netmask 255.255.255.0
これでdocker0には172.17.42.1と192.168.0.100の二つのアドレスが割り当てられました。
docker0:1: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 192.168.0.100 netmask 255.255.255.0 broadcast 192.168.0.255 ether 56:84:7a:fe:97:99 txqueuelen 0 (Ethernet)
192.168.0.xxはホストOSが乗っているネットワークアドレスにあります。この形だとブロードバンドルータはふつうに扱えます。起動した状態で外部からアクセスすると、ログにはリモートアドレスが出てきました。たぶん、dockerクラスタの使い方としてはhostモードで起動するコンテナにiptablesやfirewalldを入れてルーター化し、ほかのコンテナがルーターコンテナと内部的に通信するような形にするのでしょうね。