DockerでCakePHP+Postgresの開発環境をサクッと作る

8 min read読了の目安(約7500字

概要

この度仕事でCakePHPアプリケーションを扱うことになったので自分用にDockerでCakePHPの構築手順をまとめておこうと思います。
不備とか不具合があったら教えていただけたらありがたいです。

ゴール

CakePHP3.9とPostgresを構築してWelcomeページの表示まで行います。
作る環境は下記

  • CakePHP3.9.6
  • Postgres さいしん(latestでインストールするのでその時の最新が入ります。)
  • Apatch2

前提条件

Docker実行環境がある前提

ディレクトリとファイル作成

今回は「cake_starter」という名前でPJを作成します。
自分のプロジェクトに合わせて全置換で差し替えてください。
ディレクトリ

/cake_starter
├─ /db       # データの保存先ディレクトリ
├─ /web      # アプリケーションコードの保存先ディレクトリ
├─ Dockerfile
└─ docker-compose.yml

作成したファイルを下記のようにそれぞれ記載してください。

DockerFile
FROM php:7.4-apache

# apache
ENV APACHE_DOCUMENT_ROOT /var/www/html/cake_starter/webroot
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf \
    && sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf \
    && a2enmod rewrite
ENV DEBCONF_NOWARNINGS=yes
RUN apt-get update && apt-get install -y \
    libicu-dev \
    zip \
    unzip \
    libpq-dev \
    && docker-php-ext-install -j$(nproc) intl \
    && docker-php-ext-install -j$(nproc) pdo_pgsql
RUN ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
COPY . /var/www/html
ENV COMPOSER_ALLOW_SUPERUSER 1
COPY --from=composer /usr/bin/composer /usr/bin/composer
WORKDIR /var/www/html/cake_starter
docker-compose.yml
version: '3'
services:
  cake_web:
    container_name: cake_web
    build: .
    volumes:
      - ./web:/var/www/html/cake_starter
    ports:
      - "80:80"
  cake_db: 
    image: postgres:latest
    container_name: cake_db
    environment: 
      POSTGRES_DB: cake_db
      POSTGRES_ROOT_PASSWORD: password
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: password
    ports:
      - 5432:5432 
    volumes:
      - ./db:/var/lib/postgresql/data

ビルドと起動

例の如くdocker-compose.ymlが設置されているディレクトリで下記を実行してください。

docker-compose up -d

モリモリビルドが始まって特にエラーが起きなければ成功です。
Docker for desktopを使用している方はDashboardを開いてコンテナが起動しているのを確認してください。

CakePHPインストール

まずは起動しているWebコンテナへログインします。

docker exec -it cake_web bash

Webコンテナへのログインができたら下記のコマンドでCakePHPをインストール!

composer create-project --prefer-dist cakephp/app:3.9.* .
Set Folder Permissions ? (Default to Y) [Y,n]? Y

途中でパーミッションについて聞かれるので「Y」と元気に答えてください。
インストールが完了すると「web」ディレクトリにCakePHPのファイルがブリブリ作られます。

ちなみに

CakePHPのインストール途中で真っ赤な文字で下記のワーニングが出ることがあります。

Action required!
The CakePHP plugin installer v1.3+ no longer requires the
"post-autoload-dump" hook. Please update your app's composer.json
file and remove usage of
Cake\Composer\Installer\PluginInstaller::postAutoloadDump

ビビりますが、エラーではないので落ち着きましょう。
放っておいても大丈夫ですが、Composerコマンドを使うたびに表示されてしまうので、メッセージに表示されている通り対処します。
下記ファイルを開き、「PluginInstaller::postAutoloadDump」で検索して見つかった行を削除しておきましょう。

cake_starter/web/composer.json

composer.json
"scripts": {
    "post-install-cmd": "App\\Console\\Installer::postInstall",
    "post-create-project-cmd": "App\\Console\\Installer::postInstall",
    ☆↓この行を削除!
    "post-autoload-dump": "Cake\\Composer\\Installer\\PluginInstaller::postAutoloadDump",
    "check": [
        "@test",
        "@cs-check"
    ],
    "cs-check": "phpcs --colors -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/ config/ webroot/",
    "cs-fix": "phpcbf --colors -p --extensions=php --standard=vendor/cakephp/cakephp-codesniffer/CakePHP src/ tests/ config/ webroot/",
    "stan": "phpstan analyse -l 5 src/",
    "stan-setup": "cp composer.json composer.backup && composer require --dev phpstan/phpstan-shim:^0.11 && mv composer.backup composer.json",
    "test": "phpunit --colors=always"
},

DB設定

この時点でhttp://localhost/ へアクセスするとCakePHPのエラーが表示されます。

DBがどうのと言われているので設定しましょう。
下記ファイルにdocker-compose.ymlに記述したDB接続設定とPostgresの設定を書きます。

cake_starter/web/config/app.php
//use Cake\Database\Driver\Mysql;
use Cake\Database\Driver\Postgres;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  'Datasources' => [
        'default' => [
            'className' => Connection::class,
            //'driver' => Mysql::class,
            'driver' => Postgres::class,
            'persistent' => false,
            //'host' => 'localhost',
            'host' => 'cake_db',
            'username' => 'postgres',
            'password' => 'password',
            'database' => 'cake_db',
            /*
             * You do not need to set this flag to use full utf-8 encoding (internal default since CakePHP 3.6).
             */
            //'encoding' => 'utf8mb4',
            'timezone' => 'UTC',
            'flags' => [],
            'cacheMetadata' => true,
            'log' => false,
            'quoteIdentifiers' => false,
            'url' => env('DATABASE_URL', null),
        ],
        'test' => [
            'className' => Connection::class,
            //'driver' => Mysql::class,
            'driver' => Postgres::class,
            'persistent' => false,
            //'host' => 'localhost',
            'host' => 'cake_db',
            'username' => 'postgres',
            'password' => 'password',
            'database' => 'cake_db',
            //'encoding' => 'utf8mb4',
            'timezone' => 'UTC',
            'cacheMetadata' => true,
            'quoteIdentifiers' => false,
            'log' => false,
            //'init' => ['SET GLOBAL innodb_stats_on_metadata = 0'],
            'url' => env('DATABASE_TEST_URL', null),
        ],
    ],

再度 http://localhost/ へアクセスするとWelcomeページが表示されます。

やったー!これでモリモリWebサービス作って億万長者になるぞっていきたいですが、よく見るとDatabase接続エラーが出ていますので設定を修正します。

シンDB設定

先ほど編集したapp.phpと同じディレクトリにあるapp_local.phpを編集します。

cake_starter/web/config/app_local.php
'Datasources' => [
        'default' => [
            //'host' => 'localhost',
            'host' => 'cake_db',
            /*
             * 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' => 'my_app',
            'username' => 'postgres',
            //'password' => 'secret',
            'password' => 'password',
            //'database' => 'my_app',
            'database' => 'cake_db',
            'log' => true,
            'url' => env('DATABASE_URL', null),
        ],
    ],

このapp_local.phpは環境を切り替える際に使われるファイルで、app.phpと同じディレクトリ存在しているときはこっちの設定で上書きされるそうです。
CakePHP4のリファレンスに書いてあったのでそのことを知らずに1時間程ハマりました…

再度Welcomeページを開くとDBへの接続に成功しています。

これでセットアップは完了です。

あとがき

一部DB接続でハマりましたが結構簡単にセットアップができました。
Laravelと同様初めからディレクトリが作られているので作成時や編集時にディレクトリ構成に迷ったりだとか無駄なことに時間を使わずに作ることができるのでそこがFlaskやDjangoと比べて好きなところです。

今回のコードは下記にコミットしていますのでクローン&ビルドしてもらえれば諸々設定した状態で使えます。

https://github.com/chegeba/cake_starter
諸々のCRUD処理などはまた機会があれば書いてみようと思います。
Enjoy!

参考

https://book.cakephp.org/3/ja/index.html
https://book.cakephp.org/4/ja/quickstart.html
https://ichinari.work/cakephp_Docker_20190926
http://shin-godzilla.jp/