本記事はこちらからの転載です。
当時、内定を頂いた転職先の業務のキャッチアップのために学習していた内容を書いたという背景があったのでした。
モチベーション
CakePHPのキャッチアップの為に簡単に環境構築を行いましたのでその記録です。
環境
- ホストOS: ubuntu20.04(wsl)
- PHP: 7.3
- CakePHP: 4.*
アプリとDBだけの簡単な構成でdocker-compose.ymlを作成します。
ハマりポイントとしてはmysqlのバージョンです。
はじめは8.0で構築したのですが以下のエラーでmyappとdbの疎通が出来ませんでした。
Error: [InvalidArgumentException] There was a problem connecting to the database: SQLSTATE[HY000] [2054] The server requested authentication method unknown to the client in /var/www/html/mycakeapp/vendor/robmorgan/phinx/src/Phinx/Db/Adapter/PdoAdapter.php
調べたところこれでした。今回の本題ではないのでmysqlを5.7に下げて回避しました。
docker-compose.yml
version: "3.7"
services:
myapp:
build:
context: ./docker
dockerfile: Dockerfile
ports:
- "8888:80"
- "8765:8765"
tty: true
stdin_open: true
volumes:
- ./html:/var/www/html
db:
image: mysql:5.7
volumes:
- "./db:/docker-entrypoint-initdb.d"
environment:
MYSQL_DATABASE: sampledb
MYSQL_USER: sample-user
MYSQL_PASSWORD: 12345678
MYSQL_ROOT_PASSWORD: 12345678
Dockerfile
にはCakeが依存しているPHP拡張を入れます。
FROM php:7.3-apache
RUN apt-get update \
&& apt-get install -y unzip libicu-dev \
&& docker-php-ext-install intl \
&& docker-php-ext-install pdo_mysql \
&& a2enmod rewrite \
&& apt-get clean \
&& rm -fr /var/lib/apt/lists/*
mysqlの初期化クエリarticles.sql
はcakeのチュートリアルから持ってきた物を置いておきます。
USE sampledb;
CREATE TABLE users (
id INT AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
created DATETIME,
modified DATETIME
);
CREATE TABLE articles (
id INT AUTO_INCREMENT PRIMARY KEY,
user_id INT NOT NULL,
title VARCHAR(255) NOT NULL,
slug VARCHAR(191) NOT NULL,
body TEXT,
published BOOLEAN DEFAULT FALSE,
created DATETIME,
modified DATETIME,
UNIQUE KEY (slug),
FOREIGN KEY user_key (user_id) REFERENCES users(id)
) CHARSET=utf8mb4;
CREATE TABLE tags (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(191),
created DATETIME,
modified DATETIME,
UNIQUE KEY (title)
) CHARSET=utf8mb4;
CREATE TABLE articles_tags (
article_id INT NOT NULL,
tag_id INT NOT NULL,
PRIMARY KEY (article_id, tag_id),
FOREIGN KEY tag_key(tag_id) REFERENCES tags(id),
FOREIGN KEY article_key(article_id) REFERENCES articles(id)
);
INSERT INTO users (email, password, created, modified)
VALUES
('cakephp@example.com', 'secret', NOW(), NOW());
INSERT INTO articles (user_id, title, slug, body, published, created, modified)
VALUES
(1, 'First Post', 'first-post', 'This is the first post.', 1, now(), now());
最終的なフォルダ構成
は以下の通り
.
├── /docker
│ ├── Dockerfile
│ └── /initdb
│ └── articles.sql
├── /html // cakeのアプリケーションが入る
└── docker-compose.yml
docker compose up -d
で起動します。
projectを作成
起動中のコンテナにアタッチしてcakeのプロジェクトを作成していきます。
$ docker compose exec myapp bash
$ cd ..
$ php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
php -r "if (hash_file('sha384', 'composer-setup.php') === '756890a4488ce9024fc62c56153228907f1545c228516cbf63f885e036d37e9a59d27d63f46af1d4d07ee0f76181c7d3') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
php composer-setup.php
php -r "unlink('composer-setup.php');"
$ php composer.phar create-project --prefer-dist cakephp/app:4.* html
普段はcomposer公式dockerイメージを使っているのですが、create-project
で依存関係が無いと怒られ、上手く回避できなかったのでcomposer.pharを入れて使いました。
閑話休題
全然本題と関係ない話なのですが、composerの選択肢は以下3つだと思うんですがみなさんはどうしているのか気になります。
- composerをグローバルインストールして使う
- composer公式dockerイメージを使う
- composer.pharをプロジェクトローカルに入れる
Permission denied
話を戻します。
docker compose up -d
した状態でとりあえずhttp://localhost:8888/
にアクセスすると以下のエラーが出ます。
Warning (512): SplFileInfo::openFile(/var/www/html/tmp/cache/models/myapp_cake_model_debug_kit_requests): failed to open stream: Permission denied [CORE/src/Cache/Engine/FileEngine.php, line 387]
/tmpがroot権限になっているので権限を変更すれば解決します。
sudo chown -R www-data:www-data tmp
database接続設定
あとはDBに接続できるようにしてやります。余談ですがconfig
配下の設定ファイルが多くてややこしいのでここで無駄にハマりました。
config/app_local.php
'Datasources' => [
'default' => [
'className' => 'Cake\Database\Connection',
'driver' => 'Cake\Database\Driver\Mysql',
'persistent' => false,
// 以下の設定項目をdocker-compose.ymlに合せる
'host' => 'db', // servicesの名称
'username' => 'sample-user', // MYSQL_USER
'password' => '12345678', // MYSQL_PASSWORD
'database' => 'sampledb', // MYSQL_DATABASE
// ここまで
'encoding' => 'utf8mb4',
'timezone' => 'UTC',
'cacheMetadata' => true,
],
CakePHP is able to connect to the database.
と表示されコック帽が緑色になったらDBとの導通OK
ここからはチュートリアルをやったり、簡単なアプリを作ってみたりしながら勉強していきましょう。