はじめに
DockerにはDockerHubという便利なイメージのレポジトリなんていうのがあります。
必要なイメージは大概ここに落ちていて、PHPやMySQLの公式イメージもあったりします。
しかし! …… 公式イメージのみで今までと同じようなWordPressの環境を作ろうとするとハマります。
具体的にはホストディレクトリにWordPressのフォルダごと入れた環境をDocker内から参照し、Apacheで実行する
というものです。
ネットを漁ってみても、特にホストディレクトリへの書き込み権限まで踏み込んだリファレンスは少ないように感じます。(コンテナ内にWordPressを入れる例は多々あり)
下記に構築の要件をまとめてみたいと思います。同じことをしたいなと思っている方は参考にしてみてください・
要件
- Dockerコンテナにて公式イメージ PHP 5.6 (Apache)を実装
- Dockerコンテナにて公式イメージ MySQL 5.7を実装
- データの永続化、メンテナンスの容易さから Apacheはホストディレクトリの /docker/www をwebrootとして参照する
- MySQLも同様にホストディレクトリの/docker/lib/mysql にデータベース(/var/lib/mysql 以下)を書き込むことにする
- ホストにはApacheとか入れてません(CoreOS使用)
- phpMyAdminとかはセキュリティ的に使わず、HeidiSQLなどでデータベースにアクセスする方法を考えます。
要はホストディレクトリにデータをぶち込みデータを永続化にする設定にします
MySQL編
##公式イメージをpullする
まず、公式イメージをレポジトリからpullします。
https://hub.docker.com/_/mysql/
docker pull mysql:5.7
これでイメージは準備できました。
設定(my.cnf)を少し書き換える
MySQLのデータを永続化させるためにはホストディレクトリに/var/lib/mysql 以下のデータを
書き込ませる必要がありますが、デフォルトの設定だとうまくいきません。そこで追加のcnfデータをかきます。
まずホスト側でDocker作業用ディレクトリ /docker/ を作り、
その中にmysqlディレクトリを作成し、(ここら辺は任意のディレクトリでよいです)
起動時に追加した設定ファイル(cnf)を読み込ませることにします。
追加cnfデータadd.cnfは以下のように書きます。(名前も任意です。)
[mysqld]
user = root
character-set-server=utf8
userはmysqlの実行ユーザに関する項目でデフォルトはmysqlとなっています。
しかし、ホストディレクトリにデータを書き込む際は実行ユーザがそのままだと書き込めないので(実行ユーザーをmysqlにしたまま書き込む方法もあり 後述で検証)rootの方がよいです。
character-set-server=utf8 もついでに設定しておきます。 (デフォルトではlatin)
コンテナ起動
ではコンテナを起動します。
あらかじめ、作ったadd.cnfを読み込ませ、さらにコンテナ側の/var/lib/mysql と 新たに作成した /docker/lib/mysql とファイル共有させます。mkdirであらかじめ作っておいて下さい。こうすることで、コンテナを消してもデータベースの内容とかが永続化します。
docker run --name mysql -v /docker/mysql:/etc/mysql/conf.d -v /docker/lib/mysql:/var/lib/mysql -e MYSQL_ROOT_PASSWORD='password' -d mysql:5.7
ファイル共有の設定は -vオプションで コンテナ側のディレクトリ**:(コロン)**ホスト側のディレクトリ で実現できます。
-eオプションで環境変数を流し込むことができるのでついでにmysqlのルートパスワードを設定しておきます。
'password'に任意のパスワードを入れて下さい。 &などがパスワードに入っている時はクオーテーションマークで囲ってあげれば大丈夫
のちのち、PHPとMySQLを連携させたり、外からコンテナ内のMySQLにアクセスするためにも--name はつけておいた方が便利です。
確認
起動したか確認します。
coreos@coreos ~ $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7b55a5759557 mysql:5.7 "/entrypoint.sh mysql" 4 minutes ago Up 4 minutes 3306/tcp mysql
mysqlが起動していることが確認できました。
ちなみにホスト側に3306ポートがバインドしていないのでまだ、外からSQLを流し込むことはできません。
PHP-Apache 5.6 編
一筋縄ではいかないPHP編です
MySQLのコンテナでは公式イメージを使い、MySQLの実行ユーザを簡単にrootへ変更できました。
しかし公式イメージのPHP-Apacheでは実行ユーザwww-dataからrootに変えるのが難しいのです!
これでは、ホストディレクトリにApacheがファイルを書き込むことができません。WordPressではプラグインやテーマの更新の際、
Apacheが自らWordPressのデータを書き換えにいきます。 書き換え権限がないディレクトリの場合は更新がうまくできません。
そこで、ホストディレクトリをApacheが書き込み可能な状態で運用する方法をいくつか考えていきたいと思います。
- その一 DockerfileでUbuntuから作り上げる (真のインフラエンジニアコース)
- その二 ホストディレクトリをどんなユーザーでも書き込めるようにしてしまう。(パーミッションガバガバコース)
- その三 ホスト側にユーザーwww-dataを作成してしまう (変則コース)
それぞれ見ていきましょう
その一 DockerfileでUbuntuから作り上げる (真のインフラエンジニアコース)
DockerにはDockerfileというとても便利な機能があります。
公式PHP-ApacheイメージではすでにApacheの実行ユーザがwww-dataで作りこまれているので、なかなかこの牙城を突き破る(rootにする)のはめんどくさいです。いっそ、UbuntuなどのイメージにApacheやPHPなどをぶち込む設定をDockerfileに書くのも手かと。
その際、Dockerfileに
ENV APACHE_RUN_USER root
ENV APACHE_RUN_GROUP root
の項目を入れる か apache2.confを書き直したものをCOPYコマンドで書き換えるという作戦ができそうです。
UbuntuからPHPが動く環境を作る方法はネットにリファレンスが転がっているのでググってください。
その二 ホストディレクトリをどんなユーザーでも書き込めるようにしてしまう。(パーミッションガバガバコース)
セキュリティ的にもガバガバですし、なんかもう全てをあきらめた感がすごいのですが、
ホストディレクトリのパーミッションを777にして全ユーザが読み書きできるようにするのも作戦です。
男ならこの方法も潔いでしょう… 上司に怒られそうですが。
chmod 777 -R /docker/www
その三 ホスト側にユーザーwww-dataを作成してしまう (変則コース)
今回の実装ではほかにApacheが動く環境がないことが確認できています。
そこでコンテナ側の実行ユーザ www-dataをホスト側に作ってしまって、ディレクトリのownerもwww-dataにしてしまいましょう。
ポイントはwww-dataのuidをコンテナ側とそろえておくことです。
今回はこの方法を採用したいとおもいます。
MySQL用イメージ作成
公式イメージのpull
まずはphp-apache5.6公式のイメージをpullします。
https://hub.docker.com/_/php/ ←こ↑こ↓
docker pull php:5.6-apache
MySQLが動くように新規イメージを作る(Dockerfile編)
公式PHPイメージではphp-extがありますのでそれを使ってMySQL関係をインストールしてしまいます。
vimはログを確認するために入れたけどいれなくてもいいです。
FROM php:5.6-apache
RUN apt-get update && \
apt-get install -y vim && \
docker-php-ext-install pdo_mysql mysqli mbstring
今回はこのDockerfileを /docker/php に入れましたのでビルドしていきたいと思います。
docker build -t php:usingmysql /docker/php
タグはusingmysqlにしました。
PHPのコンテナを起動する
作ったイメージを利用してphp-apacheのコンテナを起動します。
要件通り、ホストディレクトリ /docker/www と コンテナの /var/www/html を結びつけています。
またすでに起動しているmysqlコンテナとリンクを組んでます。これでMySQLのコンテナはホスト名 mysqlとしてアクセスできます。
docker run -p 80:80 -p 443:443 -v /docker/www:/var/www/html --link mysql:mysql --name php -d php:usingmysql
確認
coreos@coreos / $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
af7bcbd2b8d6 php:usingmysql "apache2-foreground" 4 seconds ago Up 3 seconds 0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp php
7b55a5759557 mysql:5.7 "/entrypoint.sh mysql" 2 hours ago Up 2 hours 3306/tcp mysql
無事起動しました。
phpコンテナ内のwww-dataのuidとか確認する
PHPの公式イメージはDebianが元になっているのでおそらく(確実に)www-dataがapacheの実行ユーザだと考えられますが、一応確認してみたいと思います。
起動しているコンテナのbashを起動してコンテナ内に入ることにします。
docker exec -ti php bash
-ti オプションをつけると標準出力にダイレクトします。
コンテナ内でwww-dataの詳細を確認します。
root@af7bcbd2b8d6:/var/www/html# id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
やっぱりwww-dataがApacheの実行ユーザーで間違いないと思いますし、uidは33でした。
phpコンテナ内での作業
MySQLコンテナのlinkが上手くいっているか確認
phpコンテナに入っているついでにMySQLへのlinkが上手くいっているか確認しておきましょう。
リンクがうまくいっているなら/etc/hostsにコンテナのIPが入ります。
root@af7bcbd2b8d6:/var/www/html# cat /etc/hosts
172.17.0.68 af7bcbd2b8d6
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.31 mysql 7b55a5759557
172.17.0.31 mysql
172.17.0.31 mysql.bridge
172.17.0.68 php
172.17.0.68 php.bridge
MySQLのコンテナに172.17.0.31 がふられていました。(172.17~ はDockerのIPみたいです)
環境によってIPアドレスは変化するので毎度確認しておいて下さい。
###外からMySQLにアクセスする方法を考える
先ほど確認したIPアドレスをつかって外からMySQLにアクセスする方法を考えます。
方法は2通りです。
- phpMyAdminをつかう
- SSHトンネルを使う ←今回はこっち
####SSHトンネルを使ったデータベースアクセス(Docker編)
Windowsの方であればHeidiSQL が便利です。
冗長な内容なので飛ばして構いません
ネットワーク種別をMySQL (SSH tunnel)にして
ホスト名は先ほど調べたMySQLに振られたDockerのIPを
ユーザー名は root
パスワードは 先ほど設定したMySQLのルートパスワードを入れます
SSHトンネルを使うにはplinkが必要です。PuTTYが入っている人は再度インストールする必要はないです。
SSHホストとポートはDockerの動いているサーバのものを指定
ユーザー名、パスワードもホストサーバのものを利用します。
鍵方式のログインも可能です(OpenSSH形式のものはPuTTY形式への変換が必要です)
ローカルポートには利用していないポートを指定しておけばいいです。
これでアクセスできます。SSHトンネルでMySQLにアクセスする方法は便利なのです!
ホストに www-data を設定する
ユーザー www-data を作る
もう少しで終わるのでがんばっていきましょう。
コンテナからexitで抜けた後ホスト側でユーザー www-data を作ります。
sudo useradd -M -u 33 -g docker www-data
-Mオプションはホームディレクトリを作成しないオプションです。
-u でuidを設定します。 先ほど確認したら33だったので33にしました。
確認します
coreos@coreos / $ id www-data
uid=33(www-data) gid=233(docker) groups=233(docker)
/docker/www の所有ユーザーをwww-dataにする
sudo chown -R www-data /docker/www
これで終わりです。
おわりに
あとは/docker/www に WordPressを入れれば完成です。
WordPressのデータベースアドレスはmysqlにしておけば大丈夫です。
これだけです!?ふざけるな!大変だったぞ!
以上です。