Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

firsttest's avatar

Laravel + Vite + Docker : build files 404 not found

HI, this week I've been struggling with an issue. I have a laravel/vuejs (using typescript) with vite project. I am using Laravel 8.74.0 Here is my packages versions :

* "vite": "3.0.4",
* "laravel-vite": "^0.0.19", 
* "@vitejs/plugin-vue": "^2.2.2",
* "laravel-vite-plugin": "^0.6.0",
* "vue": "^3.2.6",

My issue is that when I try to build my project throught docker, the public/build files are created but the browser return me a 404 not found.

GET http://foo.localhost:8000/build/assets/main.80098a01.js net::ERR_ABORTED 404 (Not Found)
GET http://foo.localhost:8000/build/assets/main.b7cb1660.css net::ERR_ABORTED 404 (Not Found)

Notice : the "foo" before localhost is present because I am using Tenancy for Laravel

I verified and the build directory exist in the app container.

I am using docker compose to build the image. docker-compose.yml

version: '3.9'

networks:
  laravel:

services:
  nginx:
    build: 
      context: .
      dockerfile: docker/nginx.dockerfile
    ports:
      - 8000:80
    volumes:
      - ./:/var/www/html
    links:
      - app
    networks:
      - laravel
  
  app:
    build:
      context: .
      dockerfile: app.dockerfile
    links:
      - db
    networks:
      - laravel
    ports:
      - 3000:3000
    expose:
      - 3000:3000

  db:
    image: mysql:8.0
    ports:
      - 3306:3306
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_USER=user
      - MYSQL_PASSWORD=password
      - MYSQL_DATABASE=fresh_final
    networks:
      - laravel
    volumes:
      - db:/var/lib/mysql
  
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    container_name: fresh-pma
    restart: always
    ports:
        - 49152:80
    environment:
        PMA_HOST: db
    networks:
        - laravel
volumes:
    db:
        driver: local

Because I only have one project with both laravel and vuejs, I decided to create one container for the frontend and the backend.

app.dockerfile

FROM php:8.0.21-fpm

# Copy composer.lock and composer.json
COPY composer.lock composer.json /var/www/html/

# Set working directory
WORKDIR /var/www/html

# Install dependencies
RUN apt-get update && apt-get install -y \
    build-essential \
    libpng-dev \
    libjpeg62-turbo-dev \
    libfreetype6-dev \
    locales \
    zip \
    jpegoptim optipng pngquant gifsicle \
    vim \
    unzip \
    git \
    curl \
    sudo

# Clear cache
RUN apt-get clean && rm -rf /var/lib/apt/lists/*


# Install extensions
# RUN docker-php-ext-install pdo_mysql mbstring zip exif pcntl
RUN docker-php-ext-install pdo_mysql exif pcntl bcmath gd
# RUN docker-php-ext-install pdo_mysql
RUN docker-php-ext-configure gd --with-freetype --with-jpeg
# RUN docker-php-ext-install gd

# Install composer
RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

# Add user for laravel application
RUN groupadd -g 1000 www
RUN useradd -u 1000 -ms /bin/bash -g www www
# RUN sudo passwd www
# # Install nodejs
RUN sudo curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
RUN apt-get install -y nodejs

RUN npm install --global yarn
# RUN rm -rf node_modules
# Change current user to www
USER www

# Copy existing application directory contents
# COPY . /var/www/html

# Copy existing application directory permissions
COPY --chown=www:www . /var/www/html


# RUN whoami
RUN yarn install
# RUN sudo chown -R www: /var/www/html/node_modules
# RUN node node_modules/esbuild/install.js


# Expose port 9000 and start php-fpm server
EXPOSE 9000
# EXPOSE 3000

# COPY --from=vuejs /app /var/www/html

CMD ["php-fpm"]

nginx.dockerfile

 FROM nginx

ADD docker/conf/vhost.conf /etc/nginx/conf.d/default.conf

WORKDIR /var/www/html 

vhost.conf

upstream app {
  server app:9000;
}

server {
    listen 80;
    index index.php index.html;
    error_log  /var/log/nginx/error.log;
    access_log /var/log/nginx/access.log;
    root /var/www/html/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
        gzip_static on;
    }
    location ~ \.php$ {
        # fastcgi_pass app:9000;
        # fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        # include fastcgi_params;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass app;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
} 

Here is my vite.config.ts

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

export default defineConfig({
	define: {
		'process.env': process.env
	},
    server: {
        host: true,
        port: 3000,
        watch: {
            usePolling: true
        }
          
    },
    plugins: [
        laravel({
            input: ['resources/scripts/main.ts'],
            refresh: true,
        }),
		vue({
            template: {
                transformAssetUrls: {
                    // The Vue plugin will re-write asset URLs, when referenced
                    // in Single File Components, to point to the Laravel web
                    // server. Setting this to `null` allows the Laravel plugin
                    // to instead re-write asset URLs to point to the Vite
                    // server instead.
                    base: null,
 
                    // The Vue plugin will parse absolute URLs and treat them
                    // as absolute paths to files on disk. Setting this to
                    // `false` will leave absolute URLs un-touched so they can
                    // reference assets in the public directly as expected.
                    includeAbsolute: false,
                },
            },
        }),
	],
    resolve: {
        alias: {
            '@': '/resources/views/src',
        },
    },
});

Also, I noticed that the docker image run perfectly fine when I ran the build locally. So I am assuming that the docker image is referencing the local build files. (When the local build directory is deleted, the 404 not found error reappears).

0 likes
2 replies
Talinon's avatar

@firsttest I didn't read over your entire post in detail, but the thing that jumped out at me right off the bat is I'm pretty sure you can't subdomain localhost because its not a proper domain, but rather a special hostname to identify the current device. If you change your configuration to use a host such as foo.myapp.test then you'll likely no longer get the 404 errors.

MohamedTammam's avatar

Make sure to open your vite port to public in your container.

Please or to participate in this conversation.