G’s ACADEMYの皆さん、こんにちは。
G’s ACADEMY FUKUOKA・そしてDEV03の皆さんご無沙汰してます。
G’s ACADEMY FUKUOKA DEV03・OBの自称筋肉担当です。卒業後も技術力と筋力アップに励んでいます。先日福岡校へ遊びにいったとき、同期2人とFounderの児玉さんにお会いできて通っていた時期のことを思い出しました。たくさんの熱量をいただきました。ありがとうございます。
この熱量を活かして、現役のソフトウェアエンジニア(Backend dev)らしく技術記事を書いてみます。
全てを解説すると、1冊の本が書けてしまう量なので工夫したことを簡単にまとめます。
基本的な内容が多いので復習の機会になればうれしいです。
リポジトリはこちら
https://github.com/tomohiro-dev/laravel11-nextjs-docker-template
きっかけ
- 社内で使われている一部のLaravelが11へのアップデートをすることになった
- ここ最近AWS CDK(Python)を使っていたので最新バージョンであるLaravel11のキャッチアップをする
- 最後にさわったLaravelのバージョンは…6!
- 個人開発用にもこの機会に開発環境を作っておきたい- 何かしらデプロイしたいときにすぐこの環境を使えるようにしたい
 
- 社内でも使われ始めたNext.js(TypeScript based)もコンテナ環境で構築してみる
前提としてLaravel6で作成したコードをそのままgithubで管理していたので、backendリポジトリ配下のコードを削除してから環境構築しています。
ディレクトリ構造
.
├── README.md
├── backend/
├── compose.yaml
├── docker/
│   ├── frontend-docker
│   ├── mysql
│   ├── nginx
│   └── php
└── frontend/backend/ディレクトリはLaravelのコード、compose.yamlにはコンテナの初期状態を定義、docker/ディレクトリには、Docker Imageを作るためのDockerfileなど諸々入れています。そしてfrontend/ディレクトリ内でNext.jsのコードを書いていきます。
backend/ディレクトリから順番にどのように環境を変えていったかを解説します。
backend/ディレクトリ
- service providerがbootstrap/providers.phpへの追加に変わったようなのでRouteServiceProvider.phpを作成してコードを追加する
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Route;
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;
class RouteServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap any application services.
     */
    public function boot(): void
    {
        $this->routes(function () {
            Route::prefix('api')
                ->middleware('api')
                ->group(base_path('routes/api.php'));
        });
    }
}- ルーティングを定義する
<?php
return [
    App\Providers\AppServiceProvider::class,
    App\Providers\RouteServiceProvider::class,
];今回は手動で追加したが、プロジェクト独自のServiceProviderをmakeコマンドで作った場合もbootstrap/providers.phpは自動更新されるらしい。
php artisan make:provider RouteServiceProviderhttps://laravel.com/docs/11.x/providers
- LaravelのCORS(Cross-Origin Resource Sharing)設定ファイルを作成する
Laravel11 では config配下にcors.phpがないためpublish する。 artisanコマンド php artisan config:publish corsを使ってcorsの設定ファイルを作成する。(CORS: いろんな便利なサービスを、他のところでも共有できるようにする技術)
<?php
return [
    /*
    |--------------------------------------------------------------------------
    | Next.js(http://localhost:3000)からのリクエストを許可
    |--------------------------------------------------------------------------
    | - APIリクエストの対象パス
    | - 全てのHTTPメソッドを許可
    | - Next.jsのURLを指定
    | -全てのリクエストヘッダを許可
    | -認証付きリクエストを許可しない
    |
    |
    */
    'paths' => ['api/*'],
    'allowed_methods' => ['*'],
    'allowed_origins' => ['http://localhost:3000'],
    'allowed_headers' => ['*'],
    'exposed_headers' => [],
    'max_age' => 0,
    'supports_credentials' => false,
];今回はNext.jsのローカル開発サーバーからのAPIリクエストを許可するポリシーを定義する。
- セッションデータをメモリへ保存して動作テストをするために書き換える
    // 'driver' => env('SESSION_DRIVER', 'database'),
    // セッションデータを一時的にメモリへ保存。実装時にここは設定する
    'driver' => 'array',- APIレスポンス確認用に文字列を表示させる
<?php
use Illuminate\Support\Facades\Route;
Route::get('/test', function () {
    return response()->json(['message' => 'API is working! Yeah man!']);
});compose.yamlファイル
docker-compose.ymlと書かれることが多いが、現在はcompose.yamlとするのが公式では推奨されている。
The default path for a Compose file iscompose.yaml(preferred) orcompose.ymlthat is placed in the working directory. Compose also supportsdocker-compose.yamlanddocker-compose.ymlfor backwards compatibility of earlier versions.
https://docs.docker.com/compose/intro/compose-application-model/
また、versionを定義していたが現在は非推奨、というより廃止されているので従来書いていたコードは削除。
networks:
  app-network:
    driver: bridgeネットワークで使用するドライバーを指定。bridgeは、同じホスト上のコンテナ間の通信を可能にする標準的なネットワークドライバー。同じホスト上の複数のコンテナが互いに通信できるようになる。
- frontendコンテナを新たに構築。
Docker環境を作るのであれば、わざわざ作る必要はないが、開発のしやすさを見越してあえて作成する。
ここでやるのは、作業するディレクトリをカレントディレクトリに設定して、ビルド時につかうDockerfileのパスを指定する。ホスト30000番ポートをコンテナの3000番ポートにマッピング。
ローカルのfrontendディレクトリをコンテナの/workspace/frontendにマウントする。&開発用のディレクトリ、ワークディレクトリに指定。コンテナ起動時はnpm run devされてる状態であれば、タイムリーに変更が反映されるので開発しやすい。
  frontend:
    build:
      context: .
      dockerfile: ./docker/frontend-docker/Dockerfile
    ports: 
      - "30000:3000"
    volumes:
      - ./frontend:/workspace/frontend
    working_dir: /workspace/frontend
    command: npm run dev
    networks:
      - app-networkdockerディレクトリ
構成は下記
.
├── frontend-docker
│   └── Dockerfile
├── mysql
│   ├── Dockerfile
│   └── my.cnf
├── nginx
│   ├── Dockerfile
│   └── default.conf
└── php
    ├── Dockerfile
    ├── php-fpm.d
    └── php.ini少々変えたいところがありますが、環境づくりを最優先します。
- 元々Laravel6用に作成していたものを変更していく。
FROM node:22-alpine as node
RUN apk add --no-cache curl
WORKDIR /workspace/frontend
COPY ./frontend/package*.json ./  
# hostのfrontend/package*.jsonをコピーする
RUN npm install
COPY ./frontend ./
# hostのfrontend dir全体をコピーする
EXPOSE 30000
CMD ["npm", "run", "dev"]- nginx/default.confの中身を書き換える。
このファイルは「nginxがどのように動けば良いか」という設定を書いたファイルのこと。
location ~ \.php$ {
~中略~
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
}元々は下記のように書いていてLaravel6では問題なく動いていた。しかし、Laravel11ではうまく動作してくれなかった。
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;このあたりはまだ理解が乏しいのでここは要調査。
nginxのファイル設定について
※調査中(12/15中に加筆予定)
なお、fastcgi_param PATH_INFO $fastcgi_path_info; について、Laravel6の開発をしていたときはnginxがうまく動作をしてくれなかったのでこのコードを書いていた。
Laravelは、元々public/index.php にリクエストが集約されるし、全てのルーティングは index.php を通じて処理されること、かつLaravel のルート定義 (routes/web.php や routes/api.php) に基づいてリクエストを振り分けるので上記のコードは削除した。(なぜLaravel6では動作してくれなかったんだろう。)
この状態を整えれば、あとはBackend, Frontendそれぞれの開発に集中できるはず。
G’s在学時は、正直全然Laravel理解できませんでしたけど、最近はようやく理解できてきた気がしています。
このテンプレートを使って個人開発を進めていきます。
 TomoMemo.dev
TomoMemo.dev