タイトルが大げさですなぁ;-)。
前回のエントリで構築した VRF が動作する AlmaLinux 8.7 ですが、その AlmaLinux8 は実は Docker ホストとしても動作しています。
これも、以前のエントリで「Docker Registry を作る。」というのを書いていますが、このホストと同一となります。
今回はこの Docker ホストに Docker コンテナを複数起動して、外部からアクセスできる環境を構築します。
Docker コンテナに対して外部からアクセスするためのポート番号は 80 番 (別に 443 でも良いのだけど、証明書関係が面倒だったので、Port:80 で許してちょんまげ;-) とします。しかし、複数の Docker コンテナが全て Port:80 番で待ち受けるためには NAT 環境では無理です。
今回は Docker ホストとコンテナ間をブリッジで接続して、Docker ホストで利用している外部接続ネットワークをコンテナでもそのまま利用するようにします。
図はこんな感じ。
VMware ESXi に二つの仮想マシンが動作しています。一個は Docker ホストで、もう一個は FreeBSD が動作して MySQL のサービスを他の仮想マシンに提供しています。
で、せっかくなので Docker コンテナがただ HTML なコンテンツを垂れ流す環境を構築してもつまらいないので WordPress が動作する環境を構築したいと思います。
ネタが二つ分の量だけど、大丈夫かなぁ・・。
と、いうことで、まずは Docker ホストの準備から。
とはいいつつ、以前、Docker Registry を作った環境をそのまま利用しています。ただ、 dnf update しているので多少バージョンが上がっているかも;-)。
|
いろいろ端折って、既に dockerd が起動しているものとして話を進めていきます。Docker のインストールと起動については他のサイトを参考にしてください。
1. Docker イメージの作成
|
docker search で AlmaLinux を探して、オフィシャルサイトから pull して、 almalinux8:1 としてタグ付けしました。
このあと、docker run してコンテナの中に入って dnf update して、必要な rpm をインストールして httpd や php もインストールして、もとの Docker イメージを大幅に更新して tag 付けして Docker イメージを完成させます。
この辺り割愛しますが、各自で頑張って Docker イメージを作成してください;-)。
|
apache や php をインストールした新しい almalinux8_wordpress:1 という Docker イメージができました。このイメージをベースに色々やっていきましょう。
2. Docker コンテナで利用するネットワークの準備
次にネットワークの設定を行います。今回は複数の Docker コンテナに Dokcer ホストと同じセグメントを割り当てます。
僕の環境の AlmaLinux 8.7 は VMware ESXi 上で動作しています。そして、ネットワーク構成は前回の「AlmaLinux8 の VRF。」に記載してある以下の構成をそのまま利用します。
つまり、Service-segment 側はウェブアクセスのために利用し Access-Segment は MySQL アクセスで利用します。あ。MySQL サーバは 192.168.52.204 の FreeBSD 上で動作しています。
箇条書きにするとこんな感じ。
- WordPress が動作する予定の Docker コンテナは外部からのアクセスは Port:80 で eth0 側に到達するように構築します。
- その Docker コンテナは外部の MySQL サーバにアクセスするために eth1 のインターフェースを利用します。
- Docker コンテナは二つのインターフェースを持ち、それぞれが Docker ホストからのブリッジで動作します。
- 上記の図では、Server1 が Docker ホストで、Server3 が FreeBSD で MySQL サーバが動作しています。
と、いうような状況ですな。
その VMware ESXi が Docker ホストに接続するポートグループは「セキュリティ」において「無差別モード」「MACアドレレス変換」「偽装転送」の全てを『承諾』に設定します。eth0 と eth1 の二つのポートグループはブリッジインターフェースを利用するので無差別モード(俗に『プロミスキャスモード』と、言いますな)を有効にする必要があります。
VMware ESXi のネットワークの設定もちゃんとしましょう。
3. Docker network でネットワークの作成
と、いうことで Docker コンテナが利用する二つのネットワークを docker network コマンドで作成します。
|
Docker ホストの eth0 の IP アドレスは 192.168.22.217 で、eth1 側は 192.168.52.217 です。
こちらも説明は箇条書きで。
- eth0 の Service-Segment と eth1 の Access-Segment の Docker ネットワークを作成します。
- このとき Docker ホストには docker0 というインターフェースが存在していますが、利用しないのでそのまま存在しつつ、無視して問題はありません。
- NetworkManager でブリッジインターフェースの設定はしません。 /etc/sysconfig/network-scripts/ 配下に ifcfg-br0 などのファイルを置いてもなんの意味もありません。 docker network create コマンドを実行したときに付加するオプションである -o “com.docker.network.bridge.name”=”br0” があるので、既に br0 が存在しているとエラーになります。
- –gateway オプションに指定する IP アドレスは Docker ホストの IP アドレスになります。
- AlmaLinux 8.7 に bridge-utils の rpm はないようなのでソースからコンパイルしてインストールします。
- brctl addif コマンドの実行や eth0 からアドレスを消して br0 にアドレスを付加するなどは全てコマンドで行います。
|
無事に作成できるとこんな感じでしょうか。
ifconfig -a したときには br0 と br1 に IP アドレスが付いていて、eth0 と eth1 には IP アドレスはついていない状態が正解です。
これで Docker ホストとコンテナで同一セグメントを利用する環境が整いました。次にコンテナを run してみましょうかねぇ;-)。
4. Docker コンテナの起動
まず、いきなり WordPress を動かすコンテナを起動するのではなく Docker ネットワークに接続するために docker run してみましょう。
|
今回は箇条書きではなく、ベタガキで・・f(^^;;。
-p 0.0.0.0:80:80 というオプションは指定しません。これ付けると一個の Docker コンテナが Docker ホストの Port:80 を掴んでしまいます。
–net で接続する Docker ネットワークと –ip でDocker コンテナが使用する IP アドレスを指定します。今回は固定 IP アドレスで 192.168.22.222 を利用します。docker network のオプションではレンジとか CIDR を指定することができて DHCP みたいな利用形態もできますが、ここでは割愛します。自分で調べてください。
-v で Docker ホスト側のディレクトリをコンテナ側にマウントしています。 Docker イメージを色々なサービスで使い回すならこれらは外出しした方が良いかなぁ。と、僕は思ったので Docker イメージには組み込んでいません。自分・環境のお好みで設定してみてください;-)。
–log-driver=syslog は syslog 出力するための設定です。 /etc/rsyslog.conf には以下を記載してください。
|
書いたあと rsyslogd を再起動して、ついでに mkdir /var/log/docker してください。
と、いうことで、ここまでは Docker コンテナをブリッジインターフェース経由で外部公開するための起動方法になります。
ただ、これだと MySQL サーバにアクセスできないので、起動した almalinux8_wordpress コンテナに eth1 を生やしてあげるコマンドを投入します。
|
と、いう感じで docker network connect コマンドを実行したので Docker コンテナには二つのインターフェースができました。
eth0 側は Dockerホスト外部から httpd に対してアクセスができていると思います。コンテナ起動時に指定した -v /var/www/html/wordpress:/var/www/html のオプションがありますが、 Docker ホスト側の /var/www/html/wordpress/ ディレクトリ配下に WordPress のコンテンツ一式が既にインストールされていると想定しています。
裏を返すと /var/www/html/wordpress/ 配下のコンテンツを何個かの Docker コンテナに -v でマウントさせると Docker コンテナのみで冗長構成を組むことができるのですな。 eth0 側のインターフェースは docker run 時に –ip で指定する IP アドレスを変えつつ起動したあと DNS ラウンドロビンでも良いし、ロードバランサ配下のネットワークに置いても良い。今まで複数の物理や仮想マシンが担当していた部分を Docker コンテナでマカナエル。と、いうことですな。
あ。ちなみに、僕の場合は WordPress の初期環境一式は FreeBSD の ports からインストールして、 FreeBSD 上の /usr/local/www/wordpress/ ディレクトリごと tar でかためて持ってきました;-)。簡単に初期の環境が整うです。で、 IP アドレスにアクセスすると「さぁ。わーどぷれすをいんすとーるしましょうっ!!」みたいな画面がいきなりでます;-)。
あ。実はエラーになってそう簡単には出ないか・・f(^^;;。
そーそー。注意点が一個。 NetworkManager を利用しないでブリッジインターフェースの設定をしているので、サーバに再起動が入ると設定が全て飛んでしまいます。 Docker ネットワークの設定は Docker が覚えていてくれるんだけど、ブリッジを設定するためのコマンド brctl addif の設定は再起動で消えてしまうので /etc/rc.local などでリカバリーする必要があるです。
5. Docker コンテナ の WordPress 対応
僕は普段 FreeBSD 上で WordPress を動作させているので Linux 上で動作させるには随分難儀なことでして・・。
まずは Docker イメージを作成するとこでイメージに対して httpd とか php をインストールします。そのあと、AlmaLinux8 の rpm の httpd は mod_mpm_event.so で動作しているようで、これをひとまず mod_mpm_prefork.so に変更します。
Docker イメージ内の /etc/httpd/conf.modules.d/00-mpm.conf の設定ファイルの中で LoadModule mpm_event_module modules/mod_mpm_event.so の行をコメントアウトし LoadModule mpm_prefork_module modules/mod_mpm_prefork.so の行を有効化します。
これの変更で一回 docker container commit する必要がありますな。
次に Linux で WordPress を動作させるためには php-fpm というのを起動する必要があるのだそうな。と、いうことで、これも Docker イメージ内でちょっと細工をします。
mkdir /run/php-fpm と chown 48:48 /run/php-fpm ですね。一応、この二つのコマンドを Docker コンテナ内で実行し、docker container commit して環境を整えます。
ふぅ。これで準備整ったかな?と、いうことで、 WordPress が動作する Docker コンテナを起動するスクリプトのまとめとしましょう。
|
こんな感じでしょうか。
ちょっと説明を。
- docker run で Service-Segment の Docker ネットワークに接続し、固定 IP アドレスを利用します。
- -v で Docker ホスト側に用意したコンテンツや設定ファイルを参照するようにします。
- コンテナの syslog を Docker ホスト側に出力します。 docker run の説明はここまで。
- 次に、起動した almalinux8_wordpress に対して、もう一個の Docker ネットワークを接続します。
- その次は nsenter コマンド連発です;-)。 nsenter コマンドは docker exec しなくとも Docker ホスト側から Docker コンテナに対してコマンドを投入できるコマンドです。そのためには当該の Docker コンテナのプロセス番号が必要になるのでそれを取得します。
- コンテナ内に eth0 と eth1 が存在するので default gateway を設定してあげます。一旦削除してから再度設定。みたいな感じです。
- コンテナ内から Docker ホストに対して ping を打つのは、コンテナ起動ごとに MAC アドレスが書き換わるので、上位のルータに対して MAC アドレスの更新をする必要があるためです。ルータ側の MAC アドレス書き換えタイムアウトまで待っても良いですねぇ。根が短気な性分なものでして・・f(^^;;。
- そして、最後の nsenter コマンドは Linux で WordPress を動かすための php のおまじない。 /usr/sbin/php-fpm を nsenter コマンドで起動してあげます。Docker コンテナ内に入って ps -ax すると httpd と php-fpm の二種類のプロセスが一個のコンテナ内で起動する状態となります。つまり、 php-fpm 専用コンテナは不要である。と、いうことです。
例えば、(本来、動かす必要はないのだけど) zabbix_agent なども nsenter で動かすことができます。コンテナ自体が固定 IP を利用しているので Zabbix Agent のポートにもアクセスできるようになります。
これで Service-Segment 側に指定した IP アドレスにウェブブラウザからアクセスすると、WordPress の初期設定画面が表示できると思います。
データベースは MySQL ですが 192.168.52.204 で動作している MySQL サーバへのアクセスは eth1 側を抜けていくので WordPress の初期設定画面で IP アドレス・ユーザ名・パスワードを設定するとアクセスできると思います。
あ。当然、 MySQL 側ではデータベースとアクセス用のアカウントを作成しておいてください。ここでは割愛しています。
さてと。ここまで来てファイアーウォールの設定が一回も登場していません。Docker にはファイアーウォールは必須なので、Docker ホスト側で systemctl start firewalld は必須です。僕の場合は /etc/firewalld/direct.xml で設定していますが、 -i で指定するインターフェース名は eth0 と br0 、 eth1 と br1 の両方を記述する必要があるので、その点は注意してください。
あとは・・。
これで多分大丈夫だと思います。
起動する Docker コンテナは、コンテンツと設定ファイル、そして、ログ出力を -v で Docker ホスト側の情報をマウントしているので docker run 時に違うディレクトリを指定し、他にネットワーク、IP アドレスの設定を変えるだけで一個の Docker イメージで複数の、用途の違う Docker コンテナを起動して同じ仕事をしてくれるようにすることも可能です。んー。 Docker らしい使い方ぁ;-)。
Docker って、基本 NAT が当たり前で、ブリッジインターフェースを利用した環境で『コンテナに対して直接アクセス』。っての、google で検索してもネタ的に今のところはあまり多くないかな。
しかし、実際にコンテナ使い込むとコンテナごとにポート番号変えるのって、なんか納得いかなくて、その先に『こんなんじゃ実際のサービスに提供できないじゃん。』と、いうところからブリッジインターフェースでコンテナに直接アクセス、ロードバランサから見ると仮想マシンもコンテナも同一の扱いのほうが楽じゃん。と、いう発想があります。そのためにはやっぱりブリッジだよねぇ。みたいな。
それにしても、実際に調べてみると Linux の bridge-utils ツール群はヘボいですな。今回、実は IPv6 のことについて全く書いてないんですよ。 bridge-utils は IPv6 側の作りが甘いっ!!
Docker ホストの br0 から出ていく TCP パケットには eth0 の MAC アドレスとか Link Local アドレスが記載されていて、受け取った PC のほうは戻りパケットを送信側 (Docker ホストのこと) の eth0 の MAC アドレスとか Link Local アドレスに投げようとするので、Dockerホスト側の br0 の情報がないために宛先がなくて、実質的に通信できない。と、いう非常にお粗末な状態です。
Docker 自体は IPv6 が使えるかもしれないけど、Linux でブリッジを利用する場合には IPv6 は利用しないほうが良いですな。パケットキャプチャしないと原因が特定できない。ハマる前に IPv6 の利用は諦めたほうが良いかと。
と、いうことで、今回、 Docker コンテナをブリッジインターフェースで、Docker ホストと同一のネットワークで動作させる。と、いうことにチャレンジしてました。 VMware ESXi 上で複数の仮想マシンを起動するがごとく、Docker ホスト上で Docker コンテナをドドドと立ち上げることが可能になったので、サーバ資源がますますギューギュー使える状態になったでしょうかねぇ;-)。
このあと、docker swarm がまだ待っております。が、オーバーレイネットワークがちゃんと動いてくれてないのよ。とほほ・・。orz