実現したいこと
・Docker環境でLaravelとNext.jsを構築し、認証機能はLaravelBreezeを使いNext.jsの3000番ポートとLaravelの8000番ポートでAPI通信したい
発生した問題
DockerでLaravelとNext.jsの環境を構築しNext.jsのサーバー(3000番)をDockerDescTopから起動するとコンソールに以下のようなエラーメッセージが表示されました。
エラーメッセージ1
Access to XMLHttpRequest at 'http://localhost:8000/api/user' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
エラーメッセージ2
GET http://localhost:8000/api/user net::ERR_FAILED
なおLaravelBreezeを導入すると画面右上に表示されるloginとregisterボタンは正常に表示されています。新規登録やログイン機能はError: Network Errorと表示され実行できません
Docker環境でプロジェクト構築手順
- windowsターミナルからubuntuを選択しフォルダを作成しVsCodeで開く(フォルダ名はMyApp)
- プロジェクトを以下のような構成で作成する
clientフォルダはNext.jsプロジェクトを入れる用。serverフォルダはLaravelプロジェクトを入れる用です。(どちらも今現在は空)
それぞれのファイルの中身は以下の通りです。
docker-compose.ymlの内容
compose.yml
1version: '3' 2services: 3 webserver: 4 build: 5 context: . 6 dockerfile: Dockerfile.laravel 7 container_name: laravel_apache 8 volumes: 9 - ./server:/var/www/html 10 ports: 11 - "8000:80" 12 depends_on: 13 - db 14 networks: 15 - app-network 16 client: 17 build: 18 context: . 19 dockerfile: Dockerfile.client 20 container_name: nextjs_client 21 volumes: 22 - ./client:/app 23 ports: 24 - "3000:3000" 25 26 networks: 27 - app-network 28 29 db: 30 image: mysql 31 container_name: mysql_db 32 environment: 33 MYSQL_ROOT_PASSWORD: root 34 MYSQL_DATABASE: laravel 35 volumes: 36 - db-data:/var/lib/mysql 37 ports: 38 - "3306:3306" 39 networks: 40 - app-network 41 42 43 phpmyadmin: 44 image: phpmyadmin/phpmyadmin 45 container_name: phpmyadmin 46 environment: 47 PMA_HOST: mysql_db 48 PMA_PORT: 3306 49 ports: 50 - "8080:80" 51 networks: 52 - app-network 53 54networks: 55 app-network: 56 driver: bridge 57 58volumes: 59 db-data: 60
Dockerfile.laravelの内容(Laravel用のDockerファイル)
Dockerfile.laravel
1# Dockerfile.laravel 2FROM php:8.1-apache 3 4# 必要なライブラリをインストール 5RUN apt-get update && apt-get install -y git unzip libpq-dev && docker-php-ext-install pdo pdo_mysql 6 7# Composerをインストール 8COPY --from=composer:2 /usr/bin/composer /usr/bin/composer 9 10# プロジェクトディレクトリを設定 11WORKDIR /var/www/html 12 13# Apacheの設定を反映 14COPY ./apache-config/000-default.conf /etc/apache2/sites-available/000-default.conf 15 16# Apacheを前景で実行(コンテナが起動している間はapacheを起動し続ける設定) 17CMD ["apache2ctl", "-D", "FOREGROUND"] 18
Dockerfile.clientの内容(Next.js用のDockerファイル)
Dockerfile.client
1# Dockerfile.client 2FROM node:latest 3 4WORKDIR /app 5 6# グローバルにNext.jsをインストール 7RUN npm install -g create-next-app 8 9# Next.jsの開発サーバーを起動 10CMD ["npm", "run", "dev"]
000-default.confの内容(apacheの設定ファイル)
デフォルトでコメントアウトされていた部分は載せていません
default.conf
1<VirtualHost *:80> 2 ServerAdmin webmaster@localhost 3 DocumentRoot /var/www/html/public 4 5 #追加 6 <Directory /var/www/html/public> 7 Options Indexes FollowSymLinks 8 AllowOverride All 9 Require all granted 10 </Directory> 11 12 ErrorLog ${APACHE_LOG_DIR}/error.log 13 CustomLog ${APACHE_LOG_DIR}/access.log combined 14 15</VirtualHost>
3.dokerコンテナ作成&起動する
Terminal
1docker-compose build 2docker-compose up -d
4.ホスト側でファイルを編集できるようにプロジェクトのルートディレクトリで以下のコマンドを実行
Terminal
1sudo chown -R $USER:$USER .
4.Laravel用コンテナに入りLaravelをインストールする
Terminal
1#Laravel用コンテナに入る 2docker exec -it laravel_apache bash 3 4#Laravel8をインストールする 5composer create-project --prefer-dist laravel/laravel:^8.0 .
5.指定のフォルダとファイルの所有者と所有グループをwww-dataに変更&権限を指定
Terminal
1chown -R www-data:www-data storage bootstrap/cache 2chmod -R 775 storage bootstrap/cache
LaravelBreeze導入手順
1.以下のコマンドでLaravelコンテナに入る
docker exec -it laravel_apache bash
2. これ以降はLaravelBreezeを導入する下記のサイト通りに行いました。
(composer require laravel/breeze --devコマンドから実行)
Laravel Breeze API + ReactのフレームワークNext.jsの設定方法
3.node_modules/.bin/nextに実行権限を追加する(これをしないとNext.jsコンテナが起動しなかった)
Terminal
1chmod +x node_modules/.bin/next
上記の手順でclientフォルダにNext.jsプロジェクト、cors.phpでCORSの設定などが作成されました。
LaravelBreezeを導入したことでCORSポリシーエラーが発生しないように設定されたファイルは以下のようなものがあると思います。
ーーserverフォルダの中のものーー
cors.php
config/app.php
.env
composer.json
Kernel.php
ーーーーーーーーーーーーーーーー
ーーclientフォルダの中のものーー
.env.example
.env.local(.env.exampleと内容一緒)
axios.js
ーーーーーーーーーーーーーーーー
上記で上げたファイルの中身を明記します。
Laravel側のファイル達
cors.php
1<?php 2 3return [ 4 'paths' => ['*'], 5 6 'allowed_methods' => ['*'], 7 8 'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')], 9 10 'allowed_origins_patterns' => [], 11 12 'allowed_headers' => ['*'], 13 14 'exposed_headers' => [], 15 16 'max_age' => 0, 17 18 'supports_credentials' => true, 19 20];
app.php
1 'url' => env('APP_URL', 'http://localhost'), 2 3 'frontend_url' => env('FRONTEND_URL', 'http://localhost:3000'), 4 5 'asset_url' => env('ASSET_URL', null),
env
1APP_URL=http://localhost:8000 2FRONTEND_URL=http://localhost:3000
composer.json
1 "require": { 2 "php": "^7.3|^8.0", 3 "fruitcake/laravel-cors": "^2.0", 4 "guzzlehttp/guzzle": "^7.0.1", 5 "laravel/framework": "^8.75", 6 "laravel/sanctum": "^2.11", 7 "laravel/tinker": "^2.5" 8 },
Kernel.php
1 protected $middleware = [ 2 // \App\Http\Middleware\TrustHosts::class, 3 \App\Http\Middleware\TrustProxies::class, 4 \Fruitcake\Cors\HandleCors::class, 5 \App\Http\Middleware\PreventRequestsDuringMaintenance::class, 6 \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, 7 \App\Http\Middleware\TrimStrings::class, 8 \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, 9 ]; 10 11 /** 12 * The application's route middleware groups. 13 * 14 * @var array<string, array<int, class-string|string>> 15 */ 16 protected $middlewareGroups = [ 17 'web' => [ 18 \Fruitcake\Cors\HandleCors::class,#追加 19 \App\Http\Middleware\EncryptCookies::class, 20 \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, 21 \Illuminate\Session\Middleware\StartSession::class, 22 // \Illuminate\Session\Middleware\AuthenticateSession::class, 23 \Illuminate\View\Middleware\ShareErrorsFromSession::class, 24 \App\Http\Middleware\VerifyCsrfToken::class, 25 \Illuminate\Routing\Middleware\SubstituteBindings::class, 26 ], 27 28 'api' => [ 29 \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class, 30 'throttle:api', 31 \Illuminate\Routing\Middleware\SubstituteBindings::class, 32 ], 33 ];
Laravel側のファイル達ここまで↑
Laravel側のファイル達ここまで↑
env.example
1NEXT_PUBLIC_BACKEND_URL=http://localhost:8000
env.localも全く同じ内容
axios.js
1import Axios from 'axios' 2 3const axios = Axios.create({ 4 baseURL: process.env.NEXT_PUBLIC_BACKEND_URL, 5 headers: { 6 'X-Requested-With': 'XMLHttpRequest', 7 }, 8 withCredentials: true, 9}) 10 11export default axios 12
Next.js側のファイル達ここまで↑
試したこと
fruitcake/laravel-corsというものをインストールすると良いそうなのでLaravelのバージョンを8にしました。8にするとcomposerに記載している通りデフォルトで入っていました。また先ほどのKernel.phpにも記載していますが、以下のコードを追記するとよいとあったので追加しました。
\Fruitcake\Cors\HandleCors::class,#追加
補足情報(FW/ツールのバージョンなど)
Next.jsバージョン:13.0.3
Laravelバージョン:8.83.27(ちなみにバージョン10にしてもエラーは解決せず)
dockerバージョン:24.0.2

バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/08/30 06:32 編集
2023/08/31 02:18