Laravel + Vue + Vite + Inertia.js Docker開発環境の構築

## はじめに
この記事で構築するDocker環境は前回作った記事で構築した開発環境をDockerを利用して作り直したものになります。
前提条件は前回までと一緒です。

https://qiita.com/ryosuke-horie/items/f27e36f44be8ec11b2f5

## 構成
```
- docker
    - app
	    - Dockerfile
	    - php.ini
	    - www.conf
    - nginx
	    - default.conf
	    - Dockerfile
	    - nginx.conf
    - postgresql
	    - Dockerfile
	    - postgresql.conf
- src
- composer.yml
```


## 構築手順
1. Dockerfileを作成
	app(アプリケーションコンテナ用)
	```Dockerfile
	# コンテナのベースとしてamazonlinux:2023を指定
	FROM amazonlinux:2023
	
	RUN dnf -y update
	
	RUN dnf -y install unzip \
    wget
	
	# php、モジュール関連インストール
	RUN dnf -y install php less php-intl \
    php-cli php-json php-common php-devel php-fpm \
    php-gd php-mysqlnd php-mbstring php-pdo php-xml
	
	# unix socket
	RUN mkdir /var/run/php-fpm
	VOLUME [ "/var/run/php-fpm" ]

	EXPOSE 9000
	
	ENTRYPOINT /usr/sbin/php-fpm -F
	
	# composerインストール
	RUN curl -sS https://getcomposer.org/installer | php
	RUN mv composer.phar /usr/local/bin/composer
	RUN composer self-update
	
	# nodeのインストール
	RUN curl -fsSL https://rpm.nodesource.com/setup_18.x | bash -
	RUN dnf -y install nodejs
	
	# コンテナのディレクトリ指定
	WORKDIR /var/www/html
	```
	web(nginxコンテナ用)
	```Dockerfile
	# コンテナのベースとしてamazonlinux:2023を指定
	FROM amazonlinux:2023
	
	# nginxインストール
	RUN dnf -y update
	RUN dnf -y install nginx
	
	EXPOSE 5173
	
	ENTRYPOINT ["/usr/sbin/nginx", "-g", "daemon off;"]
	```
	postgres
	```Dockerfile
	FROM postgres:15.2-alpine
	```

2. compose.yml作成
	```yml
	services:
	  web:
	    container_name: web-laravel_vue
	    build:
	      context: ./docker/nginx/
	    ports:
	      - "8000:80"
	    volumes:
	      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
	      - ./src:/var/www/html
	    depends_on:
	      - app
	      - db
	
	  app:
	    container_name: app-laravel_vue
	    build:
	      context: ./docker/app/
	    ports:
	      - "5173:5173"
	    volumes:
	      - ./src:/var/www/html/
	      - ./docker/app/www.conf:/etc/php-fpm.d/www.conf
	      - ./docker/app/php.ini:/etc/php.ini
	  db:
	    container_name: pgdb-laravel_vue
	    image: postgres:latest
	    ports:
	      - "5432:5432"
	    volumes:
	      - ./docker/postgresql/postgresql.conf:/etc/postgresql/postgresql.conf
	      - pgdb-laravel_vue-volume:/var/lib/postgresql/data
	    environment:
	      POSTGRES_DB: laravel
	      POSTGRES_USER: laravel
	      POSTGRES_PASSWORD: laravel
	volumes:
	  pgdb-laravel_vue-volume:
	```

3. defalt.conf, www.conf nginx・php.ini・postgresql.confを作成
4. dockerコマンドでコンテナを作成
	```
	dokcer compose build
	docker compose up -d
	```
5. appコンテナ内でプロジェクト作成
	```
	$ docker exec app-laravel_vue bash
	
	# cd /var/www/html
	# composer create-project laravel/laravel .
	```
6. vue関連のインストール(appコンテナ内)
	```
	npm install --save-dev vue
	npm install --save-dev @vitejs/plugin-vue
	npm install --save-dev 
	```
7.viteの設定(vite.config.js)

    ```
	import { defineConfig } from 'vite';
	import laravel from 'laravel-vite-plugin';
	import vue from '@vitejs/plugin-vue';
	
	export default defineConfig({
        plugins: [
            vue(),
            laravel({
                input: ['resources/css/app.css', 'resources/js/app.js'],
                refresh: true,
            }),
        ],
        server: {
            host: '0.0.0.0',
            hmr: {
                host: '192.168.100.230',
            },
            watch: {
                usePolling: true,
            },
            port:5173
        }
    });
    ```

8. Inertia.jsの導入・設定
	```
	# インストール
	composer require inertiajs/inertia-laravel
	
	# Inertiaのミドルウェア作成
	php artisan inertia:middleware 
	```
	/app/Http/Kernel.phpに登録（webの中）
	```
	\App\Http\Middleware\HandleInertiaRequests::class,
	```
9. CreateInertiaAppの作成
	resources/js/app.js
	```js
	import { createApp, h } from "vue";
	import { createInertiaApp } from "@inertiajs/inertia-vue3";
	import { resolvePageComponent } from "laravel-vite-plugin/inertia-helpers"; 
	createInertiaApp({
		resolve: (name) =>
			resolvePageComponent(
				`./Pages/${name}.vue`,
				import.meta.glob("./Pages/**/*.vue")
			),
		setup({ el, App, props, plugin }) {
			createApp({ render: () => h(App, props) })
				.use(plugin)
				.mount(el);
		},
	});
	```

10. app.blade.phpとvueの連携
	```php
	<!DOCTYPE html>
	<html>
	
	<head>
	    <meta charset="utf-8" />
	    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
	    @inertiaHead
	    @vite(['resources/css/app.css', 'resources/js/app.js'])
	</head>
	
	<body>
	    @inertia
	</body>
	
	</html>
	```
11. ルーティング設定
	```php
	<?php
	
	use Illuminate\Support\Facades\Route;
	use Inertia\Inertia;
	
	/*
	|--------------------------------------------------------------------------
	| Web Routes
	|--------------------------------------------------------------------------
	|
	| Here is where you can register web routes for your application. These
	| routes are loaded by the RouteServiceProvider within a group which
	| contains the "web" middleware group. Now create something great!
	|
	*/
	
	Route::get('/', function () {
	    return Inertia::render('hello-world');
	});
	```
12. Hello World表示用のVueファイルを作成
	`resources/js/Pages/hello-world.vue`
	```vue
	<script>
	export default {
	    data() {
	        return {
	            greeting: "Hello World!",
	        };
	    },
	};
	</script>
	
	<template>
	    <p class="greeting">{{ greeting }}</p>
	</template>
	
	<style>
	.greeting {
	    color: red;
	    font-weight: bold;
	}
	</style>
	```
13. 動作確認(コンテナ内でそれぞれ実行)
```
php artisan serve --host 0.0.0.0
```

```
npm install && npm run dev
```



## おまけ
### 同一IPでの開発環境の複製について
以下3ファイルを修正する
- compose.yml
- /docker/nginx/default.conf
- /src/vite.config.js

compose.yml でportとコンテナ名の重複を防ぐ
```yml
services:
  web:
    container_name: web-laravel_vue2
    build:
      context: ./docker/nginx/
    ports:
      - "8083:80"
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./src:/var/www/html
    depends_on:
      - app
      - db
 
  app:
    container_name: app-laravel_vue2
    build:
      context: ./docker/app/
    ports:
      - "5174:5174"
    volumes:
      - ./src:/var/www/html/
      - ./docker/app/www.conf:/etc/php-fpm.d/www.conf
      - ./docker/app/php.ini:/etc/php.ini

  db:
    container_name: pgdb-laravel_vue2
    image: postgres:latest
    ports:
      - "5436:5432"
    volumes:
      - ./docker/postgresql/postgresql.conf:/etc/postgresql/postgresql.conf
      - pgdb-laravel_vue2-volume:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: laravel_db
      POSTGRES_USER: tanimoto
      POSTGRES_PASSWORD: Kazumakouki1

volumes:
  pgdb-laravel_vue2-volume:
```

/docker/nginx/default.conf portとコンテナ名を変更
```
// 略

location /devserver/ {
        proxy_pass http://app-laravel_vue2:5174/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
}

 // 略
```

/src/vite.config.js　portを変更
```javascript
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    plugins: [
        vue(),
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
    ],

    server: {
        host: '0.0.0.0',
        hmr: {
            host: '192.168.100.230',
        },
        watch: {
            usePolling: true,
        },
        port:5174
    }
});
```