DockerコマンドのみでPHPコンテナ及びMySQLコンテナ、Postgresコンテナを立ち上げ、CodeIgniterを起動させる。


``(目的)docker-composeコマンドを用いずにPHPとMySQL,Postgresの開発環境を構築する``

# 1.docker-composeを使用せずにコマンドだけでPHPとMySQL,Postgresの実行環境を作成

## (1)PHPコンテナとMySQLコンテナ,Postgresコンテナを連結するためにネットワークを作成
```docker 
docker network create codeigniter
# 今回はCodeIgniter(FW)を使うため
# 便宜上このように命名する。
```
***これまでのバージョンでは --linkオプションで任意のコンテナから別のコンテナへ接続できるように指定する仕様だったようですが、最近のバージョンでは --linkオプションが非推奨になったようで、今後のバージョンでは上記のような方法が望ましいようです。***


## (2)PostgresコンテナをマウントするためのDocker Volumeを作成

```docker

docker volume create postgres-server
# ここで指定したpostgres-serverという名前をPostgresコンテナ作成時に
# -v オプションに渡してやる。
```

## (3)PHPアプリケーション向けPHPコンテナの作成
```docker 
docker container create --name php56-server --net codeigniter -p 8080:80 -v /c/codeigniter/local_html/:/var/www/html/ php:5.6-apache

# --name コンテナ名を指定
# --net MySQLコンテナと接続するために必要なため事前に任意の名前でdocker networkを作成
# -p ホストOSポート:ゲストOSポート ※ブラウザアクセス時に使用するポート
# -v 共有ディレクトリのマウント先
```

## (4)--mountオプションを指定してマウントする
***マウントボリュームを -vオプションではなく --mountオプションで指定する方法が以下の方法です。***

***(3)で行ったマウントボリュームの方法ですが、 -vオプションを指定してコンテナのデータ永続化を実現しているが、最新のdockerでは[-v]オプションより[--mount]オプションを指定する方法が推奨されている。***

```docker
# --mountオプションを利用したマウントを実施する
docker container create
--name php56-server
--net codeigniter
--mount type=bind,src=/c/codeigniter/local_html/,dst=/var/www/html/
# --mountオプションを指定してtype=bindと指定する(※従来の-vオプションと同等のもの)
-p 8080:80
php:5.6-apache
```

## (5)MySQLコンテナを作成
```docker
docker container create --name mysql-server --net codeigniter -p 3306:3306 -v /c/codeigniter/local_html/mysql/mysql-data/:/var/lib/mysql/ -e MYSQL_DATABASE=mysql_application -e MYSQL_USER=mysql_user -e MYSQL_PASSWORD=mysql_password -e MYSQL_ROOT_PASSWORD=root_password mysql:5.7.22 

# --name コンテナ名を指定
# --net PHPコンテナと接続するために必要なため事前に任意の名前でdocker networkを作成
# -e MYSQL_***=*** はPHPアプリケーションからMySQLへ接続する際に使用する接続情報のため注意して設定する
# -e MYSQL_USER=mysql_user
# -e MYSQL_DATABASE=mysql_application
# -e MYSQL_PASSWORD=mysql_password
# -e MYSQL_ROOT_PASSWORD=root_password
```

***こちらのMySQLコンテナの作成時も-vオプションではなく--mountオプションを使ってディレクトリのマウントが可能になる***

```docker
docker container create --name mysql-server --net codeigniter  --mount type=bind,src=/c/codeigniter/local_html/mysql/mysql-data/,dst=/var/lib/mysql/ -p 3306:3306 -e MYSQL_USER=mysql_user -e MYSQL_DATABASE=mysql_application -e MYSQL_PASSWORD=mysql_password -e MYSQL_ROOT_PASSWORD=root_password mysql:5.7.22

#上記コマンドで-vオプションを--mountで代替できる。
```

## (6)postgresコンテナを作成

```docker
 docker container create --name postgres-server --net codeigniter -v postgres-server:/var/lib/postgresql/data  -p 5432:5432 -e POSTGRES_USER=my_app -e POSTGRES_PASSWORD=my_app -e POSTGRES_DB=my_app postgres:latest
# --name Postgresコンテナサーバーの名前を付ける
# --net PHPコンテナから接続する際のdocker networkを指定
# -v {ボリューム名}:ゲスト側ディレクトリ ※ホスト側のディレクトリには
# 事前に作成した docker volume postgres-server(任意の名前)を指定する。(postgresの永続化のため)
# -e POSTGRES_USER=my_app postgresの接続ユーザー名
# -e POSTGRES_PASSWORD=my_app postgresユーザーのパスワード
# -e POSTGRES_DB=my_app 使用データベース名(※ユーザー名と同一である必要がある)
```
***以上のコマンドでPostgresコンテナが作成完了する。
ただし、MySQLコンテナと異なり、Windowsのディレクトリに直接ボリュームをマウントすることができない点に注意すること。***


# 2.作成したコンテナを停止状態から起動させる
## (1)PHPコンテナを起動する

```docker
docker container start php56-server # PHPコンテナを起動させる
```
*ところがDocker公式のPHPコンテナはデフォルトではpdo_mysqlおよびpdo_pgsqlがインストールされていないため別途コンテナ内に入り任意のモジュールをインストールする必要がある。*

```docker
docker container exec -it php56-server /bin/bash 
docker-php-ext-install pdo_mysql mysqli mbstring
# PHPアプリケーションからMYSQLに接続することが主目的なので取り急ぎこれだけ
```

```docker

# 更にPHPからPDOを用いてPostgresに接続するためpdo_pgsqlをインストールする
# ※参考)https://gist.github.com/ben-albon/3c33628662dcd4120bf4
apt-get update && 
apt-get install -y libpq-dev && 
docker-php-ext-install pdo pdo_pgsql
# pdo_mysqlと同じくコンテナ内にexecコマンドでログインし上記コマンドを実行
```

```docker
# 上記コマンド実行後、PHPコンテナを再起動する
docker container restart php56-server 
```

## (2)MySQLコンテナを起動させる
```docker 
docker container start mysql-server # MySQLコンテナを起動させる
```

## (3)Postgresコンテナを起動させる

```docker
docker container start postgres-server # Postgresコンテナを起動させる。
```


## (4)ブラウザでlocalhost:8080にアクセス

*codeigniterが起動していればOK*

# 3.MYSQLコンテナの接続情報をCodeIginterに設定する

## (1)MySQLコンテナ作成時のDB情報を設定

```php:database.php

$db['default'] = array(
    // ホスト名はPostgresコンテナ名の{mysql-server}と指定する
    'dsn'   => 'mysql:host=mysql-server;dbname=mysql_application;charset=UTF8;',
    'hostname' => 'localhost',
    'username' => 'mysql_user',
    'password' => 'mysql_password',
    'database' => 'mysql_application',
    'dbdriver' => 'pdo',
    'dbprefix' => '',
    'pconnect' => FALSE,
    'db_debug' => (ENVIRONMENT !== 'production'),
    'cache_on' => FALSE,
    'cachedir' => '',
    'char_set' => 'utf8',
    'dbcollat' => 'utf8_general_ci',
    'swap_pre' => '',
    'encrypt' => FALSE,
    'compress' => FALSE,
    'stricton' => FALSE,
    'failover' => array(),
    'save_queries' => TRUE
);

```

## (2)Postgresコンテナ作成時のDB情報を設定

```php:database.php

$db['default'] = array(
    // ホスト名はMySQLコンテナ名の{postgres-server}と指定する
    'dsn'   => 'pgsql:host=postgres-server;dbname=my_app;port=5432;',
    'hostname' => 'localhost',
    'username' => 'my_app',
    'password' => 'my_app',
    'database' => 'my_app',
    'dbdriver' => 'pdo',
    'dbprefix' => '',
    'pconnect' => FALSE,
    'db_debug' => (ENVIRONMENT !== 'production'),
    'cache_on' => FALSE,
    'cachedir' => '',
    'char_set' => 'utf8',
    'dbcollat' => 'utf8_general_ci',
    'swap_pre' => '',
    'encrypt' => FALSE,
    'compress' => FALSE,
    'stricton' => FALSE,
    'failover' => array(),
    'save_queries' => TRUE
);

```

## (2)上記ファイルを設定後ブラウザアクセス

*データーベースへの接続autuload許可した上で実行後
なんのエラーも出ていなければ、PHPコンテナとMySQLコンテナの連結が完了しています。*


# 4.Dockerfileに処理をまとめる
***上記までの手順だと、PHPアプリケーション用のコンテナを動作状態に構築するまでに pdoモジュールをインストールしたりいくつか不便なことがあるので Docker公式イメージのphp:5.6-apacheを拡張したimageをDockerfileで作成する。***

##(1)Dockerfileを作成
```dockerfile
# 以下のようにDockerfileを記述する
FROM php:5.6-apache
# Mysql接続用にPDOモジュールをインストールする
RUN docker-php-ext-install pdo_mysql mysqli mbstring
# PostgresqlもPDO接続を可能にするためpdo_pgsqlをインストールする
RUN apt-get update && apt-get install -y libpq-dev && docker-php-ext-install pdo pdo_pgsql
# docker公式のPHPコンテナのエントリポイントは
# /usr/local/bin/docker-php-entrypoint というスクリプトなので下記を記述
ENTRYPOINT ["/usr/local/bin/docker-php-entrypoint", "-DFOREGROUND"]
```
***上記Dockerfileを任意のディレクトリに配置して以下のようなコマンドを実行する。***

```docker
docker build -t php56/server . 
           # -t [作成後のビルドイメージ名] [Dockerfileが存在するディレクトリ]
```
***その後 docker imagesでDockerイメージのリストを表示させると作成したphp56/serverというイメージが追加されているのがわかる。***

##(2)作成した独自イメージからコンテナを起動する

```docker
docker container create --name php56-server --net codeigniter --mount type=bind,src=/c/codeigniter/local_html,dst=/var/www/html -p 8080:80 php56/server
```
***上記のようにコンテナのもととなるイメージをphp56/serverに変更してコンテナを作成する。***

##(3)ブラウザでlocalhost:8080にアクセス
***問題なくページが動作すれば、Dockerfileを使ったコンテナの作成は成功です。***