javascriptphplaraveldockervite

Laravel and Vite within a Docker container


I'm attempting to containerise a laravel project which will be running vue, as webpack is now not a standard and vite is, for me to run vite it would then refresh if something in the project has changed.

I have npm running in a different service, this is only ran when needed and when I run npm run dev the vite development server starts which is great, but I find that nothing is being noticed by it.

my docker compose file is:

ervices:
  nginx:
    #image: nginx:stable-apline
    build:
      context: .
    ports:
      - 80:80
    volumes:
      - ./src:/var/www/html
    
    depends_on:
      - mysql
      - php
  mysql:
    image: mariadb:10.5.8
    ports:
      - 3306:3306
    environment:
      MYSQL_DATABASE: laravel
      MYSQL_USER: laravel
      MYSQL_PASSWORD: secret
      MYSQL_ROOT_PASSWORD: secret
    volumes:
      - ./mysql:/var/lib/mysql
  
  php:
    build:
      context: .
      dockerfile: php.dockerfile
    volumes:
      - ./src:/var/www/html
  
  composer:
    build:
      context: .
      dockerfile: composer.dockerfile
    volumes:
      - ./src:/var/www/html
    working_dir: /var/www/html

  node:
    image: node:current-alpine
    volumes:
      - ./src:/var/www/html
    entrypoint: ["npm"]
    working_dir: /var/www/html

When my nginx container is running, I get the following in the console:

enter image description here

My vite config is as follows:

import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import tailwindcss from '@tailwindcss/vite';
import vue from '@vitejs/plugin-vue';

export default defineConfig({
    server: {
        strictPort: true,
        port: 5173,
        host: '127.0.0.1',
        origin: 'http://localhost:5173',
        hmr: {
            host: 'localhost',
        },
        watch: {
            usePolling: true
        }
    },
    plugins: [
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.js'],
            refresh: true,
        }),
        tailwindcss(),
        vue()
    ]
});

this is the welcome.blade.php

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">

        <title>{{ config('app.name', 'Laravel') }}</title>

        <!-- Fonts -->
        <link rel="preconnect" href="https://fonts.bunny.net">
        <link href="https://fonts.bunny.net/css?family=instrument-sans:400,500,600" rel="stylesheet" />

        <!-- Styles / Scripts -->
        @vite(['resources/css/app.css', 'resources/js/app.js'])
    </head>
    <body id="app">
            <HomeComponent/>
    </body>
</html>

The app.js file:

import './bootstrap';

import {createApp} from "vue/dist/vue.esm-bundler.js";
import HomeComponent from "./components/HomeComponent.vue";

const app = createApp({});

app.component('HomeComponent', HomeComponent);

app.mount('#app');


Only time the console errors are not showing is if I delete the hot file under public, but still no luck getting my component to show.

Any thoughts?


Solution

  • Your issue is that Vite's dev server is binding to localhost (127.0.0.1) inside the container, which makes it inaccessible from your host machine. When running in Docker, you need to bind to 0.0.0.0 to accept connections from outside the container.

    Solution:

    Update your vite.config.js to bind to all network interfaces:

    js

    import { defineConfig } from 'vite';
    import laravel from 'laravel-vite-plugin';
    
    export default defineConfig({
        plugins: [
            laravel({
                input: ['resources/css/app.css', 'resources/js/app.js'],
                refresh: true,
            }),
        ],
        server: {
            host: '0.0.0.0',  // Bind to all interfaces
            port: 5173,
            hmr: {
                host: 'localhost',  // Use your actual host or Docker service name
            },
        },
    });
    

    Key points:

    1. host: '0.0.0.0' makes Vite listen on all network interfaces inside the container

    2. The hmr.host should be set to how you access the container from your browser (could be localhost, your machine's IP, or a Docker service name if using docker-compose)

    3. Make sure port 5173 is properly exposed in your Docker configuration

    If using docker-compose, ensure your service has the port mapped:

    yaml

    services:
      app:
        ports:
          - "5173:5173"
    

    After making these changes, restart your Vite dev server and it should be accessible from your host machine.