2016/03/13 13:04:15

Dockerを使ってwordpressのテーマをデータコンテナとして配置してみる


Warning: Attempt to read property "post_excerpt" on null in /home/kpkyvkzp/public_html/unskilled.site/wp-content/themes/unskilled2/content-header-eyecatch.php on line 5
目次(クリックするとジャンプします)
  • 1:WordPressをコンテナで
  • 2:テーマのデータコンテナ化
  • 3:CentOS7にDockerを導入する。
  • 4:WordPressをコンテナとして起動する
  • 4.1:デプロイ用ディレクトリを作る
  • 4.2:データコンテナを作る
  • 4.3:データベースコンテナを作る
  • 4.4:WordPressコンテナを作る
  • 5:補足・ハマったところ
  • 5.1:データボリューム・データコンテナとホストのディレクトリやファイルの所有者について
  • 5.2:オプションでボリュームを読み込み専用にした場合
  • 5.3:所有者のテスト
  • 6:後記

WordPressをコンテナで

CMSといったらやっぱりWordPress。ブログ構築・サイト構築はもちろん、簡易会員管理システムや予約システムなどいろいろ汎用的につかえるので、@MINOはフレームワーク的に活用させてもらっています。

今回はDockerにてWordPressを稼働させようと思います。

  • 環境
  • 作業マシン GNU/Linux debian8
  • サーバ conohaクラウド
  • CPUコア 2Core
  • メモリ 1GB
  • ストレージ50GB
  • OS CentOS7.2
  • チャレンジ内容
  • CentOSにDockerの導入
  • Docker経由でWordPressの導入
  • テーマのデータコンテナ化

テーマのデータコンテナ化

今回のチャレンジでは開発のしやすさを意識した構成を考えています。WordPressでカスタマイズするというのはテーマをいじることがほとんどかと思います。

テーマの開発とデプロイ(サーバへの配置)がやりやすいと開発効率も上がるはず。

具体的に言うと

/var/www/html/wp-content/themes/my-thema

をデータコンテナ化します。このディレクトリはテーマディレクトリのデフォルト位置なので、

こうしてmy-themeディレクトリを分離することで、テーマを管理しやすくします。

このデータコンテナは別途、サーバ(Dockerホスト)上の別なディレクトリにバインドしています。このディレクトリにGitHub経由で開発したファイルをcloneで持ってくるなりpullなりすることにより自動的にデプロイが可能になります。

公式のWordPressのDockerfileではVOLUMコマンドで/var/www/htmlが作られています。

これはドキュメントルート(サイトの公開用のディレクトリ)として使われるディレクトリで、Dockerfileの記述上、ここにWordPressのファイルがコピーされるように設定されています。

なので、WordPressコンテナをrunした段階で/var/www/htmlがつくられ、それ以下のwp-content/themesが存在していることなります。

CentOS7にDockerを導入する。

Dockerのインストールに関しては別記事にまとめましたので参照してください。

WordPressをコンテナとして起動する

デプロイ用ディレクトリを作る

サーバ(Dockerホスト)にテーマをデプロイするディレクトリを作ります(ディレクトリは任意でOKです)。

$ mkdir /home/hoge/deploy/

データコンテナを作る

データコンテナを作ります。先ほど作ったデプロイ用ディレクトリをバインドしたボリュームを持ったデータコンテナです(ややこしい)。

docker create --name thema -v /home/hoge/deploy:/var/www/html/wp-content/themes/my-thema busybox

データコンテナは起動している必要がないので、runではなくcreateでOKです。

このデータコンテナには/var/www/html/wp-content/themes/my-themがボリュームとして作られているわけです。

データベースコンテナを作る

WordPressコンテナに必要不可欠になるデータベースコンテナ(MySQLコンテナ)を作ります。

$ docker run -d --name db -e MYSQL_ROOT_PASSWORD=password -e MYSQL_DATABASE=db mysql

WordPressコンテナを作る

最後に、データコンテナをバインドし、データベースコンテナをリンクしたWordPressコンテナを作ります。

データコンテナを--volumes-fromオプションでバインドして、--linkオプションでMySQLコンテナをリンクし、必要な情報をeオプションで指定します。例ではコンテナの名前をwpにしています。

データベース関連の指定を行わないと(-eオプションで指定しているもの)エラーになってrunは失敗します。

$ docker run -d -p 80:80 --volumes-from thema -e WORDPRESS_DB_HOST=172.17.0.2:3306 -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=password --name wp --link wpdb:mysql wordpress

上記の例だとipなどがハードコードになっていますので、コマンドに汎用性がありません。なのでもう少しスマートに書く方法として環境変数を使ったほうが良いかもしれません。今回の例では以下の様になります。

$ docker run -p 80:80 --volumes-from thema -e WORDPRESS_DB_HOST=$TESTDB_ENV_MYSQL_ROOT_PASSWORD -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=$TESTDB_ENV_MYSQL_ROOT_PASSWORD --name wp --link wpdb:mysql wordpress

$TESTDB_ENV_MYSQL_ROOT_PASSWORD$TESTDB_ENV_MYSQL_ROOT_PASSWORDはMySQLコンテナからWordPressコンテナに出力された環境変数です。こっちのほうがスマートです。

-pオプションでポートのバインドを行っています。コンテナのport80をホストのport80につないでいるような感じです。ホストのport80にリクエストがあったらコンテナのport80が応答するようになります。

--volumes-from themaを指定することで、WordPressコンテナの/var/www/html/themesに先ほど作ったデータコンテナがバインドされます。

かつ/var/www/html/themesはサーバ(Dockerホスト)の/home/hoge/deployにバインドされているので、このディレクトリにテーマファイル(ディレクトリ)をpullしてくるなりすることで、コンテナの中にテーマが追加することができます。

これでサーバに直接wordpressをインストールした時の感覚と同じように扱うことができます。

補足・ハマったところ

docker: Error response from daemon: failed to create endpoint wp on network bridge: iptables failed: iptables --wait -t nat -A DOCKER -p tcp -d 0/0 --d
port 80 -j DNAT --to-destination 172.17.0.3:80 ! -i docker0: iptables: No chain/target/match by that name.

ポートにバインディングしようとたらできない…。ずっとこんなエラーがでてしまう。

dockerのポートマッピングはポートフォワーディングを使っていると理解しているので、それほど難しいものではないと思っていました。

どうやってもできず、いろいろ検索しましたがクリティカルな情報をえられず息も絶え絶えに。

結局解決したのが

  • DockerEnginの再起動

というオチ。

なんだそりゃ。

再起動した後は今のところ上記のエラーはでていません。

データボリューム・データコンテナとホストのディレクトリやファイルの所有者について

コンテナが展開したディレクトリはあくまでもコンテナの持ち物になるようで、ホスト側からはroot権限でしか触ることができないようです。

しかしコンテナには存在せず、データコンテナを介してかデータボリュームを介してホストから作られたディレクトリはrunを実行したユーザの所有になっていました。

今回の例で言うと

/var/www/html/wp-content/themes/my-thema

はもともとコンテナに存在しないので、run時に作られるディレクトリとなります。このディレクトリはrunを実行したホストのユーザが所有権を持つことになります。

しかし

/var/www/html/wp-content/themes

はもともとコンテナに存在する(WordPressのDockerfileの処理上で作られるディレクトリで所有者はwww-dataになるよう記述されている)ので所有者はあくまでもコンテナに存在するユーザ(今回の場合はwww-data)になるようです。

/var/www/html/wp-content/themesとバインドされたホストディレクトリを覗くとWordPressコンテナ側で作られたファイルやディレクトリは所有者が数字になっているかと思います。

@MINOの環境では33になっていました。これはWordPressコンテナ内のwww-dataユーザのuidと一致します。

drwxr-xr-x 6     33     33   99  2月  3 02:12 .
drwxrwxr-x 3 hoge hoge   17  2月 25 12:41 ..
-rw-r--r-- 1     33     33   28  6月  6  2014 index.php
drwxr-xr-x 7     33     33 4096  2月  3 02:11 twentyfifteen
drwxr-xr-x 9     33     33 4096  2月  3 02:11 twentyfourteen
drwxr-xr-x 8     33     33 4096  2月  3 02:12 twentysixteen

そのため/var/www/html/wp-content/themesをバインドした場合、ホストディレクトリにroot以外のユーザ権限でgit cloneを行っても失敗します。

例えばこう。

git clone https://github.com/hoge/my-thema.git
fatal: could not create work tree dir 'thema'.: ????????

??????という気味の悪いものが出力されていますが、おそらくこれはpermission deniedのことだと思います。文字化けなのかな。

さらにはコンテナを止めた後にもバインドしていたホストのディレクトリの所有者はコンテナ側のユーザのままになっています(ボリュームの書き込み権限を与えた場合)

roオプションでボリュームを読み込み専用にした場合

/var/www/html/wp-content/themes
docker run -i -t -d -p 80:80 --volumes-from dc01:ro -e WORDPRESS_DB_HOST=172.17.0.2:3306 -e WORDPRESS_DB_USER=root -e WORDPRESS_DB_PASSWORD=pass --name wp --link db:mysql wordpress

上記のようにroオプションを付けてボリュームコンテナを読み込み専用としてバインドした場合、/var/www/html/wp-content/themesにバインドしたホストのディレクトリの所有者はホストのユーザとなりました。

読み込み専用にしたことで所有者の書き換えが行われなかったためかと思います。

しかし困ったことに、/var/www/html/wp-content/themesに展開されているべき公式テーマも無い状態になります。

読み込み専用にしてしまったため、/var/www/html/wp-content/themesにはファイルを書き込むことができなかったということなのだと思います。

所有者のテスト

以下のようにしてデータコンテナを作り、CentOSコンテナの/varディレクトリにバインドするようにしてみました。

docker create -v /home/hoge/var/:/var --name data busybox
docker run -it --volumes-from data --name os centos /bin/bash

[root@0fa622460197 /]# ls -al
total 32
drwxr-xr-x  17 root root  4096 Feb 25 07:11 .
drwxr-xr-x  17 root root  4096 Feb 25 07:11 ..
-rwxr-xr-x   1 root root     0 Feb 25 07:11 .dockerenv
-rwxr-xr-x   1 root root     0 Feb 25 07:11 .dockerinit

...         〜中略〜

drwxr-xr-x  13 root root   143 Feb 17 16:51 usr
drwxrwxr-x   2 1000 1000     6 Feb 25 07:09 var

この場合、CentOSコンテナの内部から確認すると/varディレクトリのみ1000というユーザが所有者になっています。これはホスト側のrunを実行したユーザのuidに一致します。

このようにイメージ側で所有権の変更がされない場合、バインドしたディレクトリの所有者はホスト側のユーザとなるようです。

rootになるかsudoを付けてcloneなりpullなりをすればいいのですが、果たしてそれで良いのかは@MINOにはわかっていません。

jenkinsさんらCIツールと連携するとなるとホストマシンへのrootでのログインはセキュリティ上避けたいですし、sudo付きのコマンド実行って@MINOにはまだ難しく思える点も多々あります(自動的にパスワードを入れる処理が難しい)。

本来であればWordPress以下のファイルはすべて、WordPressコンテナに存在するwww-data(apacheの実行ユーザ)というユーザの所有になっているべきかと思います。

所有者がwww-data以外でもテーマ自体は動くので問題ないといえばそれまでですが、動いているからよしとすべきなのか、ちょっと不整備な感じがして気になる部分です。

これはおそらくDockerfileにて所有者ないしは所有グループについての処理をカスタマイズする必要があるのではないかと思います。

この辺の処理はまだ@MINOの経験値だと解決できそうにないのでもっと勉強してみたいと思います。

後記

後からテーマを追加した場合どうするかの解決方法が思いついていません。wordpressコンテナに後付でデータコンテナをバインドできのかな。

もしできない場合はcontentディレクトリ自体をデータコンテナにして、入れ子状態に方法もあるかも。それであれば一度作ったwordpressコンテナを解体せずにデータだけ入れ替えができるかも。