Dockerコンテナを使って 東京都内なら約1分で Wordpress を動かすメモ


今さら驚きもしない Dockerファミリの利用なのですが、 docker-compose のYAMLを作成して、Wordpress と MySQLの構成を約1分で起動する方法についてのメモです。


## 実現したい事

docker-compose の yamlファイルを作成して、Dockerコンテナで Wordpress のサーバーとMySQLデータベースを作成します。 MySQLのデータ領域は、コンテナのホストOSの領域と共有することで、コンテナを削除してもWordpressのデータは保存しておき、何度でも続きから再開できる様にするものです。

![スクリーンショット 2017-09-19 14.19.33.png](https://qiita-image-store.s3.amazonaws.com/0/42829/416b201b-dfd2-ecc1-20ad-5063683e7c5f.png "スクリーンショット 2017-09-19 14.19.33.png")



## docker-compose の定義ファイル

docker-compose の yamlファイルには、mysqlサーバー と wordpress の定義を書いておきます。 db:とwordpress: それぞれにある image は、それぞれ、Dockerストアのリポジトリのオフィシャル・イメージです。 もちろん、自分で Dockerイメージをビルドする事もできますが、Dockerストアには、コンテナ環境用最適化された様々なオフィシャル・イメージが登録されているので、適宜利用して効率を高めるのが良いと思います。

~~~file:docker-compose.yml 
version: '3'

services:
   db:
     image: mysql:5.7
     volumes:
       - "./mysql-data:/var/lib/mysql"
     restart: always
     environment:
       MYSQL_ROOT_PASSWORD: somewordpress
       MYSQL_DATABASE: wordpress
       MYSQL_USER: wordpress
       MYSQL_PASSWORD: wordpress

   wordpress:
     depends_on:
       - db
     image: wordpress:latest
     ports:
       - "8001:80"
     restart: always
     environment:
       WORDPRESS_DB_HOST: db:3306
       WORDPRESS_DB_USER: wordpress
       WORDPRESS_DB_PASSWORD: wordpress
~~~

### MySQL公式コンテナ・イメージ

Docker Hub に登録されている [オフィシャル MySQL コンテナイメージのウェブページ](https://hub.docker.com/_/mysql/) には、コンテナを利用するにあたり、便利な機能や必要な情報が書かれていますから、利用するにあたっては、確認しておく事をお勧めします。 一例として、このウェブページには、利用可能な環境変数と機能について説明があります。 その具体例として、db: の environment: にある環境変数は、初回起動時にパスワードやデータベースを設定するためのものです。
 ここでは、MYSQL_USER と WORDPRESS_DB_USER を一致させ、かつ、MYSQL_PASSWORD と WORDPRESS_DB_PASSWORDを一致させて設定することで、Wordpress サーバーから MySQLサーバーをアクセスできる様になります。

次にvolumesの `- ./mysql-data:/var/lib/mysql` では、先頭のハイフン（マイナス）は、その行が配列の１要素であることを表し、volumes の定義の中に、複数の保存場所の定義が設定できることがわかります。 そして、`:` を境界に、前半がコンテナのホストになっているLinuxのファイルシステムです。　そして、後半がコンテナ上のファイル・システムの位置になります。 この設定では、mysqlのデータ領域をコンテナのホスト側にマップします。 これによって、コンテナを消去しても、データベースの内容は保存されます。 

その他にも、volumes に `- ./data/mysql_init:/docker-entrypoint-initdb.d` をマップしておき、拡張子 .sh や .sql のファイルを置くとで、初回起動時に一回だけ実行して、データをロードし、初期化するなどのバッチを実行することができます。 


### Wordpress公式コンテナ・イメージ

[Wordpress オフィシャル・コンテナ](https://hub.docker.com/_/wordpress/)では、MySQLサーバーとの接続について、そして、機能拡張についての記述があります。 また、Wordpress のイメージのベースOSは、Alpine であることが解ります。 Apline は、非常にコンパクトなOSイメージで、起動時間の短縮や資源の節約に効果が高く、とても利用者が多い様です。

Wordpress のコンテナは、MySQLのコンテナに依存しているわけですが、それを表す表記が `depents_on:` の後に `- db` と設定されている部分です。 この設定により、MySQLを先に起動する様になります。 そして、Wordpressのコンテナでは、ホスト名 'db' で MySQLへアクセスできる様になります。



## 起動過程の様子

前述のyamlファイルのある場所で、`docker-compose up -d` を実行することで、Docker Hubからコンテナをダウンロードして、利用できる様になります。


~~~
$ docker-compose up -d
Creating network "wordpress_default" with the default driver
Pulling db (mysql:5.7)...
5.7: Pulling from library/mysql
aa18ad1a0d33: Pull complete
1324423d52e9: Pull complete
ee152a81987c: Pull complete
b054cf37bcae: Pull complete
eb0cbad90353: Pull complete
710fc2dae571: Pull complete
5ff098d10285: Pull complete
79f9dfa6f98f: Pull complete
5d033d38431e: Pull complete
bdde10ea566e: Pull complete
1a36bb8deb0e: Pull complete
Digest: sha256:dfaabbd5466dafe04c5af0ccb1a43d8a18a9604ac23a95534bb0626b3321034d
Status: Downloaded newer image for mysql:5.7
Pulling wordpress (wordpress:latest)...
latest: Pulling from library/wordpress
aa18ad1a0d33: Already exists
29d5f85af454: Pull complete
eca642e7826b: Pull complete
3638d91a9039: Pull complete
3646a95ab677: Pull complete
628b8373e193: Pull complete
c24a2b2280ed: Pull complete
f968b84cbbbc: Pull complete
74cc3c21f7f1: Pull complete
27fb12209ba4: Pull complete
18cac49c13da: Pull complete
0eb6cc3dbc7d: Pull complete
c4f8e37f04ae: Pull complete
8f39cfb9a6c6: Pull complete
1f35c5fef428: Pull complete
5a7fa3665466: Pull complete
9d4bb117fcc0: Pull complete
2fc5ef806fe5: Pull complete
Digest: sha256:47803b7a0984a500e902ad42b9809d63283b66d72e4fb7cfd824d2c46ee93d7a
Status: Downloaded newer image for wordpress:latest
Creating wordpress_db_1 ... 
Creating wordpress_db_1 ... done
Creating wordpress_wordpress_1 ... 
Creating wordpress_wordpress_1 ... done
~~~


システムの構築が完了したら、コンテナの稼働を確認します。 次のコマンドで、MySQL と WordPress の二つが起動していることが解りますす。 

~~~
$ docker-compose ps
        Name                       Command               State          Ports        
-------------------------------------------------------------------------------------
wordpress_db_1          docker-entrypoint.sh mysqld      Up      3306/tcp            
wordpress_wordpress_1   docker-entrypoint.sh apach ...   Up      0.0.0.0:8001->80/tcp
~~~


## Wordpress のインストールと起動確認

PCのブラウザで `http://localhost:80001/` をアクセスすると 次の様な画面が出ますから、画面の指示に従って、設定を進めます。

![スクリーンショット 2017-09-19 15.38.17.png](https://qiita-image-store.s3.amazonaws.com/0/42829/1dccac66-6776-4b10-4150-b32ebf6ed050.png "スクリーンショット 2017-09-19 15.38.17.png")

設定が完了すると、`http://localhost:80001/` の美しい画面が表示される様になります。

![スクリーンショット 2017-09-19 15.43.43.png](https://qiita-image-store.s3.amazonaws.com/0/42829/0e92c78e-be69-4feb-e52d-ea26ea650f29.png "スクリーンショット 2017-09-19 15.43.43.png")



## コンテナ間のネットワーク

Wordpressの実行中のコンテナには、次のコマンドでログインして、dbサーバーに向けて ping を実行してみます。

~~~
$ docker exec -it wordpress_wordpress_1 bash
~~~

ping の結果から、Dockerコンテナは、172.18 のネットワーク上に存在していることが解ります。 

~~~
# ping db
PING db (172.18.0.2): 56 data bytes
64 bytes from 172.18.0.2: icmp_seq=0 ttl=64 time=0.047 ms
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.065 ms
64 bytes from 172.18.0.2: icmp_seq=2 ttl=64 time=0.062 ms
^C--- db ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.047/0.058/0.065/0.000 ms
~~~


コンテナ間のネットワークがどうなっているか、知るために、dockerコマンドを利用しながら、確認していきます。  この中で、wordpress_defaultが、今回、起動したコンテナが接続されている仮想ネットワークです。

~~~
$ docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
30219220453c        bridge              bridge              local
3b8dfb6dcc75        host                host                local
f9912e005a1f        none                null                local
585a21a1115f        wordpress_default   bridge              local
~~~

この仮想ネットワークに繋がる WordpressサーバーとMySQLサーバー について、`docker network inspect wordpress_default` コマンドを利用して、さらに、確認していきます。 '172.18.0.0/16' という仮想ネットワークが作られており、二つのコンテナのアドレス、及び、デフォルトGWを把握することができます。 

~~~
$ docker network inspect wordpress_default
[
    {
        "Name": "wordpress_default",
        "Id": "585a21a1115f135328f2aa8cfb6fcb58c38175e417c346f2de0c79574afd231d",
        "Created": "2017-09-19T04:21:36.817963302Z",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.18.0.0/16",
                    "Gateway": "172.18.0.1"
                }
            ]
        },
        "Internal": false,
        "Attachable": true,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {
            "0ce550af1dbabc768449d436c6dff57adc448f0a1c6c4f067b17ad71ce64b96f": {
                "Name": "wordpress_wordpress_1",
                "EndpointID": "bbdd3b5af92e1f7616881d474a8eab057ecce01386b496c3ab07c0bfd88e738e",
                "MacAddress": "02:42:ac:12:00:03",
                "IPv4Address": "172.18.0.3/16",
                "IPv6Address": ""
            },
            "a43246787bfe5e0773400112f0752146b92ffb08ddec86366d01d279d5cadb54": {
                "Name": "wordpress_db_1",
                "EndpointID": "e02fa8cd307513d83190485265ceffca40ffa05cbedde193f0926e4f53485dd6",
                "MacAddress": "02:42:ac:12:00:02",
                "IPv4Address": "172.18.0.2/16",
                "IPv6Address": ""
            }
        },
        "Options": {},
        "Labels": {
            "com.docker.compose.network": "default",
            "com.docker.compose.project": "wordpress"
        }
    }
]
~~~

これを図にすると、次の様になります。 もっと知りたい方は、  [Docker container networking](https://docs.docker.com/engine/userguide/networking/) や [参考訳：Docker コンテナ・ネットワークの理解](http://qiita.com/zembutsu/items/1da05cb6a60e1c5acc25) がお勧めです。

![スクリーンショット 2017-09-19 16.03.28.png](https://qiita-image-store.s3.amazonaws.com/0/42829/e04b7aa4-7972-922c-b445-fb4fa7f5316f.png "スクリーンショット 2017-09-19 16.03.28.png")


##  Vagrant の構成ファイル

本題ではないのですが、Dockerの動作環境をPCに作ると、PCの乗り換えや、メモリを圧迫したり、定常的に影響を与える様になりますから、僕の場合は、Docker環境は、Vagrant + VirturalBox 上の仮想マシン上に作成しています。 Vagrantはとても便利な、仮想環境とのユーザーインタフェースで、いつも愛用しています。

以下に、Vagrantfile をあげて、ポイントをコメントします。 






~~~file:Vagrantfile 
# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "ubuntu/trusty64"
  config.vm.network "public_network", ip: "192.168.1.88", bridge: "en0: Ethernet"
  config.vm.network :forwarded_port, host: 3000, guest: 3000
  config.vm.network :forwarded_port, host: 8001, guest: 8001
  config.vm.network :forwarded_port, host: 4040, guest: 4040
  config.vm.provider "virtualbox" do |vb|
    vb.memory = "1024"
  end
  config.vm.provision "shell", inline: <<-SHELL
apt-get update
apt-get install -y make build-essential git libssl-dev X11-apps libxml2 libxml2-dev re2c libcurl3 libjpeg-dev icu-devtools libicu-dev libmcrypt-dev libtidy-dev libxslt1-dev libcurl4-openssl-dev zip zlib1g-dev libbz2-dev libpng12-dev g++ libreadline-dev autoconf ksh unzip default-jre libsqlite3-dev emacs24-nox wget curl llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev

# 
su -l vagrant -c 'echo "# Program Language switch env" > ~/.bash_profile'

#
# Install phpenv & php-build 
#
su -l vagrant -c 'echo "# for PHP" >> ~/.bash_profile'
su -l vagrant -c 'git clone git://github.com/madumlao/phpenv.git ~/.phpenv'
su -l vagrant -c 'git clone git://github.com/CHH/php-build.git $HOME/.phpenv/plugins/php-build'
su -l vagrant -c 'echo export PATH=$HOME/.phpenv/bin:$PATH >> ~/.bash_profile'
su -l vagrant -c 'echo eval "$(phpenv init -)" >> ~/.bash_profile'

#
# Install ndenv & node-build
#
su -l vagrant -c 'echo "# for Node.js" >> ~/.bash_profile'
su -l vagrant -c 'git clone https://github.com/riywo/ndenv ~/.ndenv'
su -l vagrant -c 'git clone https://github.com/riywo/node-build.git ~/.ndenv/plugins/node-build'
su -l vagrant -c 'echo export PATH="$HOME/.ndenv/bin:$PATH" >> ~/.bash_profile'
su -l vagrant -c 'echo eval "$(ndenv init -)" >> ~/.bash_profile'

#
# Install rbenv & ruby-build
#
su -l vagrant -c 'echo "# for Ruby" >> ~/.bash_profile'
su -l vagrant -c 'git clone https://github.com/sstephenson/rbenv.git ~/.rbenv'
su -l vagrant -c 'git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build'
su -l vagrant -c 'echo export PATH="$HOME/.rbenv/bin:$PATH" >> ~/.bash_profile'
su -l vagrant -c 'echo eval "$(rbenv init -)" >> ~/.bash_profile'

#
# Install pyenv 
#
su -l vagrant -c 'echo "# for Python" >> ~/.bash_profile'
su -l vagrant -c 'git clone https://github.com/yyuu/pyenv.git ~/.pyenv'
su -l vagrant -c 'echo export PYENV_ROOT="$HOME/.pyenv" >> ~/.bash_profile'
su -l vagrant -c 'echo export PATH="$PYENV_ROOT/bin:$PATH" >> ~/.bash_profile'
su -l vagrant -c 'echo eval "$(pyenv init -)" >> ~/.bash_profile'

#
# for ALL
#
su -l vagrant -c 'exec $SHELL -l'

#
# Install Bluemix CLI
#
su -l vagrant -c 'mkdir download'
su -l vagrant -c 'cd download;curl -s -O https://public.dhe.ibm.com/cloud/bluemix/cli/bluemix-cli/Bluemix_CLI_0.5.5_amd64.tar.gz'
su -l vagrant -c 'cd download;tar xzvf Bluemix_CLI_0.5.5_amd64.tar.gz'
su -l vagrant -c 'sudo ./download/Bluemix_CLI/install_bluemix_cli'

#
# for Docker and Bluemix CLI IC plugin
#
apt-get install apt-transport-https ca-certificates curl software-properties-common
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
apt-key fingerprint 0EBFCD88
add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu  $(lsb_release -cs) stable"
apt-get update
apt-get install -y docker-ce
usermod -aG docker vagrant

#
# for docker-compose
#
curl -s -L -O https://github.com/docker/compose/releases/download/1.16.1/docker-compose-`uname -s`-`uname -m`
mv docker-compose-`uname -s`-`uname -m` /usr/local/bin/docker-compose 
chmod a+x /usr/local/bin/docker-compose 

#
# for Kubernetes CLI 
#
curl -s -O http://storage.googleapis.com/kubernetes-release/release/v1.5.6/bin/linux/amd64/kubectl
mv kubectl /usr/local/bin
chmod a+x /usr/local/bin/kubectl 

#
SHELL
end
~~~ 


`config.vm.network "public_network", ip: "192.168.1.88", bridge: "en0: Ethernet"` この設定は、仮想マシンへ外部からアクセス可能なIPアドレスを付与します。  野良サーバーを生んでしまうかも知れませんが、MacやPCの仮想サーバー上に、一時的なサーバーを作るには、大変便利な機能です。 

`config.vm.network :forwarded_port, host: 3000, guest: 3000` 仮想マシンのゲストOSのポート番号を ホスト（PC）のポート番号にマップします。 ここで立ち上げた Wordpress のサーバーをLAN上の他のサーバー、または、PCのブラウザからアクセスするために、ポートをマッピングすることで、コンテナが開いているサーバーポートにアクセスができます。

このあと、PHP,Python,Ruby, Node.js のツールの環境が続きます。 そして、Bluemix CLI, Docker, docer-compose, kubectlのインストールが続きます。 

このファイルは、https://github.com/takara9/bluemix-dev においてあり、時々修正して、機能を追加していますので、ご注意願います。


## 停止、削除など

次のコマンドで、ダウンロードしたDockerイメージを全て削除して、消します。 しかし、mysql のデータ部分は、ホスト側のファイルシステムに存在していますから、もう一度 up すると、続きから利用できる様になります。

~~~
$ docker-compose down --rmi all 
~~~


## まとめ

k8sを使いこなすためには、やはり、Dockerを良く知って、有効に使える知識が必要なんだと思います。 そして、 Docker Hubには、公式イメージと称されるコンテナが登録される様になっており、いろいろな便利な機能を付け加えて、登録されています。 Docker Hub に登録されているコンテナを有効に活用しながら、ユーザーの満足度を上げる活動だできる様に、少しでも、力になれたら良いなぁと思っています。



## 参考資料
(1) Quickstart: Docker Compose and WordPress https://docs.docker.com/v1.10/compose/wordpress/