My goal is to Dockerize Laravel + Vite + React.js with Inertia.js for Development. I can get the app to run, but it has no Hot Module Replacement (HMR) and loads the pages like SSR pages and not quickly like SPA pages.
Assumption:
Vite might not be running correctly
Behaviour:
localhost:8000 shows the app correctly but without HMR and SPA-Behaviour
localhost:5173 shows the default page for vite+laravel
This is the base Dockerfile:
# Use the official PHP image as a base
FROM php:8.2-fpm
# Set working directory
WORKDIR /var/www
# Install dependencies
RUN apt-get update && apt-get install -y
git
curl
libpng-dev
libonig-dev
libxml2-dev
zip
unzip
nodejs
npm
&& docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd
# Install Composer 2.2
RUN curl -sS https://getcomposer.org/installer | php -- --version=2.2.0 --install-dir=/usr/bin --filename=composer
# Copy existing application directory contents
COPY . /var/www
# Copy existing application directory permissions
COPY --chown=www-data:www-data . /var/www
# Install Laravel dependencies
RUN composer install
RUN npm install
# Expose port 9000 and start php-fpm server
EXPOSE 9000 5173
CMD ["sh", "-c", "php-fpm & npm run dev"]
This is the docker-compose.yml
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: laravel_app
container_name: laravel_app
ports:
- "5173:5173"
restart: unless-stopped
working_dir: /var/www
volumes:
- .:/var/www
- ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
- laravel
environment:
- APP_ENV=local
- APP_DEBUG=true
- APP_KEY=${APP_KEY}
- DB_CONNECTION=mysql
- DB_HOST=db
- DB_PORT=3306
- DB_DATABASE=laravel
- DB_USERNAME=laravel
- DB_PASSWORD=laravel
web:
image: nginx:alpine
container_name: laravel_web
#restart: unless-stopped
ports:
- "8000:80"
volumes:
- .:/var/www
- ./docker/nginx/nginx.conf:/etc/nginx/conf.d/default.conf
networks:
- laravel
depends_on:
- app
db:
image: mysql
container_name: laravel_db
restart: unless-stopped
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: laravel
MYSQL_USER: laravel
MYSQL_PASSWORD: laravel
volumes:
- dbdata:/var/lib/mysql
networks:
- laravel
volumes:
dbdata:
networks:
laravel:
driver: bridge
This is the nginx.conf
server {
listen 80;
index index.php index.html;
server_name localhost;
root /var/www/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;
}
location /_vite/ {
proxy_pass http://app:5173;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
}
location ~ /.ht {
deny all;
}
}
This is the vite.config.js
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import react from '@vitejs/plugin-react';
export default defineConfig({
plugins: [
laravel({
input: [
'resources/css/app.css',
'resources/js/app.jsx',
],
refresh: true,
}),
react({}),
],
server: {
host: '0.0.0.0',
port: 5173,
hmr: {
host: 'localhost',
},
},
});