wordpress
のサイトヘルスを改善した。
レンタルサーバとかでなく、docker
で運用中なので、資料が少なくて難儀した。
解決すべき問題
主に2つ。他にも更新関係があるが、テーマやプラグインの更新などは、特別な理由がなければ、通知の度に更新しておきたい。
使用中のPHPバージョンは古すぎます
サイトでループバックリクエストが完了できませんでした
と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
SRC
はwordpress
コンテナの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-
の後ろに続くようだ。これで、ネットワーク設定が再生成された場合でも、設定し直せるはずだ。
課題
docker
のnetworking
について勉強不足が実感された。ネットワークについての資料はあまり探していなかったので、今後時間を見つけて探して熟読していくようにしたい。