質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.31%
Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

Q&A

1回答

2118閲覧

DockerでNext.jsとLaravelの環境を構築し、LaravelBrezeを導入するとクロスポリシーエラーが発生する

erfechkun

総合スコア17

Next.js

Next.jsは、Reactを用いたサーバサイドレンダリングなどを行う軽量なフレームワークです。Zeit社が開発しており、nextコマンドでプロジェクトを作成することにより、開発環境整備が整った環境が即時に作成できます。

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Docker

Dockerは、Docker社が開発したオープンソースのコンテナー管理ソフトウェアの1つです

0グッド

0クリップ

投稿2023/08/21 12:59

編集2023/08/21 13:04

実現したいこと

・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環境でプロジェクト構築手順

  1. windowsターミナルからubuntuを選択しフォルダを作成しVsCodeで開く(フォルダ名はMyApp)
  2. プロジェクトを以下のような構成で作成する

イメージ説明
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

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

\Fruitcake\Cors\HandleCors::class

このライブラリの更新が止まっているようなので、Laravel標準のcorsミドルウエア使えばいいと思います。
選べるならLaravel8ではなく9 or 10にした方がいいということです。

Laravel9 or 10 だとHttpのKernel.phpに \Illuminate\Http\Middleware\HandleCors::class,が標準で書いてあると思います。

問題を切り分けるためにcors.phpの
'allowed_origins' => [env('FRONTEND_URL', 'http://localhost:3000')],を
'allowed_origins' => ['*']にして動作するか試してみてはどうでしょうか。

サーバー側でdd(config('cors.allowed_origins')); したら何が表示されるか。
cors.allowed_originsに意図した値が入ってないなら一度php artisan config:clear でキャッシュクリアしてみてはどうでしょう。

投稿2023/08/25 23:30

niiyz

総合スコア131

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

erfechkun

2023/08/30 06:32 編集

ご回答ありがとうございます。しかし、いまだ問題は解決しておりません。ご指摘の通り、以下の項目を修正しましたが、変わらずクロスポリシーエラーが発生します。 ・LaravelのバージョンをLaravel9 or 10 にする ・'allowed_origins' => ['*']にする サーバー側でdd(config('cors.allowed_origins'))を設定する方法はよくわかりませんでした。 またAPI通信をするためのポート番号の指定をlocallhostで指定するのではなく、コンテナ名とポート番号で指定すれば治ると思い、Next.jsとLaravelの.envファイルを以下のように修正しましたが、解決しませんでした。 ■Laravelの.envファイル  #変更前  APP_URL=http://localhost:8000  FRONTEND_URL=http://localhost:3000  #変更後  APP_URL=http://webserver:80  FRONTEND_URL=http://client:3000 ■Next.jsの.env.localファイルと.env.exampleファイル(どちらも全く同じ内容)  #変更前  NEXT_PUBLIC_BACKEND_URL=http://localhost:8000  #変更後 NEXT_PUBLIC_BACKEND_URL=http://webserver:80
niiyz

2023/08/31 02:18

エラーになっているページをChromeのデペロッパーツールで見て [ネットワーク]タブでhttp://localhost:8000/api/userなりhttp://webserverを選択して[ヘッダー]-[レスポンスヘッダー]の項目に「Access-Control-Allow-Origin:」が存在して値が存在しますか? Access-Control-Allow-Origin: * ならどこからでもOK Access-Control-Allow-Origin: http://client:3000 ならhttp://client:3000を許可しているというサーバー側の設定になると思います。 これが設定されていないとフロント側のドメインが弾かれているということになります。 フロント側の設定としてはaxiosにwithCredentials: trueが書いてあるので問題ないのではと思ってます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.31%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問