WSL2上のDockerでCakePHP4の開発環境を構築する

## はじめに
私は新卒4年目のエンジニアとしてWeb系の開発をおこなっています。

普段の開発環境はAWS EC2に直接インストールしたPHP+Phalcon（！）+MySQL+nginxという、少し懐かしいスタイルです。
この度、CakePHPに触れる機会があり、ついでにDockerで開発環境を構築しようと思い、アウトプットのために実際に行った手順を書いていきたいと思います。

:::note warn
DockerもCakePHPも初心者ですが、この記事では細かい解説を省き、まずは動作させることを目標としています。
:::

## 環境
- Windows 10 Home 22H2
- WSL2 Ubuntu 22.04.2 LTS
- Docker Desktop 4.19.0

これらのインストールは済ませている前提です。

## ファイル構成
ホームディレクトリ直下にcakephpディレクトリを作成し、そちらで作業します。
最終的にこのようなファイル構成となります。
```plaintext:~/cakephp
├── docker
│   ├── mysql
│   │   └── my.cnf
│   └── web
│       └── Dockerfile
├── .env
└── docker-compose.yml
```
### docker-compose
`docker-compose`は、複数のコンテナで構成されるアプリケーションについて、Dockerイメージのビルドや各コンテナの起動・停止などをより簡単に行えるようにするツールです。
`docker-compose.yml`という設定ファイルに、複数のDockerコンテナの設定をまとめて記述することで、一括管理が可能になります。
今回はMySQL 8.0.X、PHP 8.2.X、CakePHP 4.Xの環境を作ります。

```yaml:docker-compose.yml
version: '3'
services:
  web:
    # ./docker/web/Dockerfileでビルド
    build:
      context: ./docker/web
      dockerfile: Dockerfile
    # db起動後にwebを起動
    depends_on:
      - db
    # ローカルのカレントディレクトリをコンテナの/var/wwwにマウント
    volumes:
      - ./:/var/www
    # 80番ポートを割り当て
    ports:
      - ${WEB_PORT}:80

  db:
    # mysql:8.0イメージから構築
    image: mysql:8.0
    # 認証プラグインをmysql_native_passwordに設定
    command: --default-authentication-plugin=mysql_native_password
    # ローカルの./docker/mysql/my.cnfをコンテナの/etc/mysql/conf.d/my.cnfにマウント
    volumes:
      - ./docker/mysql/my.cnf:/etc/mysql/conf.d/my.cnf
    # .envで環境変数を管理
    environment:
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASS}
      - MYSQL_ROOT_PASSWORD=${DB_PASS}
    # 80番ポートを割り当て
    ports:
      - ${DB_PORT}:3306
```
### Dockerfile
`Dockerfile`は、公開されているDockerイメージをそのまま使うのではなく、必要なパッケージやアプリ、各種設定を含んだDockerイメージを自分で作成して使用する場合に記述するビルド手順書です。

この`Dockerfile`では、さきほどの`docker-compose.yml`のwebコンテナを編集します。
```dockerfile:Dockerfile
FROM php:8.2-apache

RUN apt-get update \
  && apt-get install -y vim \
  # unzipコマンド(composer create-projectで必要)
  && apt-get install -y unzip \
  # PHPのintl拡張(CakePHPで必要)
  && apt-get install -y libicu-dev \
  && docker-php-ext-install intl \
  # PDO MySQL拡張
  && docker-php-ext-install pdo_mysql \
  # mod_rewrite有効化
  && a2enmod rewrite

COPY --from=composer /usr/bin/composer /usr/bin/composer
```
### MySQLの設定
文字コードとタイムゾーンの設定を記載します。
```:my.cnf
[mysqld]
# 文字コード/照合順序の設定
character-set-server = utf8mb4
collation-server = utf8mb4_bin

# タイムゾーンの設定
default-time-zone = SYSTEM
log_timestamps = SYSTEM

# mysqlオプションの設定
[mysql]
# 文字コードの設定
default-character-set = utf8mb4

# mysqlクライアントツールの設定
[client]
# 文字コードの設定
default-character-set = utf8mb4
```
### 環境変数の設定
ポートとデータベースの接続情報を記載します。
```:.env
WEB_PORT=8080
DB_NAME=cakephptest
DB_USER=cake
DB_PASS=cakepassword
DB_PORT=8888
```
## dockerコンテナの起動
```bash:dockerコンテナの起動
yoyoyo@wsl:~/cakephp$ docker-compose up -d
```
ここで私の環境ではエラーになってしまいました。
```bash:エラー内容
yoyoyo@wsl:~/cakephp$ docker-compose up -d
[+] Building 1.9s (7/8)
 => [internal] load .dockerignore                                                                                                                                                                                                                       0.0s
 => => transferring context: 2B                                                                                                                                                                                                                         0.0s
 => [internal] load build definition from Dockerfile                                                                                                                                                                                                    0.0s
 => => transferring dockerfile: 529B                                                                                                                                                                                                                    0.0s
 => [internal] load metadata for docker.io/library/composer:latest                                                                                                                                                                                      0.8s
 => [internal] load metadata for docker.io/library/php:8.2-apache                                                                                                                                                                                       0.9s
 => CACHED FROM docker.io/library/composer@sha256:d718bf3b9e308a8616a12924c5e74ef565a44f83264191bb0e37aafee5254134                                                                                                                                      0.0s
 => CACHED [stage-0 1/3] FROM docker.io/library/php:8.2-apache@sha256:e28189a95082561bd68fa1424217909cdbc15295a15f39bec1a72746a6a7112b                                                                                                                  0.0s
 => ERROR [stage-0 2/3] RUN apt-get update   && apt-get install -y vim   && apt-get install -y unzip   && apt-get install -y libicu-dev   && docker-php-ext-install intl   && docker-php-ext-install pdo_mysql   && a2enmod rewrite   && apt-get clean  0.9s
------
 > [stage-0 2/3] RUN apt-get update   && apt-get install -y vim   && apt-get install -y unzip   && apt-get install -y libicu-dev   && docker-php-ext-install intl   && docker-php-ext-install pdo_mysql   && a2enmod rewrite   && apt-get clean   && rm -rf /var/lib/apt/lists/*:
#0 0.508 Get:1 http://deb.debian.org/debian bullseye InRelease [116 kB]
#0 0.524 Err:1 http://deb.debian.org/debian bullseye InRelease
#0 0.524   Undetermined Error [IP: ****]
#0 0.542 Get:2 http://deb.debian.org/debian-security bullseye-security InRelease [48.4 kB]
#0 0.572 Get:3 http://deb.debian.org/debian bullseye-updates InRelease [44.1 kB]
#0 0.677 Get:4 http://deb.debian.org/debian-security bullseye-security/main amd64 Packages [237 kB]
#0 0.800 Get:5 http://deb.debian.org/debian bullseye-updates/main amd64 Packages [14.6 kB]
#0 0.810 Fetched 344 kB in 0s (1003 kB/s)
#0 0.810 Reading package lists...
#0 0.835 W: Failed to fetch http://deb.debian.org/debian/dists/bullseye/InRelease  Undetermined Error [IP: ****]
#0 0.835 W: Some index files failed to download. They have been ignored, or old ones used instead.
#0 0.844 Reading package lists...
#0 0.872 Building dependency tree...
#0 0.877 Reading state information...
#0 0.884 E: Unable to locate package vim
------
failed to solve: process "/bin/sh -c apt-get update   && apt-get install -y vim   && apt-get install -y unzip   && apt-get install -y libicu-dev   && docker-php-ext-install intl   && docker-php-ext-install pdo_mysql   && a2enmod rewrite   && apt-get clean   && rm -rf /var/lib/apt/lists/*" did not complete successfully: exit code: 100
```
最初の`apt-get update`でつまづいているようです。
こちらの記事を参考に`/etc/resolv.conf`に8.8.8.8を追加することで解決できました。

https://qiita.com/siruku6/items/84698c3276e29a7aca4e

dbコンテナとwebコンテナが稼働していることが分かります。
```bash:稼働中のコンテナ
yoyoyo@wsl:~/cakephp$ docker-compose ps
NAME                IMAGE               COMMAND                  SERVICE             CREATED             STATUS              PORTS
cakephp-db-1        mysql:8.0           "docker-entrypoint.s…"   db                  8 minutes ago       Up 8 minutes        33060/tcp, 0.0.0.0:8888->3306/tcp
cakephp-web-1       cakephp-web         "docker-php-entrypoi…"   web                 8 minutes ago       Up 8 minutes        0.0.0.0:8080->80/tcp
```
## CakePHPのインストール
次にCakePHPのインストールを行います。バージョンは4.Xです。
先ほどのcakephp-web-1コンテナに入り、/var/wwwでCakePHPのインストールを実行します。
```bash:CakePHPのインストール
yoyoyo@wsl:~/cakephp$ docker exec -it cakephp-web-1 bash
root@b945a715e846:/var/www# composer create-project --prefer-dist cakephp/app:4.* html
```
`http://127.0.0.1:8080`にアクセスすると、CakePHPの初期画面が表示されるようになりました！
![CakePHP the rapid development PHP framework.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348786/2e118f9f-816d-30e6-d2dd-b2cfe4b70bda.png)
しかし、CakePHPからデータベースへの接続ができていません。（画像赤枠）
### データベースの接続
CakePHPのデータベース接続情報は`/var/www/html/config/app_local.php`で管理します。
先ほどの`.env`に記載した接続情報をこちらに入力します。
```plaintext:config/app_local.php
'Datasources' => [
    'default' => [
        'host' => 'db',
        'username' => 'cake',
        'password' => 'cakepassword',
        'database' => 'cakephptest',
```
無事にデータベースへの接続も完了しました！（画像赤枠）
![CakePHP the rapid development PHP framework.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348786/26ea0acf-3356-ae25-1b99-99b925205852.png)
## おわりに
初めてのDockerでしたがとても簡単に動作させることができました。
コードベースでの環境構築は保守性が高くてよいですね。
次は公式サイトの[チュートリアル](https://book.cakephp.org/4/ja/tutorials-and-examples.html)に従って、CakePHPの動作になれていこうと思います。