docker上で動かすwordpressのサイトヘルスを改善する

wordpressのサイトヘルスを改善した。

レンタルサーバとかでなく、dockerで運用中なので、資料が少なくて難儀した。

解決すべき問題

主に2つ。他にも更新関係があるが、テーマやプラグインの更新などは、特別な理由がなければ、通知の度に更新しておきたい。

  1. 使用中のPHPバージョンは古すぎます
  2. サイトでループバックリクエストが完了できませんでしたREST APIでエラーが発生しました

2は同じ原因で発生しているため、ひとまとめとした。その原因は、Host is unreachable

直し方

1. PHPバージョンの対処

docker環境なので、wordpressのイメージをpullすればいい。一応、wordpress - Docker Hubにて、イメージの確認をしておいた。

確認が済んだら、イメージをpullする。

$ docker pull wordpress:<tag>

<tag>は、適切なものを指定する。基本的には、これまで使ってきたイメージのタグを同じになるはず。自分の今回の場合は、fpm-alpine。イメージサイズが大きくなった。190MB。

あとは、走らせているコンテナで最新イメージを使うようにすればいい。自分の場合は、docker-composeを使っているので、

$ docker-compose up -d

とするだけでOK。あとは、使わなくなった古いイメージが不要なら削除する。

$ docker images  # イメージのリストから、不要なイメージのIDを探す。<none>が目印
$ docker rmi <old_image_id>

これで、PHPのバージョンは新しくなっているはず。ついでに、他のPHPが原因となりそうなサイトヘルスの問題も直ったりする。

2. Host is unreachableの対処

これは結構面倒だった。

問題の切り分け

自環境では、リバースプロキシと他のサービスを別のdocker-composeで運用している。そして、ループバックリクエストREST APIでは、

$ curl -I https://<domain>.tld

のようなことを行うようだ。これはサイトヘルスの項目詳細のところから類推したもの。

そこで、リバースプロキシとwordpressのそれぞれのコンテナにアタッチして、指定ドメインへのncを行ってみると、

$ nc -zv <domain>.tld 443
nc: <domain>.tld (<ip_addr>): Host is unreachable

となり、到達できない。なお、pingは通る。そこで、dockerのホストのログをみてみることにした。 less /var/log/messagesなどでログを閲覧可能だが、エラーログの設定をfirewall-cmdで行う必要がある。(centos7の場合)

$ docker-machine ssh <hostname>
> firewall-cmd --set-log-denied=all  # エラーログを記録するように設定
# この間に`nc -vz ..`を行いエラーを記録する。
> less /var/log/messages
...エラーがある。(後述)

エラーは次のようなものだった。

<date> <hostname> kernel: FINAL_REJECT: IN=br-************ OUT= MAC=<mac_addr> SRC=<container_ip> DST=<this_host_ip> LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=4483 DF PROTO=TCP SPT=36948 DPT=80 WINDOW=29200 RES=0x00 SYN URGP=0 

SRCwordpressコンテナのIPアドレスだった。(dockerから割り振られたもの) また、INは、docker-composeのymlファイルでコンテナ(というかサービス)に当てたネットワークに対応して、dockerによって生成された仮想ブリッジだった。(だと思う。)

以上から、原因は、ホストのbr-************インターフェースに到達したパケットが破棄されてしまうためだとわかった。

対処

破棄されないようにすればいい。

curl - Host unreachable inside Docker container - Stack Overflowが、参考になった。

なお、本来は、docker内部からのパケットは、docker0インターフェースをデフォルトゲートウェイとするはずだが、別の内部へのパケットだから、デフォルトゲートウェイを経由しないのかもしれない。

話を戻して、破棄されないようにするには、dockerのホストで設定を行えばいい。centos7で行っているので、firewall-cmdを使用。参考にあるdocker0だけでは解決しなかった。

firewall-cmd --permanent --zone=trusted --change-interface=docker0  # これは必要ないかもしれない
firewall-cmd --permanent --zone=trusted --change-interface=br-************
firewall-cmd --reload

これで、解決。wordpressコンテナにアタッチして、確認すると、

$ nc -zv <domain>.tld 443
<domain>.tld (<ip_addr>) open

到達可能になっていることが分かる。

修正完了

これにて、作業が面倒なサイトヘルスの問題はすべて解決できた。

仮想ブリッジ関連のホストの設定は、ネットワークのIDが変わったら再び設定する必要がある懸念が存在している。 そのため、br-***のIDの発見方法も記しておく。

$ docker network ls
> ...
> <network_id>        <compose_dir_name>_<network_name>       bridge              local
> ...

この、<network_id>br-の後ろに続くようだ。これで、ネットワーク設定が再生成された場合でも、設定し直せるはずだ。

課題

dockernetworkingについて勉強不足が実感された。ネットワークについての資料はあまり探していなかったので、今後時間を見つけて探して熟読していくようにしたい。

タイトルとURLをコピーしました