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

dlouhyd's avatar

Laravel 10 containers

I need to run php and node as two separate containers for Laravel. The tutorials for older versions of Laravel support this. However, version 10 is giving me problems. I am using Nginx as my web server. I also use Vite and Vue with Laravel. Can anyone advise me how to modify the configuration to make it work? t is really important for me to keep php and nodejs separate - I want to keep the containerization philosophy as much as possible.

docker-compose:

version: '3.8'

services:
  
  php:
    build:
      context: ./docker/php
    volumes:
      - ./:/var/www/html

  nginx:
    image: nginx:1.25.0
    ports:
      - "80:80"
    volumes:
      - ./docker/nginx/lcs.conf:/etc/nginx/conf.d/default.conf
      - ./:/var/www/html
    working_dir: /var/www/html
  
  node:
    image: node:20.2
    user: node
    volumes:
      - ./:/assets
    working_dir: /assets
    ports:
      - 3000:3000
      - 3001:3001
      - 3009:3009
    command: npm run dev
  
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: "${DB_PASSWORD}"
      MYSQL_DATABASE: "${DB_DATABASE}"
      MYSQL_USER: "${DB_USERNAME}"
      MYSQL_PASSWORD: "${DB_PASSWORD}"
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

Nginx:

server {
    listen 80;
    listen [::]:80;
    server_name _;
    root /var/www/html/public;
 
    add_header X-Frame-Options "SAMEORIGIN";
    add_header X-Content-Type-Options "nosniff";
 
    index index.php;
 
    charset utf-8;

    access_log /dev/stdout;
    error_log /dev/stdout;
 
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
 
    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }
 
    error_page 404 /index.php;
 
    location ~ \.php$ {
        fastcgi_pass php:9000;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        include fastcgi_params;
    }
 
    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Vite:

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

export default defineConfig({
    server: {
        host: true,
        port: 3009,
        watch: {
            usePolling: true
        }
    },
    plugins: [
        laravel({
            input: [
                'resources/sass/app.scss',
                'resources/js/app.js',
            ],
            refresh: true,
        }),
        vue({
            template: {
                transformAssetUrls: {
                    base: null,
                    includeAbsolute: false,
                },
            },
        }),
    ],
    resolve: {
        alias: {
            vue: 'vue/dist/vue.esm-bundler.js',
        },
    },
});
0 likes
10 replies
tisuchi's avatar

@dlouhyd

is really important for me to keep php and nodejs separate

I am confused by your query! Your node and php services are separated.

What exactly is your issue? It's not working?

3 likes
dlouhyd's avatar

@tisuchi Thanks for the reply. Yes, it is two containers, but unfortunately it doesn't work that way. I tried to modify and configure it in different ways. But I haven't managed to get it to work together yet. With the configuration above I get this error in the browser:

Failed to load resource: net::ERR_ADDRESS_INVALID client:1
Failed to load resource: net::ERR_ADDRESS_INVALID app.js:1

Where client:1 is [::]:3009/@vite/client and app.js:1 is [::]:3009/resources/js/app.js.

1 like
dlouhyd's avatar

@tisuchi When I set up vite with hmr as follows:

...
export default defineConfig({
    server: {
        host: true,
        port: 3009,
        hmr : { host: '0.0.0.0'},
        watch: {
            usePolling: true
        }
    },
...

I got the same errors but [::] was replaced with 0.0.0.0

And after few minutes its return this:

GET 0.0.0.0:3009/@vite/client net::ERR_ADDRESS_INVALID
GET 0.0.0.0:3009/resources/js/app.js net::ERR_ADDRESS_INVALID
dlouhyd's avatar

@tisuchi When I set up vite with hmr as follows:

...javascript
server: {
        host: true,
        port: 3009,
        hmr : { host: 'localhost'},
        watch: {
            usePolling: true
        }
    },
...

I get this error in the browser:

[Vue warn]: Component is missing template or render function. 
  at <App>

When I added Vue, I followed the Laravel 10 documentation as follows:

composer require laravel/ui
php artisan ui vue

Edit: I managed to fix this. I had a bug in the component and the blade. But now the page takes a long time to load.

tisuchi's avatar

@dlouhyd I suggest your setting in this way>

docker-compose.yml file.

version: '3.8'

services:
  
  php:
    build:
      context: .
      dockerfile: Dockerfile
    volumes:
      - ./:/var/www
    ports:
      - "9000:9000"

  nginx:
    image: nginx:1.19.2-alpine
    volumes:
      - ./:/var/www
      - ./docker/nginx/lcs.conf:/etc/nginx/conf.d/default.conf
    ports:
      - 8080:80
    depends_on:
      - php

  node:
    image: node:20.2
    user: node
    volumes:
      - ./:/assets
    working_dir: /assets
    ports:
      - 3000:3000
      - 3001:3001
      - 3009:3009
    command: npm run dev
  
  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: "${DB_PASSWORD}"
      MYSQL_DATABASE: "${DB_DATABASE}"
      MYSQL_USER: "${DB_USERNAME}"
      MYSQL_PASSWORD: "${DB_PASSWORD}"
    volumes:
      - mysql_data:/var/lib/mysql

volumes:
  mysql_data:

Double confirm your Docerfile has been enabled with the necessary PHP extensions for Laravel.

FROM php:8.1-fpm

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

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

# Install PHP extensions
RUN docker-php-ext-install pdo_mysql zip exif pcntl
RUN docker-php-ext-configure gd --with-jpeg=/usr/include/ --with-freetype=/usr/include/
RUN docker-php-ext-install gd

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Set working directory
WORKDIR /var/www

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

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

# Change current user to www
USER www-data

# Expose port 9000 and start php-fpm server
EXPOSE 9000
CMD ["php-fpm"]
2 likes
dlouhyd's avatar

@tisuchi I tried what you wrote. But it has the same result as configuring hmr with localhost. The application loads (URL address), but it takes long time (1-2 m). Same thing if I edit the code. hmr responds, but it all takes long time.

1 like
dlouhyd's avatar

This command DISM /Online /Enable-Feature /All /FeatureName:Microsoft-Hyper-V helps to speed loading to 30 s - 1 m but it is still slow.

It's slow when detecting a new change and then it's slow when loading the page. I use Windows 11, WSL 2 and Rancher Dedktop with dockerd

1 like
dlouhyd's avatar

@tisuchi So I tried a couple of changes. I found that if I run the same docker-compose and application on a server running Fedora Linux, everything works fine. Both hmr and requests. It's fast. Probably a bug somewhere in Windows or WSL2.

1 like
dlouhyd's avatar
dlouhyd
OP
Best Answer
Level 1

The final solution for me was to install some Linux distribution - WSL 2. I chose Fedora. Here I cloned the project to ~/ and everything works. VSC has to connect to WSL for it to see what it has. I'm using Rancher Desktop, so there was a WSL need to check. Let's see if something changes in the future and it goes better.

Please or to participate in this conversation.