この記事はあくあたん工房アドベントカレンダー2022の7日目の記事です

初投稿です

初めまして、腐れ大学生と申します。 某工繊大のソフトウェア工学研究室というところでIaCの品質管理に関する研究をしています。

こういった記事を書くのは初めてで何を書こうか迷ったのですが、自分に書けそうな技術寄りの話として、弊学の施設に関するHPをメンテしていたのでその時に得た経験や感想などを書いていこうと思います。

始まり

ことの発端は、当時担当していた先輩からの引き継ぎでした。その時は、VPS上に建てたWordpressであることと、その先輩が作成したカスタムテーマを使用しているとだけ伝えられ、特に複雑なことをしている印象ではなかったのでとりあえず引き受ける形になりました。

これまでwordpress自体を触ったことがなかったので、どういった仕組みで動いているのか、ディレクトリの構造は?といった基本的なことから調べることになりました。また、カスタムテーマについても特にドキュメントらしいものが残っていなかったので、これについても後々調べることになりました。

プロキシ配下の悲しみ

引き継ぎ時は知らなかったのですが、利用していたVPSは大学が某ネットワーク事業者と契約して提供していたものであり、大学内のネットワークに配置された仮想マシンを利用していました。 そのため外部に接続するためには大学が提供するプロキシを設定する必要があり、普段プロキシ下で作業することが無いため最初に躓いたポイントでした。

Ubuntuでプロキシを設定する

ターミナル上でプロキシを介した通信を利用するためには基本的に次の二つが必要です。

  • 環境変数http_proxyhttps_proxy の設定
  • /etc/apt/apt.confの設定(aptパッケージマネージャーの場合)

.bashrcなど

1
2
export http_proxy="http://proxy.server:8080"
export https_proxy="http://proxy.server:8080"

/etc/apt/apt.conf

1
2
Acquire::http::Proxy "http://proxy.server:8080";
Acquire::https::Proxy "http://proxy.server:8080";

Wordpressでプロキシを設定する

Wordpress単体はプロキシが設定されていなくても動作しますが、外部プラグインのダウンロードやアップデートなどが管理画面上でできなくなってしまいます。 プロキシを設定するにはWP_PROXY_HOSTWP_PROXY_PORTの二つ(パスワードによる認証があればWP_PROXY_USERNAMEWP_PROXY_PASSWORDも)が必要です。また、設定ファイルの場所はドキュメントルートのwp-config.phpになります。

Wordpress http proxy

/var/www/html/wp-config.php など

1
2
define('WP_PROXY_HOST', 'http://proxy.server');
define('WP_PROXY_PORT', '8080');

Docker Composeへの移行

5月頃に大学からPHPのバージョンを上げるように指示が出されました。その時は単純にパッケージのバージョンを上げるだけで済んだのですが、今後phpのメジャーバージョンのアップデートなどで動作に支障が出かねないため、Dockerのオフィシャルイメージを利用することで、責任を押し付けることとバージョンを固定することを考えました。

幸いにも “wordpress docker” などでGoogle検索にかけると無限にサンプルが出てくるので構築自体はとても簡単でした。

Quickstart: Compose and WordPress

wordpressとmariadbによるサンプル

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
services:
  db:
    image: mariadb:10.9.3
    volumes:
      - db_data:/var/lib/mysql
      - ./mariadb/mariadb.cnf:/etc/mysql/mariadb.cnf
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root_password
      MYSQL_DATABASE: wordpress_db
      MYSQL_USER: wordpress_user
      MYSQL_PASSWORD: wordpress_password
    logging:
        driver: syslog
        options:
          syslog-facility: daemon
          tag: docker-service/{{.Name}}/{{.ID}}

  wordpress:
    depends_on:
      - db
    image: wordpress:php7.4-apache
    volumes:
      - wp-content:/var/www/html
      - ./wordpress/wp-content:/var/www/html/wp-content
      - ./wordpress/wp-config.php:/var/www/html/wp-config.php
      - ./wordpress/.htaccess:/var/www/html/.htaccess
    restart: always
    ports:
	  - 80:80
    environment:
      WORDPRESS_DB_HOST: db
      WORDPRESS_DB_NAME: wordpress_db
      WORDPRESS_DB_USER: wordpress_user
      WORDPRESS_DB_PASSWORD: wordpress_password
    logging:
        driver: syslog
        options:
          syslog-facility: daemon
          tag: docker-service/{{.Name}}/{{.ID}}

volumes:
    db_data:
    wp-content:

サンプルと異なるところとして、mariadb.cnf、wp-content、 wp-config.php、 .htaccessをバインドマウントしているところと、rsyslogでロギングをとっています。

mariadbが文字化けする

特に設定しないと文字コードが latin1 になってしまい、文字化けが発生してしまいました。

mariadb.cnfに以下を追記したものを /etc/mysql/ 以下にバインドマウントしています。

1
2
[client]
default-character-set=utf8mb4

カスタムテーマ対応

wp-content/themes/ 以下に使用しているカスタムテーマがあるので、それらをイメージの中に埋め込む、またはバインドする必要があり、今回はコンテナ内に入らなくても編集できるようにバインドを行っています。 同様に、プロキシやリダイレクトの設定を行うファイルwp-config.htaccessについても外から編集できるようバインドしています。

rsyslogによるロギング

サーバーの/var/log/docker以下にログを残したかったので、以下を参考にcomposeとrsyslog.dに設定を記述しログを残すようにしました。

Dockerのログをrsyslogで出力する

/etc/rsyslog.d/10-docker.conf に以下を記述し、rsyslogの再起動を行います。

1
2
3
4
$template DockerLogs, "/var/log/docker/%programname%_%$year%%$month%%$day%.log"

if $syslogfacility-text == 'daemon' and $programname contains 'docker-service' then -?DockerLogs
& stop
1
$ sudo service rsyslog restart

出力ファイルは以下のように保存されていきます。

1
2
3
$ ls /var/log/docker/
docker-service_20221106.log  docker-service_20221112.log
docker-service_20221118.log  ...

HTTPS対応

Dockerに移行して数ヶ月、今度はhttpsに対応するように求められました。 大学のサブドメインを持っていれば一年間有効な証明書がもらえるようになっているため、これを利用することにしました。 docker を使ったサービスではよく certbot/certbotsteveltn/https-portalによるLet’s encryptを利用したものが多く見つかりますが、今回はあらかじめ用意された証明書を用いるため、nginxのリバースプロキシを利用する方法を取りました。

サンプル

jwilder/nginx-proxy を用いてリバースプロキシの構築を行いました。

./certs/ 以下に取得した証明書をドメイン名(www.foo.bar.key, www.foo.bar.crt)に変更して配置することでよしなにしてくれるようになっています

また、ネットワークを作成しその中に先ほどのwordpressコンテナを配置するようにすることで、リバースプロキシ用のcompose.ymlファイルとwordpress用のcompose.ymlに分けることができ、ファイルの責任を分散させています。

reverse_proxy/compose.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
services:
  nginx_proxy:
    image: jwilder/nginx-proxy:1.0-alpine
    ports:
      - '80:80'
      - '443:443'
    volumes:
      - /var/run/docker.sock:/tmp/docker.sock:ro
      - ./certs:/etc/nginx/certs
    logging:
        driver: syslog
        options:
          syslog-facility: daemon
          tag: docker-service/{{.Name}}/{{.ID}}
    restart: on-failure:5
networks:
  default:
    name: my-network

wordpress/compose.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
	 ...
     restart: always
-    ports:
-	  - 80:80
     environment:
       WORDPRESS_DB_HOST: db
	 
	 ...
	 
     logging:
         driver: syslog
         options:
           syslog-facility: daemon
           tag: docker-service/{{.Name}}/{{.ID}}

+ networks:
+   default:
+     external: true
+     name: my-network

 volumes:
     db_data:
     wp-content:   

余談ですが、個人でLet’s encryptによる証明書を利用する場合はsteveltn/https-portal が使いやすくておすすめです。

持続可能なサービス管理に向けて

約1年前からメンテナンスを担当していましたが、3月で卒業してしまうので引き継ぎを行わなければなりません。前任者はドキュメント類をほとんど残さずに去ってしまったので、不幸を繰り返さないためにもいくつか対策を講じました。

この間にもPHPで問い合わせフォームをフルスクラッチで書いていますが、それだけで一つの記事になりそうなので割愛します。

ドキュメントの整備

まずは、基本となるドキュメントを用意し、それを一部非公開Wikiとしてまとめることにしました。ちょうど所属する部署でWikiを整備する話が出ていたのでそれに載せる形で文書をいくつか作成しました。(ちなみに利用したのはwiki.js というOSSのwikiを選びました)

Makefileによるコマンドの隠蔽

dockerの扱いに慣れていない場合を想定し、makeによる命令の単純化を図りました。 例えば、make up_allで全てのコンテナを起動させたり、make restart_allで再起動させるような単純なものですが、typoの回避や不用意なコマンドの実行を避ける狙いでMakefileを作りました。

Makefileの自己文書化

make helpmakeだけでヘルプを出力するように自己文書化を行いました。 いくつか手法があるそうですが、Self-Documented Makefile が有名らしくほぼコピペでヘルプを作成しました。

1
2
3
4
5
6
7
8
9
$ make
status               Print container status
logs_nginx           Logs (nginx_proxy)
logs_wp              Logs (wordpress)
restart_all          Restart all containers
down_all             Stop and Remove all containers
up_all               Create and Start all container
restore_db           Restore wordpress database
prune                Clean build caches

後任者は一応決まっているのですが忙しいらしくサーバーに接続するところまで行ってません。悲しい。

最後に

個人開発だと気にしないプロキシだったり、ちょっと入り組んだ compose.yml を書いたりするなど、いろいろ経験できるところがあって個人的には楽しい仕事でした。

またメンテナンスのしやすさやドキュメントの整備などもあまり意識していなかったので、これを機に人に優しい開発を心がけたいなと思います。

(GoogleでWordpressに関する検索をするとノイズまみれなのはなんとかなりませんかね…)

おまけ

Build Cacheでパンパンになったディスク

$ docker system df docker_df.png

docker builder prunedocker system pruneで定期的に綺麗にしましょう。 記事を書いたのはこの画像を供養したくてしょうがなかったからだったりする