Laravel + React + Dockerで開発環境構築

はじめに

モダンなウェブアプリケーション開発において、LaravelとReactの組み合わせは非常に人気があります。Laravelの堅牢なバックエンドフレームワークとReactの柔軟なフロントエンドライブラリを組み合わせることで、高品質なウェブアプリケーションを効率的に開発できます。

さらに、Docker を導入することで、開発環境の構築と共有が容易になり、「自分の環境では動くのに」という問題を解決できます。この記事では、Laravel、React、そしてDockerを組み合わせた開発環境の構築方法を詳しく解説します。

前提条件

この記事を進めるにあたり、以下のツールがインストールされていることを前提とします:

  • Docker Desktop
  • Git
  • コードエディタ(VS Code など)

プロジェクトの構成

今回構築する開発環境は以下のような構成になります:

project-root/
├── docker/              # Docker関連ファイル
│   ├── nginx/           # Nginxの設定
│   ├── php/             # PHPの設定
│   └── mysql/           # MySQLの設定
├── backend/             # Laravelプロジェクト
├── frontend/            # Reactプロジェクト
├── docker-compose.yml   # Docker Compose設定
└── .env                 # 環境変数

1. プロジェクトのセットアップ

まず、プロジェクトのルートディレクトリを作成し、必要なフォルダ構造を準備します。

mkdir laravel-react-docker
cd laravel-react-docker
mkdir -p docker/nginx docker/php docker/mysql

2. Dockerの設定

docker-compose.yml の作成

プロジェクトのルートディレクトリに docker-compose.yml ファイルを作成します。

version: '3'
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

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 $USER:$USER backend

Laravelの環境設定

backend/.env ファイルを編集して、データベース接続情報を設定します。

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel_db
DB_USERNAME=laravel
DB_PASSWORD=secret

4. Reactプロジェクトの作成

次に、Reactプロジェクトを作成します。

# Reactプロジェクトを作成
docker-compose run --rm node sh -c "npx create-react-app . --template typescript"

# 権限を設定
sudo chown -R $USER:$USER frontend

Reactの設定

API通信のためのプロキシ設定を行います。frontend/package.json に以下の行を追加します。

"proxy": "http://web"

5. CORSの設定

Laravelで異なるオリジンからのリクエストを許可するために、CORSを設定します。

# LaravelのCORSパッケージをインストール
docker-compose run --rm app composer require fruitcake/laravel-cors

backend/app/Http/Kernel.php$middleware 配列に \Fruitcake\Cors\HandleCors::class を追加します。

backend/config/cors.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 composer require laravel/sanctum

# Sanctumのインストール
docker-compose run --rm app php artisan sanctum:install

# マイグレーションの実行
docker-compose run --rm app php artisan migrate

backend/app/Http/Kernel.phpapi ミドルウェアグループに \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class を追加します。

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    'throttle:api',
    \Illuminate\Routing\Middleware\SubstituteBindings::class,
],

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 Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\API\TaskController;

// ユーザー情報取得のルート
Route::middleware('auth:sanctum')->get('/user', function (Request $request) {
    return $request->user();
});

// タスク一覧取得のルート
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 axios from 'axios';
import './App.css';

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

12. トラブルシューティング

権限の問題

コンテナ内で生成されたファイルのパーミッション問題が発生した場合、以下のコマンドを実行します。

sudo chown -R $USER:$USER backend
sudo chown -R $USER:$USER frontend

コンテナ間の通信問題

コンテナ間で通信できない場合、ネットワーク設定を確認し、必要に応じて再起動します。

docker-compose down
docker-compose up -d

ポートの衝突

ポートが既に使用されている場合、docker-compose.yml ファイルでポート設定を変更します。

ports:
  - "8080:80"  # 80ポートの代わりに8080を使用

まとめ

この記事では、Laravel、React、そしてDockerを組み合わせた開発環境の構築方法を解説しました。このセットアップにより、以下のメリットが得られます:

  1. 環境の一貫性: Dockerを使用することで、開発環境と本番環境の一貫性を確保できます。
  2. 簡単なセットアップ: 新しいチームメンバーがプロジェクトに参加する際、簡単に開発環境を構築できます。
  3. 分離された開発: バックエンド(Laravel)とフロントエンド(React)の開発を明確に分離できます。
  4. スケーラビリティ: 必要に応じてサービスを追加または変更できます。

この構成を基に、あなたのプロジェクトに合わせてカスタマイズしてください。Dockerを活用することで、開発プロセスがよりスムーズになり、「自分の環境では動くのに」という問題から解放されるでしょう。

次のステップとして、CI/CDパイプラインの設定や、本番環境へのデプロイ方法などを検討することをお勧めします。

コメント

タイトルとURLをコピーしました