Erro vite conexão recusada usando o Laravel 12 mais Docker e Nginx

Oi estou desenvolvendo um sistema para estudos usando Docker e Laravel, e estou enfrentando um erro depois de ter gerado a imagen, agora quando eu quero rodar o comando npm run dev e tento acessar o localhost:8081 onde foi a porta que eu setei porém esta dando erro de conexão recusada:

GET http://localhost:5173/@vite/client net::ERR_CONNECTION_REFUSED localhost/:21 GET http://localhost:5173/resources/js/app.jsx net::ERR_CONNECTION_REFUSED localhost/:21 GET http://localhost:5173/resources/js/Pages/Welcome.jsx net::ERR_CONNECTION_REFUSED localhost/:16 GET http://localhost:5173/@react-refresh net::ERR_CONNECTION_REFUSED

Esse aqui é meu dockerfile:

FROM php:8.2-fpm

# Install required dependencies
RUN apt-get update && apt-get install -y \
    git \
    unzip \
    curl \
    libpng-dev \
    libonig-dev \
    libxml2-dev \
    zip \
    libzip-dev \
    procps \
    && docker-php-ext-install pdo_mysql mbstring exif pcntl bcmath gd zip

RUN curl -fsSL https://deb.nodesource.com/setup_current.x | bash - \
    && apt-get install -y nodejs

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

# Set working directory
WORKDIR /var/www/html

COPY . /var/www/html

Esse é meu docker-compose.yml:

services:
  economize-app:
    build:
      context: ./docker/php
    container_name: economize-app
    volumes:
      - .:/var/www/html
    ports:
      - "9000:9000"
    networks:
      - laravel

  nginx:
    image: nginx:latest
    container_name: nginx
    ports:
      - "8081:80"
    volumes:
      - .:/var/www/html
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
    depends_on:
      - economize-app
    networks:
      - laravel

networks:
  laravel:

E essa é minha config do nginx:

server {
    listen 80;
    server_name localhost;
    index index.php index.html;
    root /var/www/html/public;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass economize-app:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~ /\.ht {
        deny all;
    }
}

Eu tentei setar um ip padrão no vite, mas ainda sim não consegui:

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

export default defineConfig({
    plugins: [
        laravel({
            input: 'resources/js/app.jsx',
            refresh: true,
        }),
        react(),
    ],
    server: {
        host: '0.0.0.0', // Acessível em qualquer interface de rede
        port: 5173, // Porta padrão do Vite
        https: false,
        cors: false,
        hmr: {
            host: 'localhost', // Host para Hot Module Replacement (HMR)
        },
    },
});

Alguém sabe como posso consertar esse problema?

O vite roda na porta 5173 mas ela não está aberta em nenhum container. Verifiquei que instalou o node no container do PHP. Seria mais interessante ter um container só para o node. Porém se quiser manter assim é só abrir essa porta no container que está rodando o npm run dev

Caso tenha problemas para fazer o setup do ambiente dê uma olhada no Laravel Sail

Eu usei o Laravel Sail algumas vezes mas eu quero algo que eu posso colocar em produção, depois do erro eu encontrei o problema da mesma forma, eu exportei a porta `5173` no container do PHP e fiz a configuração do vite.config.js, agradeço.
> algo que eu posso colocar em produção Não é recomendado colocar `npm run dev` em produção, já que ele expõe todos os seus sourcemaps e gera um overhead gigantesco por ter que verificar toda hora se os arquivos foram alterados. Sendo assim a instalação do node poderia estar em um container totalmente separado, apenas para desenvolvimento. Outro motivo para usar configurações separadas é a otimização de produção. O PHP precisa ficar alterando o tempo inteiro? Não, então deixa tudo compilado e quando alterar rebuilda a imagem inteira ------ Aqui vai uma ideia do que uso nos meus projetos em produção. Eu crio uma configuração totalmente personalizada para cada projeto, é uma boa base para começar. ### Dockerfile ```Dockerfile ############ BUILD PHP ############# FROM php:8.3-fpm AS build-php WORKDIR /app RUN apt update && \ apt install -y ca-certificates curl tar libxml2-dev libzip-dev wget libpq-dev && \ apt clean RUN docker-php-ext-install opcache RUN docker-php-ext-configure zip RUN docker-php-ext-configure pgsql -with-pgsql=/usr/local/pgsql RUN docker-php-ext-install bcmath pdo_mysql zip xml sockets pgsql pdo_pgsql intl RUN pecl install redis && docker-php-ext-enable redis RUN curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer COPY . ./ RUN composer install --optimize-autoloader --no-dev RUN cp /app/deploy/php.ini /usr/local/etc/php/conf.d/z_config.ini ########### STATIC BUILD ########### FROM node:20-alpine AS static-build WORKDIR /app COPY package.json ./ RUN npm install --include=dev COPY . ./ RUN npm run build ############### BASE ############### FROM build-php AS base COPY --from=static-build /app/public/build /app/public/build ########## STATIC SERVER ########### FROM nginx:alpine AS static-server WORKDIR /app/public COPY ./deploy/static/nginx.conf /etc/nginx/nginx.conf COPY ./deploy/static/static.conf /etc/nginx/conf.d/default.conf COPY --from=static-build /app/public /app/public ############ WEB SERVER ############ FROM base AS web RUN chmod +x deploy/web/docker_entrypoint.sh ########## WORKER SERVER ########### FROM base AS worker RUN apt update && apt install -y supervisor && apt clean RUN chmod +x deploy/worker/docker_entrypoint.sh # Config workers RUN cp /app/deploy/worker/* /etc/supervisor/conf.d/ && \ touch /app/storage/logs/schedule.log && \ touch /app/storage/logs/worker.log ``` ### Docker compose ```yml services: web: restart: always build: context: . target: web entrypoint: 'deploy/web/docker_entrypoint.sh' volumes: - ./storage:/app/storage ports: - 9000:9000 env_file: - .env networks: - [appname]svc deploy: resources: limits: cpus: '2' memory: 2G reservations: cpus: '0.25' memory: 256M worker: restart: always build: context: . target: worker entrypoint: 'deploy/worker/docker_entrypoint.sh' volumes: - ./storage:/app/storage env_file: - .env networks: - [appname]svc deploy: resources: limits: cpus: '1' memory: 1.5G reservations: memory: 256M static: restart: always build: context: . target: static-server ports: - 9001:9001 networks: - [appname]svc deploy: resources: limits: cpus: '1' memory: 128M reservations: cpus: '0.25' memory: 32M networks: [appname]svc: driver: bridge external: true name: [appname]_svc ``` ### static.conf ```conf server { root /app/public; listen [::]:9001; listen 9001; } ``` Sim, tem um nginx dedicado a apenas servir os estáticos deste projeto, e outro nginx para fazer o proxy de todos os serviços # entrypoint web ```bash #!/bin/bash php artisan migrate --force --isolated php artisan db:seed --force php artisan optimize:clear php artisan optimize php-fpm ``` # entrypoint worker ```bash #!/bin/bash php artisan migrate --force --isolated php artisan optimize:clear php artisan optimize supervisord -n ``` ### Conf supervisor worker ```conf [program:[appname]-worker] process_name=%(program_name)s_%(process_num)02d command=php /app/artisan queue:work --max-jobs=1000 --max-time=3600 --queue=high,default,low autostart=true autorestart=true stopasgroup=true numprocs=10 redirect_stderr=true stdout_logfile=/app/storage/logs/worker.log stopwaitsecs=30 user=www-data ``` ```conf [program:[appname]-schedule] process_name=%(program_name)s_%(process_num)02d command=php /app/artisan schedule:work autostart=true autorestart=true stopasgroup=true numprocs=1 redirect_stderr=true stdout_logfile=/app/storage/logs/schedule.log user=www-data ``` ### nginx conf ``` server { server_name [appname]; root /app; location / { try_files $uri /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 127.0.0.1:9000; include fastcgi_params; fastcgi_param SCRIPT_FILENAME /app/public/index.php; } location /build { proxy_pass http://127.0.0.1:9001; proxy_redirect off; 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-Host $server_name; } listen [::]:443 ssl; ```

bom parece que eu consertei na config do vite:

server: {
        host: '0.0.0.0',
        hmr: {
            host: 'localhost'
        }
    }

Agora o por que? é outros 5000