プロジェクトの構成
project-root/
├── docker/ # Docker関連ファイル
│ ├── nginx/ # Nginxの設定
│ ├── php/ # PHPの設定
│ └── mysql/ # MySQLの設定
├── backend/ # Laravelプロジェクト
├── frontend/ # Reactプロジェクト
├── docker-compose.yml # Docker Compose設定
└── .env # 環境変数
1. 必要なフォルダ構造を準備
mkdir sample-project
cd sample-project
mkdir -p docker/nginx docker/php docker/mysql
2. Dockerの設定
docker-compose.yml の作成
プロジェクトのルートディレクトリに docker-compose.yml
ファイルを作成します。
services:
# PHPサービス
app:
build:
context: ./docker/php
volumes:
- ./backend:/var/www/html
depends_on:
- db
networks:
- laravel-network
# Nginxサービス
web:
build:
context: ./docker/nginx
ports:
- "80:80"
volumes:
- ./backend:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- laravel-network
# MySQLサービス
db:
image: mysql:8.0
ports:
- "3306:3306"
environment:
MYSQL_DATABASE: laravel_db
MYSQL_ROOT_PASSWORD: root
MYSQL_USER: laravel
MYSQL_PASSWORD: secret
volumes:
- mysql-data:/var/lib/mysql
networks:
- laravel-network
# Node.jsサービス(React用)
node:
image: node:18-alpine
working_dir: /app
volumes:
- ./frontend:/app
ports:
- "3000:3000"
command: sh -c "if [ -f package.json ]; then npm install && npm start; else echo 'Waiting for frontend setup...'; fi"
networks:
- laravel-network
networks:
laravel-network:
driver: bridge
volumes:
mysql-data:
PHPの設定
docker/php/Dockerfile
を作成します。
FROM php:8.2-fpm
# 必要なパッケージのインストール
RUN apt-get update && apt-get install -y \\
git \\
curl \\
libpng-dev \\
libonig-dev \\
libxml2-dev \\
zip \\
unzip
# PHPの拡張機能をインストール
RUN docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Composerのインストール
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# 作業ディレクトリの設定
WORKDIR /var/www/html
# UIDとGIDを設定して権限の問題を回避
RUN usermod -u 1000 www-data
⚠️ /usr/bin/composer
の/usrを/userに間違わないように気を付けてください(体験談)。
Nginxの設定
docker/nginx/Dockerfile
を作成します。
FROM nginx:1.23-alpine
WORKDIR /var/www/html
Nginxの設定ファイル docker/nginx/default.conf
を作成します。
server {
listen 80;
index index.php index.html;
server_name localhost;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /var/www/html/public;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \\.php$ {
try_files $uri =404;
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;
}
}
3. Laravelプロジェクトの作成
Dockerを使用してLaravelプロジェクトを作成します。
# Dockerイメージのビルド
docker compose build
# Laravelプロジェクトを作成
docker compose run --rm app composer create-project laravel/laravel .
# 権限を設定
sudo chown -R $(id -un):$(id -gn) backend
💡 Hint
docker compose run --rm app は、Docker Compose を使って「一時的なコンテナを起動してコマンドを実行し、終了後にそのコンテナを削除する」という操作を行うコマンドです。
一時的に実行するコマンド(artisan, composer, npm など)に使い、一回実行系に最適です。
長時間動かす常駐型サービス(webサーバやDBなど)はdocker compose up を使います。
⚠️ 今回はLaravel 12がインストールされました。
💡 Hint
権限の設定についてはこちらで説明しています。
Laravelの環境設定
backend/.env
ファイルを編集して、データベース接続情報を設定します。
DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel
DB_PASSWORD=secret
💡 Hint
docker-compose.ymlのMySQLサービスで設定しているものと同じ値が入ります。
4. Reactプロジェクトの作成
次に、Reactプロジェクトを作成します。
# Reactプロジェクトを作成
docker compose run --rm node sh -c "npx create-react-app . --template typescript"
# 権限を設定
sudo chown -R $(id -un):$(id -gn) frontend
Reactの設定
API通信のためのプロキシ設定を行います。frontend/package.json
に以下の行を追加します。
"proxy": "<http://web>"
5. CORSの設定
Laravelで異なるオリジンからのリクエストを許可するために、CORSを設定します。
config/cors.php
設定ファイルは、デフォルトで公開していないため作成します。
# cors.phpファイルを作成
docker compose run --rm app php artisan config:publish cors
config/cors.php
を編集して、以下のように設定します。
<?php
return [
'paths' => ['api/*'],
'allowed_methods' => ['*'],
'allowed_origins' => ['<http://localhost:3000>'],
'allowed_origins_patterns' => [],
'allowed_headers' => ['*'],
'exposed_headers' => [],
'max_age' => 0,
'supports_credentials' => true,
];
6. Laravel SanctumによるAPI認証の設定
LaravelでAPIの認証を簡単に実装するために、Sanctumを使用します。
# Sanctumのインストール
docker compose run --rm app php artisan install:api
backend/bootstrap/app.php
に以下を記述します。
->withMiddleware(function (Middleware $middleware) {
// apiミドルウェアグループの最後に追加
$middleware->api(append: [
\\Laravel\\Sanctum\\Http\\Middleware\\EnsureFrontendRequestsAreStateful::class,
]);
})
💡 Hint
Laravel 11以降ではミドルウェアの設定の書き方が変わったようなので注意してください。
こちらを参考にしました。
7. バックエンドAPIの作成
シンプルなAPIを作成してみましょう。
# コントローラーの作成
docker compose run --rm app php artisan make:controller API/TaskController --api
backend/app/Http/Controllers/API/TaskController.php
を編集します。
<?php
namespace App\\Http\\Controllers\\API;
use App\\Http\\Controllers\\Controller;
use Illuminate\\Http\\Request;
class TaskController extends Controller
{
/**
* タスク一覧の取得
*
* @return \\Illuminate\\Http\\Response
*/
public function index()
{
$tasks = [
['id' => 1, 'title' => 'タスク1', 'completed' => false],
['id' => 2, 'title' => 'タスク2', 'completed' => true],
['id' => 3, 'title' => 'タスク3', 'completed' => false],
];
return response()->json($tasks);
}
}
APIルートを設定します。backend/routes/api.php
を編集します。
<?php
use App\\Http\\Controllers\\API\\TaskController;
use Illuminate\\Http\\Request;
use Illuminate\\Support\\Facades\\Route;
Route::get('/user', function (Request $request) {
return $request->user();
})->middleware('auth:sanctum');
// タスク一覧取得のルート
Route::get('/tasks', [TaskController::class, 'index']);
8. フロントエンドでAPIの利用
必要なパッケージをインストールします。
docker compose run --rm node npm install axios
APIからデータを取得するコンポーネントを作成します。frontend/src/App.tsx
を編集します。
import React, { useEffect, useState } from 'react';
import logo from './logo.svg';
import './App.css';
import axios from 'axios';
interface Task {
id: number;
title: string;
completed: boolean;
}
function App() {
const [tasks, setTasks] = useState<Task[]>([]);
const [loading, setLoading] = useState<boolean>(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
// APIからタスク一覧を取得
const fetchTasks = async () => {
try {
const response = await axios.get('/api/tasks');
setTasks(response.data);
setLoading(false);
} catch(err) {
setError('タスクの取得に失敗しました');
setLoading(false);
}
};
fetchTasks();
}, []);
if (loading) return <div>読み込み中...</div>;
if (error) return <div>{error}</div>;
return (
<div className="App">
<header className="App-header">
<h1>タスク一覧</h1>
</header>
<main>
<ul>
{tasks.map(task => (
<li key={task.id} style={{ textDecoration: task.completed ? 'line-through' : 'none' }}>
{task.title}
</li>
))}
</ul>
</main>
</div>
);
}
export default App;
9. 開発環境の起動
すべての設定が完了したら、Docker Composeを使って開発環境を起動します。
docker compose up -d
これで以下のURLでアプリケーションにアクセスできます:
- Laravel: http://localhost
- React: http://localhost:3000
10. 開発環境の使用方法
Laravelコマンドの実行
# Artisanコマンドの実行
docker compose exec app php artisan <command>
# 例: マイグレーション
docker compose exec app php artisan migrate
# 例: シーダーの実行
docker compose exec app php artisan db:seed
npmコマンドの実行
# npmコマンドの実行
docker compose exec node npm <command>
# 例: パッケージのインストール
docker compose exec node npm install <package-name>
# 例: ビルド
docker compose exec node npm run build
データベースへのアクセス
# MySQLへの接続
docker compose exec db mysql -u laravel -p
11. 本番環境への準備
本番環境にデプロイする前に、以下のステップを実行してください。
フロントエンドのビルド
docker compose exec node npm run build
環境変数の設定
本番環境用の .env
ファイルを作成し、適切な設定を行います。
キャッシュの最適化
docker compose exec app php artisan config:cache
docker compose exec app php artisan route:cache
docker compose exec app php artisan view:cache
こちらをとても参考にさせていただきました。
環境による違いが出たので、勉強も兼ねて改めて復習に書いてみました。
[ここから追記]
後からTailwind CSSも入れたくなったので追記します。
Tailwind CSS バージョン 4 以降
では、npx tailwindcss init -p コマンドが使用できないため、よく見かける以下のコマンドではsh: tailwind: not found
exit status 127
が起こってしまいました。
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init
そこで調べてみたところ、こちらの2のような方法もあるようですが、今回はcreate-react-appで作ってしまったのでVite環境ではありません。
ですのでTailwindのバージョンを3に下げることで対応します。
docker compose exec node npm install -D tailwindcss@3 postcss autoprefixer
docker compose exec node npx tailwindcss init -p
これでTailwind CSSもインストールできました。
コメント