Vagrant+Dockerローカル用LAMP環境作成メモ

VagrantとDockerを利用して、ローカル用のLAMP環境を作ったときの自分用メモ。
本手順では、以下の環境を作成しています。
Windowsで作業したときのメモ。~~多分、Macでも環境構築できると信じてる。~~
_Macでも問題なく構築できました。(2015/07/15 追記)_

* Apache
* MySQL 5.6
* PHP 5.5

# 必要なものをインストール

VirtualBoxとVagrantを入れないと話は進みません。

VirtualBox
https://www.virtualbox.org/

Vagrant
https://www.vagrantup.com/

それぞれインストール。

# Vagrant初期ファイル作成

## 初期ファイル生成

任意の場所に作業用ディレクトリを作成。
今回、本手順では「C:\vmdir」を作成しました。
コマンドプロンプトで作成したディレクトリへ移動し、初期データを作ります。
Dockerと相性が良かった(と思う)Ubuntuをベースに作ります。

boxを追加します。

http://www.vagrantbox.es/

上記のサイトでboxの各取得URLが記載されています。
「Ubuntu 14.04 with Docker enabled (based on amd64 server iso file)」を落とすのが手っ取り早いと思います。(2015/06/26 現在)

```console:cmd
> vagrant box add ubuntu14.04 https://github.com/jose-lpa/packer-ubuntu_14.04/releases/download/v2.0/ubuntu-14.04.box
```

boxの追加に少し時間がかかります。
box追加後、作業フォルダを作成して、initします。

```console:cmd
> cd C:\vmdir
> vagrant init ubuntu14.04
```

Vagrantfileが生成されるので、必要項目を変更します。

## 設定ファイルを編集

docker使ってLAMP環境動かせるようにカスタマイズします。

```rb:Vagrantfile
:
Vagrant.configure(2) do |config|
:
  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.network "forwarded_port", guest: 80, host: 8080 ←追加
:
  # Provider-specific configuration so you can fine-tune various
  # backing providers for Vagrant. These expose provider-specific options.
  # Example for VirtualBox:
  #
  config.vm.provider "virtualbox" do |vb| ←コメント解除
  #  # Display the VirtualBox GUI when booting the machine
  #  vb.gui = true
  #
  #  # Customize the amount of memory on the VM:
    vb.memory = "1024" ←コメント解除
  end ←コメント解除
:
end
```

上記の変更により、

* 仮想環境にメモリ1024MB付与(MySQL5.6を起動する為)

これらを付与してます。

# VM起動～初期設定

## VM起動

```console:cmd
> vagrant up
```

これで起動します。
初回起動時は構築作業がある為、時間がかかります。

## SSHでアクセス

Windowsの場合はSSH用の秘密鍵をppkファイルにしないとダメかもしれません。
秘密鍵は、「.vagrant\machines\default\virtualbox\private_key」というファイルが作られてると思うので、これをppkに変換します。

```
host: 192.168.33.10
port: 22
user: vagrant
```

上記の条件でSSH接続可能かと。
Macの場合は、

```console:
$ vagrant ssh
```

このコマンドで接続できます。
(Windowsの場合もSSHとの紐付けがされてればこれでいける？)

## タイムゾーンの設定

USになってるので、日本に合わせる。

```console:ssh
$ sudo dpkg-reconfigure tzdata
```

設定画面が表示されるので、「Asia→Tokyo」で設定すればOKです。

# Docker環境作成

DockerでCentOS6系をベースに準備していきます。

## CentOS6のイメージファイル取得

### イメージファイル取得

Docker用のCentOS6イメージファイルをpullします。

```console:ssh
$ docker pull centos:centos6
```

### コンテナ起動

CentOS6のコンテナを起動します。

```console:ssh
$ docker run --name centos_init -d -t centos:centos6 /sbin/init
```

### コンテナへ接続

起動したコンテナへ接続し、初期設定を行います。

```console:ssh
$ docker exec -it centos_init /bin/bash
```

#### タイムゾーンの設定

```console:接続したコンテナ
# vi /etc/sysconfig/clock
```

```bash:/etc/sysconfig/clock
ZONE="Asia/Tokyo"
UTC="false"
```

```console:接続したコンテナ
# source /etc/sysconfig/clock
# cp -p /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

#### yumアップデート

```console:接続したコンテナ
# yum -y update
```

#### 開発ツールのインストール

```console:接続したコンテナ
# yum -y groupinstall "Development tools"
# yum -y install python-setuptools
```

#### supervisordのインストール

コンテナ内のプロセスを効率良く起動するのに、supervisordを利用します。

```console:接続したコンテナ
# easy_install supervisor
# vi /etc/init.d/supervisord ←起動用スクリプト作成
```

```bash:/etc/init.d/supervisord
#!/bin/sh
#
# /etc/rc.d/init.d/supervisord
#
# Supervisor is a client/server system that
# allows its users to monitor and control a
# number of processes on UNIX-like operating
# systems.
#
# chkconfig: - 64 36
# description: Supervisor Server
# processname: supervisord

# Source init functions
. /etc/init.d/functions

RETVAL=0
prog="supervisord"
pidfile="/tmp/supervisord.pid"
lockfile="/var/lock/subsys/supervisord"

start()
{
   echo -n $"Starting $prog: "
   daemon --pidfile $pidfile supervisord
   RETVAL=$?
   echo
   [ $RETVAL -eq 0 ] && touch ${lockfile}
}
stop()
{
   echo -n $"Shutting down $prog: "
   killproc -p ${pidfile} /usr/bin/supervisord
   RETVAL=$?
   echo
   if [ $RETVAL -eq 0 ] ; then
      rm -f ${lockfile} ${pidfile}
   fi
}
case "$1" in
  start)
    start
  ;;
  stop)
    stop
  ;;
  status)
    status $prog
  ;;
  restart)
    stop
    start
  ;;
  *)
    echo "Usage: $0 {start|stop|restart|status}"
  ;;
esac
```

### 初期設定したコンテナを保存

初期設定をしたコンテナを保存(コミット)します。

```console:接続したコンテナ
# exit ←コンテナから抜ける
```

```console:ssh
$ docker stop centos_init ←コンテナの停止
$ docker commit centos_init centos:supervisord ←コンテナをコミット
$ docker images ←コミットしたコンテナが存在することを確認
```

## イメージをビルドする

ビルド用ファイルを作成します。

### MySQL用イメージのビルド

まず、ビルドに必要な各ファイルを作成します。

```console:ssh
$ mkdir -p /vagrant/docker/mysql ←ビルド用ディレクトリ作成
$ cd /vagrant/docker/mysql
$ vi Dockerfile ←Docker用ビルドファイル作成
```

```bash:Dockerfile
FROM centos:supervisord

RUN yum install -y http://repo.mysql.com/mysql-community-release-el6-5.noarch.rpm
RUN yum install -y mysql mysql-server mysql-devel

ADD supervisord.conf /etc/supervisord.conf
RUN chmod 644 /etc/supervisord.conf

CMD ["/usr/bin/supervisord"]
```

```console:ssh
$ vi supervisord.conf ←設定ファイル作成
```

```bash:supervisord.conf
[supervisord]
nodaemon=true

[program:mysqld]
command=/sbin/service mysqld start
```

ビルド用ファイル作成後、イメージをビルドします。

```console:ssh
$ docker build -t centos:mysql . ←ビルド実行
$ docker images ←イメージが作成されたことを確認
```

### Apache用イメージのビルド

まず、ビルドに必要な各ファイルを作成します。

```console:ssh
$ mkdir -p /vagrant/docker/apache ←ビルド用ディレクトリ作成
$ cd /vagrant/docker/apache
$ vi Dockerfile ←Docker用ビルドファイル作成
```

```bash:Dockerfile
FROM centos:supervisord

RUN rpm -ivh http://ftp.riken.jp/Linux/fedora/epel/6/x86_64/epel-release-6-8.noarch.rpm
RUN rpm -ivh http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
RUN yum install -y http://repo.mysql.com/mysql-community-release-el6-5.noarch.rpm
RUN yum install -y httpd httpd-devel
RUN yum install -y mysql
RUN yum install -y --enablerepo=remi,remi-php55 phpMyAdmin
RUN yum install -y --enablerepo=epel libmcrypt
RUN yum install -y --enablerepo=remi,remi-php55 php php-devel php-pear php-mbstring php-xml php-mcrypt php-gd php-pecl-xdebug php-opcache php-pecl-apcu php-fpm php-phpunit-PHPUnit php-mysqlnd

ADD supervisord.conf /etc/supervisord.conf
RUN chmod 644 /etc/supervisord.conf

CMD ["/usr/bin/supervisord"]
```

```console:ssh
$ vi addfile/supervisord.conf ←設定ファイル作成
```

```bash:supervisord.conf
[supervisord]
nodaemon=true

[program:httpd]
command=/sbin/service httpd start
```

ビルド用ファイル作成後、イメージをビルドします。

```console:ssh
$ docker build -t centos:apache . ←ビルド実行
$ docker images ←イメージが作成されたことを確認
```

## コンテナ起動

コンテナを作成します。
本手順では、「/vagrant/document」をドキュメントルートとして読み込むように設定しています。
※Vagrantfileが置いてあるディレクトリは仮想環境の/vagrantと共有している

### MySQL用コンテナの起動

```console:ssh
$ docker run --name mysql -t -d centos:mysql
```

### Apache用コンテナの起動

MySQLコンテナのネットワーク情報を共有する為、必ずMySQLコンテナより後に起動する。

```console:ssh
$ docker run --name apache -t -d -p 80:80 -v /vagrant/document:/var/www/html --link mysql:mysql_srv centos:apache
```

起動していることを確認します。

```console:ssh
$ docker ps
```

### MySQL初期設定

コンテナへ接続した状態から作業します。

```console:ssh
$ docker exec -it mysql /bin/bash
```

```console:接続したコンテナ
# vi /etc/my.cnf
```

設定ファイルを編集。文字コードを指定しておきます。

```bash:/etc/my.cnf
:
[mysqld]
:
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
character-set-server = utf8 ← 追記
:
```

```console:接続したコンテナ
# service mysqld restart
```

mysql_secure_installationを実行しとく。

```console:接続したコンテナ
# mysql_secure_installation

:
Enter current password for root (enter for none): 　←　空ENTER
OK, successfully used password, moving on...
:
Set root password? [Y/n] 　←　空ENTER(rootパスワード設定)
New password: 　←　rootパスワード応答
Re-enter new password: 　←　rootパスワード応答(確認)
Password updated successfully!
Reloading privilege tables..
 ... Success!
:
Remove anonymous users? [Y/n] 　←　空ENTER(匿名ユーザー削除)
 ... Success!
Disallow root login remotely? [Y/n] 　←　空ENTER(リモートからのrootログイン禁止)
 ... Success!
Remove test database and access to it? [Y/n] 　←　空ENTER(testデータベース削除)
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!
Reload privilege tables now? [Y/n] 　←　空ENTER
 ... Success!
```

Apacheから接続可能なユーザを作成します。
※以下、Dockerコンテナ内のIPアドレスが「172.17.0.0/24」の場合

```console:接続したコンテナ
# mysql -u root -p ←MySQLへ接続
```

```mysql:接続用ユーザ作成
> grant all privileges on *.* to root@'172.17.0.%' identified by '{password}' with grant option;
> exit
```

設定後、コンテナから抜けます。

```console:接続したコンテナ
# exit
```

### phpMyAdmin設定

phpMyAdminが利用できるように設定ファイルを修正します。

```console:ssh
$ docker exec -it apache /bin/bash
```

```console:接続したコンテナ
# vi /etc/httpd/conf.d/phpMyAdmin.conf
```

```apacheconf:/etc/httpd/conf.d/phpMyAdmin.conf
:
<Directory /usr/share/phpMyAdmin/>
   AddDefaultCharset UTF-8

   <IfModule mod_authz_core.c>
     # Apache 2.4
     Require local
   </IfModule>
   <IfModule !mod_authz_core.c>
     # Apache 2.2
     Order Deny,Allow
     Deny from All
     Allow from 127.0.0.1
     Allow from ::1
     Allow from 10.0.2.2 ← 追記
   </IfModule>
</Directory>
:
```

変更した内容を反映します。

```console:接続したコンテナ
# service httpd graceful
```

DBの接続先を指定します。

```console:接続したコンテナ
# vi /etc/phpMyAdmin/config.inc.php
```

```php:/etc/phpMyAdmin/config.inc.php
$cfg['Servers'][$i]['host'] = 'mysql_srv'; ←変更
```

# 各動作確認

## ブラウザから動作確認

http://localhost:8080/

上記へアクセスして、WEBコンテンツが表示されることを確認。

## MySQLへの接続確認

http://localhost:8080/phpMyAdmin/

phpMyAdminへアクセスできることを確認。
rootでログインできればOKです。

# 起動、停止

## 各コンテナの停止

```console:ssh
$ docker stop apache
$ docker stop mysql
```

## 各コンテナの起動

```console:ssh
$ docker start mysql
$ docker start apache
```

## VMの起動

ホストOSより操作します。

```console:cmd
> vagrant up
```

## VMの停止

```console:cmd
> vagrant halt
```

## VM起動時にコンテナを自動起動

Vagrantfileに自動起動スクリプト記述を追記します。

```rb:Vagrantfile
Vagrant.configure(2) do |config|
:
  config.vm.provision "shell", inline: "docker start mysql", run: "always" ← 追記
  config.vm.provision "shell", inline: "docker start apache", run: "always" ← 追記
end
```

# あとがき

あとは開発に合わせて都度カスタマイズできるかと。
まだDocker勉強中なので、色々と便利にできたらいいですね。
最後に初期設定のイメージをコミットしているので、テスト過程で壊したり作ったりをコンテナでうまく繰り返せばリターン地点が楽かも？