DockerでCakePHPの環境を立ち上げる on M1 Mac【4.x 対応】

Web開発Docker,nginx,Mac,PHP,docker-compose,CakePHP

日本で人気のPHPフレームワーク、CakePHP

  • MVCアーキテクチャ
  • コーディング規約が厳しいが、その分学習コストが低く、素早い開発が可能
  • 日本語ドキュメントが豊富
  • 同じPHPフレームワークであるLaravelに次ぐトレンド

この記事では、CakePHPをDockerで立ち上げ、データベースへの接続確認ができるまでをご紹介していきたいと思います。

こんな人におすすめ
  • これからCakePHPを勉強するために、環境を立ち上げたい
  • Dockerで立ち上げてみたいが、Dockerを使ったことがない

構築環境

  • CakePHP 4
  • PHP:8.1.4
  • MySQL:8.0.26
  • Nginx:1.21.6-alpine

Githubリポジトリ

Dockerコンテナを立ち上げる手前までの状態のものをGithubリポジトリに置いてあります。

すぐに環境と立ち上げたい方は、上記リポジトリをクローンし、Dockerコンテナの起動の手順から進めてもらえたらよいかと思います。

準備

ターミナルの使用について

この記事では基本的にターミナルでの操作を記載していきますが、必要に応じてFinderやエディターを利用していただいて問題ありません。

ただ、ターミナルはWebエンジニアとしてやっていくためには必須です。
適宜コメントアウトを記載していますので、少しずつでもターミナルに慣れていくようにしましょう!

Dockerをインストールする

以下の記事の 1. Docker for Macをインストールする をやっていただければOKです。

CakePHPをインストールするためのディレクトリを作成する

次にCakePHPインストールするためのディレクトリ(フォルダ)を作成していきます。

# ホームディレクトリへ移動
$ cd ~

# wwwディレクトリを作成し、wwwへ移動
$ mkdir www
$ cd www

# cakephp-with-dockerディレクトリを作成し、cakephp-with-dockerへ移動
$ mkdir cakephp-with-docker
$ cd cakephp-with-docker

# 現在いるディレクトリを確認
$ pwd
/Users/{ユーザー名}/www/cakephp-with-docker

# dockerディレクトリとsrcディレクトリを作成
$ mkdir src
$ mkdir -p docker/mysql/conf.d
$ mkdir -p docker/nginx
$ mkdir -p docker/php

ホームディレクトリ ~ は、/Users/{ユーザー名}ディレクトリのことを指しています。
つまり、最初にホームディレクトリである/Users/{ユーザー名}ディレクトリに移動し、そこから wwwcakephp-with-docker と移動してきたので、現在いるディレクトリを確認した時には/Users/{ユーザー名}/www/cakephp-with-dockerにいることになります。

ですので、現在のディレクトリ構成は以下の通りになっています。

Users/
└ {ユーザー名}/
  └ www/
    └ cakephp-with-docker/ ←今ここにいる
      ├ src/
      └ docker/
         ├ nginx/
         ├ php/
         └ mysql/
           └ conf.d/

Dockerの設定

次にDockerでCakePHPを立ち上げるために必要なファイルを作成していきます。

docker-compose.yml

今いるディレクトリ ~/www/cakephp-with-dockerdocker-compose.yml ファイルを作成します。

Users/
└ {ユーザー名}/
  └ www/
    └ cakephp-with-docker/
      ├ docker-compose.yml  ←新しく作成
      ├ src/
      └ docker/
         ├ nginx/
         ├ php/
         └ mysql/
           └ conf.d/

これはDockerの機能一つのである Docker Compose機能 を利用するための設定ファイルです。

Dockerは、コンテナと呼ばれる実行環境を起動することで、コンテナごとのアプリケーションを利用できます。
通常、コンテナはアプリケーションごとに独立しており、それをコンテナごとに起動したり設定したりするのですが、コンテナの数が増えてくると管理が煩雑になります。
また、それをチームメンバーで同じような環境を作ろうと思うともっと大変です。

そういったことを解決するため、コンテナをまとめて一括管理できる機能が Docker compose機能 です。
以下が、Docker compose機能を利用するための docker-compose.yml ファイルです。
今回は、nginx(Webサーバー)・PHP・MySQL(データベース)のコンテナを一括管理します。

docker-compose.yml

version: '3.9'
volumes:
  db-store:
services:
    web:
        image: nginx:1.21.6-alpine
        ports:
            - 34251:80
        volumes:
            - ./src:/var/www
            - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
        depends_on:
            - app
    app:
        build: ./docker/php
        volumes:
            - ./src:/var/www
        links:
            - db
        depends_on:
            - db
    db:
        image: mysql:8.0.26
        platform: 'linux/amd64'
        volumes:
            - ./docker/mysql/conf.d:/etc/mysql/conf.d
            - db-store:/var/lib/mysql
        ports:
            - 2435:3306
        environment:
            MYSQL_DATABASE: sample
            MYSQL_USER: user
            MYSQL_PASSWORD: secret
            MYSQL_ROOT_PASSWORD: secret
            TZ: "Asia/Tokyo"

PHP : Dockerfile

続いて、~/www/cakephp-with-docker/docker/php ディレクトリにPHPのDockerfileを作成します。

Users/
└ {ユーザー名}/
  └ www/
    └ cakephp-with-docker/
      ├ docker-compose.yml
      ├ src/
      └ docker/
         ├ nginx/
         ├ php/
         │ └ Dockerfile  ←新しく作成
         └ mysql/
           └ conf.d/

Dockerfile は、Dockerイメージを作成するための設計図のようなものです。
今回、nginx(Webサーバー)やMySQL(データベース)は既存の各イメージを使ってコンテナを作成しますが、PHPについてはCakePHPのインストールなども必要なので、Dockerfile からイメージを作成→コンテナを作成する流れになります。

Dockerfile

FROM php:8.1.4-fpm-alpine
COPY php.ini /usr/local/etc/php/

COPY --from=composer:2.0 /usr/bin/composer /usr/bin/composer

RUN apk --no-cache update \
    && apk --no-cache upgrade \
    && apk --no-cache add icu-dev zlib-dev libzip-dev mariadb mariadb-client vim \
    && docker-php-ext-configure intl \
    && docker-php-ext-install intl zip pdo pdo_mysql mysqli \
    && docker-php-ext-enable intl

WORKDIR /var/www

PHP : php.ini

次に、先程とおなじ ~/www/cakephp-with-docker/docker/php ディレクトリに php.ini ファイルを作成します。
php.ini は、PHPプログラムの全体的な動作や環境を設定するファイルです。

Users/
└ {ユーザー名}/
  └ www/
    └ cakephp-with-docker/
      ├ docker-compose.yml
      ├ src/
      └ docker/
         ├ nginx/
         ├ php/
         │ ├ Dockerfile
         │ └ php.ini  ←新しく作成
         └ mysql/
           └ conf.d/

この設定ファイルでは、タイムゾーン(使用する時間帯の地域)や使用する言語といった最低限の設定を行います。

php.ini

date.timezone = Asia/Tokyo

log_errors = On
error_log = /dev/stderr
display_errors = Off

output_buffering = On

mbstring.language = "Japanese""

nginx : default.conf

次はWebサーバーとなるnginxの設定ファイルである default.conf を作成します。
作成場所は ~/www/cakephp-with-docker/docker/nginx です。

Users/
└ {ユーザー名}/
  └ www/
    └ cakephp-with-docker/
      ├ docker-compose.yml
      ├ src/
      └ docker/
         ├ nginx/
         │ ├ default.conf  ←新しく作成
         ├ php/
         │ ├ Dockerfile
         │ └ php.ini
         └ mysql/
           └ conf.d/

default.conf

server {
  listen 80;

  root  /var/www/webroot;
  index index.php;

  location / {
    try_files $uri $uri/ /index.php$is_args$args;
  }

  location ~ \.php$ {
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass   app:9000;
    fastcgi_index  index.php;
    include        fastcgi_params;
    fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param  PATH_INFO $fastcgi_path_info;
  }
}

ここではWebサーバーのドキュメントルートの指定やPHPを使用するための設定をしています。

MySQL : my.cnf

次にMySQLの設定ファイルを作成します。
8.0でデフォルトで設定されている認証プラグインから、以前の認証プラグインを使用するように設定します。
ファイルは ~/www/cakephp-with-docker/docker/mysql/conf.d へ作成します。

Users/
└ {ユーザー名}/
  └ www/
    └ cakephp-with-docker/
      ├ docker-compose.yml
      ├ src/
      └ docker/
         ├ nginx/
         │ ├ default.conf
         ├ php/
         │ ├ Dockerfile
         │ └ php.ini
         └ mysql/
           └ conf.d/
             └ my.cnf  ←新しく作成

my.cnf

######################################
### mysqldグループ: mysqlサーバーへの設定
######################################

[mysqld]
# 文字コード/照合順序の設定
character-set-server = utf8mb4
collation-server = utf8mb4_bin

# デフォルト認証方式を mysql_native_password へ変更
# CakePHP4では、MySQL8.0以降のデフォルト認証方式の caching_sha2_password が対応していないため
default_authentication_plugin = mysql_native_password

######################################
### mysqlグループ: mysqlオプションへの設定
######################################

[mysql]
# 文字コードの設定
default-character-set = utf8mb4

######################################
### clientグループ: mysqlクライアントツールへの設定
######################################

[client]
# 文字コードの設定
default-character-set = utf8mb4

Dockerイメージをビルドする

ここまで作成できたら、今まで作ってきた docker-compose.yml をもとに、その他のファイルを利用してDokerイメージをビルドします。
Dockerイメージをビルドするコマンドは docker-compose build です。

# 現在いるディレクトリを確認
$ pwd
~/www/cakephp-with-docker
# もし ~/www/cakephp-with-docker でない場合は cd ~/www/cakephp-with-docker で移動する

# Dockerイメージをビルドする
$ docker compose build
...

# 最終的に以下のようなメッセージが出ればOKです
=> exporting to image                                           0.0s
=> => exporting layer                                           0.0s
=> => writing image sha256:c1a72a05cf36f3d363e1751fa41          0.0s
=> => naming to docker.io/library/cakephp-with-docker_app          0.0s

これでDockerイメージのビルドが完了しました。

Dockerコンテナを起動する

続いて、先程ビルドしたDockerイメージを使ってDockerコンテナを一括で起動します。
Dockerコンテナを起動するコマンドは docker compose up -d です。

$ docker compose up -d
[+] Running 5/5
 ⠿ Network cakephp-with-docker_default    Created     0.0s
 ⠿ Volume "cakephp-with-docker_db-store"  Created     0.0s
 ⠿ Container cakephp-with-docker-db-1     Started     0.5s
 ⠿ Container cakephp-with-docker-app-1    Started     1.2s
 ⠿ Container cakephp-with-docker-web-1    Started     1.9s

# 起動したDockerコンテナを確認
$ docker-compose ps
NAME                        COMMAND                  SERVICE             STATUS              PORTS
cakephp-with-docker-app-1   "docker-php-entrypoi…"   app                 running             9000/tcp
cakephp-with-docker-db-1    "docker-entrypoint.s…"   db                  running             0.0.0.0:2435->3306/tcp
cakephp-with-docker-web-1   "/docker-entrypoint.…"   web                 running             0.0.0.0:34251->80/tcp

上記のStateが全てrunningになっていれば、無事nginx, php, mysqlが起動できています。

CakePHPをインストール

プロジェクトを作成する

次に起動できたPHPのコンテナでCakePHPをインストールしていきます。
そのためにコンテナ上でコマンド操作をしていく必要があります。
コンテナ上でコマンド操作をするためのコマンドは docker compose exec ... sh です。

# PHPのコンテナ上で操作できるようにする
$ docker compose exec app sh

# Composerを使って、CakePHPプロジェクトを作成する
/var/www # composer self-update && composer create-project --prefer-dist cakephp/app:4.* .

# 途中いくつか対話モードが入るのですべてyかY(YES)を入力してEnter

# 最終的に以下のようなメッセージが出ればOKです
Updated Security.salt value in config/app_local.php

もし Project directory "/var/www/." is not empty. というエラーがでた場合は、今いるディレクトリに隠しファイルがある可能性があるので、それを確認して削除しましょう。

/var/www # composer self-update && composer create-project --prefer-dist cakephp/app:4.* .

# こんなエラーが出たら
 [InvalidArgumentException]
  Project directory "/var/www/." is not empty.

# 現在のディレクトリ内の隠しファイルを含めた全てのファイルを表示する
/var/www # ls -la
total 12
drwxr-xr-x 3 root root   96 Mar 10 15:47 .
drwxr-xr-x 1 root root 4096 Feb 26 11:59 ..
-rw-r--r-- 1 root root 6148 Mar  5 17:59 .DS_Store  # ← .(ドット)から始まるファイルが隠しファイル

# 隠しファイルを削除
/var/www # rm -f .DS_Store

# 再度ディレクトリ内のファイルを表示し、隠しファイルがないことを確認
/var/www # ls -la 
total 4
drwxr-xr-x 2 root root   64 Mar 10 15:48 .
drwxr-xr-x 1 root root 4096 Feb 26 11:59 ..

# 再度プロジェクト作成コマンドを実行
/var/www # composer self-update && composer create-project --prefer-dist cakephp/app:4.* .
...

Updated Security.salt value in config/app_local.php

# Dockerコンテナ上での操作を終了する
/var/www # exit
exit
$ 

プロジェクト作成が完了すると、~/www/cakephp-with-docker/src の中にCakePHPのプロジェクトファイルが作成されます。

Users/
└ {ユーザー名}/
  └ www/
    └ cakephp-with-docker/
      ├ docker-compose.yml
      ├ src/  ↓新しく作成されている
      │ ├ bin/
      │ ├ config/
      │ ├ ...
      │
      └ docker/
         ├ nginx/
         │ ├ default.conf
         ├ php/
         │ ├ Dockerfile
         │ └ php.ini
         └ mysql/
           └ conf.d/
             └ my.cnf

最後にGoogle ChromeやSafariなどのブラウザで http://localhost:34251/ へアクセスし、CakePHPの初期画面が表示されればCakePHPのインストールは完了です。

ただ、画像の左下を見てもらうと『Database』の部分が CakePHP is NOT able to connect to the database. を表示されており、データベースへの接続ができていないことがわかります。

次にデータベースへ接続するための設定を行います。

データベースの接続設定

app_local.php

次にデータベースに関する設定が書かれている app_local.php ファイルを変更します。
~/www/cakephp-with-docker/scr/configフォルダにapp_local.example.php というファイルがあるので、それをコピーして app_local.php というファイル名に書き換えて、その内容を変更します。
(もしapp_local.php が既にある場合はそちらを変更しますので、コピーは不要です)

変更する内容は、docker-compose.yml で設定したデータベースの設定内容です。

app_local.php

...

    'Datasources' => [
        'default' => [
            'host' => 'db',    // localhost から db へ(MySQLコンテナのサービス名を指定することで、コンテナのホストIPを指定してくれる)
            /*
             * CakePHP will use the default DB port based on the driver selected
             * MySQL on MAMP uses port 8889, MAMP users will want to uncomment
             * the following line and set the port accordingly
             */
            //'port' => 'non_standard_port_number',

            'username' => 'user',    // my_app から user へ
            'password' => 'secret',

            'database' => 'sample',  // my_app から sample へ

...

app.php

次に app.php ファイルを変更します。
~/www/cakephp-with-docker/scr/configフォルダにあります。

app.php

...

            /*
             * For MariaDB/MySQL the internal default changed from utf8 to utf8mb4, aka full utf-8 support, in CakePHP 3.6
             */
            'encoding' => 'utf8mb4',    // コメントアウト(//)をはずす

...

接続確認

CakePHPの画面に戻って、画面をリロードしてみると、先程の『Database』の部分が CakePHP is able to connect to the database. となっているかと思います。


以上になります。

今回新たにCakePHPでの開発をすることになったため、合わせて記事にしました。
Enjoy CakePHP on Docker!

もし不明点があればTwitterまで!