Codeigniter3のローカル環境をMAMPからDockerへ移した話

タイトルの通りですが、その際色々とつまづいたのでこちらに学習メモとして残しておきます。

最初に筆者のスペックを簡単に

・CodeigniterもPHPも初級者
・MAMP歴1週間、Docker利用は今回が初めて
・Qiita初投稿

てな状況でQiitaに投稿するなんて無謀かなーとは思いましたが、アウトプットの一環ということで😅
流れを再現しつつ解決方法を書いていきます。

#使用したものとバージョン
- PHP 7.4
- Codeigniter 3.1.6
- Apache
- Mysql 5.7

PHP、Apache、MysqlはMAMPの環境をそのまま持って行きたかったので特に選んだ理由はなし。
Codeigniterはcomposerを使ってインストールしたものになります。

#ディレクトリ構造

```
codeigniter
├──application
├──bin
├──public
│   └──index.php
├──vendor
├──docker-compose.yml
└──php.ini
```

```yml:docker-compose.yml
version: '3'

services:
  php:
    container_name: CI-TL-L
    image: php:7.4-apache
    depends_on:
      - mysql
    volumes:
      - ./:/var/www/html/codeigniter
    working_dir: /var/www/html
    ports:
      - 8080:80
    restart: always
  mysql:
    image: mysql:5.7
    volumes:
      - ./mysql:/var/lib/mysql
    environment:
      - MYSQL_ROOT_PASSWORD=「パスワード名」
      - MYSQL_DATABASE=「データベース名」
      - MYSQL_USER=「ユーザー名」
      - MYSQL_PASSWORD=「パスワード」
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=mysql
      - PMA_USER=root
      - PMA_PASSWORD=root
    links:
      - mysql
    ports:
      - 4040:80
    volumes:
      - ./phpmyadmin/sessions:/sessions
```

```ini:php.ini
[Date]
date.timezone = "Asia/Tokyo"
[mbstring]
mbstring.internal_encoding = "UTF-8"
mbstring.language = "Japanese"
```
#コンテナ起動 1
この時点で一度コンテナを起動してみると...

```
codeigniter$ docker-compose up -d
```

```
An uncaught Exception was encountered
Type: Error
Message: Call to undefined function mysqli_init()
Filename: /var/www/html/codeigniter/vendor/codeigniter/framework/system/database/drivers/mysqli/mysqli_driver.php
Line Number: 135
Backtrace:
    File: /var/www/html/codeigniter/public/index.php
     Line: 315
     Function: require_once
```

「定義されていないmysqli_init()が呼び出されています」というエラーが出ます。
#コンテナ起動 1 解決方法
このエラーは指定したドライバーのmysqliがインストールされていないことに起因します。
解決するには
1.php-apache用のDockerfileを作成して
2.docker-compose.ymlを編集して上記のDockerfileでコンテナを起動します。

```
codeigniter
├──application
├──bin
├──public
│   └──index.php
├──vendor
├──docker-compose.yml
├──Dockerfile ---------追加
└──php.ini
```

```dockerfile:Dockerfile
FROM php:7.4-apache

RUN apt-get update \
    && docker-php-ext-install mysqli
```

```yml:docker-compose.yml
version: '3'

services:
  php:
    container_name: CI-TL-L
    build: ./Dockerfile -------編集
    depends_on:
      - mysql
    volumes:
    .
    .
    .
```
これで先ほどのエラーは解消されたはずです。

#コンテナ起動 2
ここでコンテナを再起動してみると...

```terminal
codeigniter$ docker-compose down
codeigniter$ docker-compose up -d
```

```error:エラー
Message: mysqli::real_connect(): (HY000/2002): No such file or directory
Filename: mysqli/mysqli_driver.php
Line Number: 203
```
また別のエラーが出ました。
mysqliのエラーのようなので「mysqliはインストールしたはずなのに...」とこのエラーで２日ほど潰されました。

#コンテナ起動 2 解決方法
では実際mysqliに問題があったかというと実はそうではありません。
このエラーはdatabase.phpを編集することで解消できます。
ディレクトリパスはapplication>config>database.phpですね。

```php:database.php
db['default'] = array(
	'dsn'	=> '',
	'hostname' => 'mysql', -----編集
	'username' => 'ユーザー名',
	'password' => 'パスワード',
	'database' => 'データベース名',
	'dbdriver' => 'mysqli',
```
これで先ほどのエラーは解消できました。

詳しいことは分かりませんが、コンテナ間の通信ではdocker-compose.ymlで指定したサービス名でホスト名を指定する必要があるそうです。
今回の場合だと、docker-compose.ymlでmysqlコンテナにmysqlというサービス名を付けたのでこのような記述になるというわけですね。

#コンテナ起動 3
そして、今度こそ３度目の正直ということで祈りながら起動...

```terminal:terminal
codeigniter$ docker-compose down
codeigniter$ docker-compose up -d
```
・
・
・

```error:エラー
A PHP Error was encountered
mkdir() invalid path
drivers/Session_file_driver.php
Line number: 136
```
はい、出ました。エラーです。
ここまできたらサクッと解決しちゃいましょう。

#コンテナ起動 3 解決方法
解決するにはconfig.phpの編集が必要になります。

```php:config.php
$config['sess_driver'] = 'files';
$config['sess_cookie_name'] = 'ci_session';
$config['sess_expiration'] = 7200;
$config['sess_save_path'] = BASEPATH.'sessions'; -------編集
$config['sess_match_ip'] = FALSE;
$config['sess_time_to_update'] = 300;
$config['sess_regenerate_destroy'] = FALSE;
```

正直このエラーはなぜエラーが出たのか、なぜこれで解消できたのか、分かりませんでした。すみません。

ということでエラー解消までの流れは以上になります。