James Pavett
James Pavett

Reputation: 399

HMR not working with Laravel Mix in Docker

I am having some problems setting up Hot Module Reloading in Laravel Mix inside a Docker container.

I have the following Dockerfile:

FROM php:7.4.0-fpm

RUN curl -sL https://deb.nodesource.com/setup_13.x | bash

RUN apt-get update && \
    apt-get install -y -q --no-install-recommends \
    nano apt-utils curl unzip default-mysql-client nodejs build-essential git \
    libcurl4-gnutls-dev libmcrypt-dev libmagickwand-dev \
    libwebp-dev libjpeg-dev libpng-dev libxpm-dev \
    libfreetype6-dev libaio-dev zlib1g-dev libzip-dev && \
    echo 'umask 002' >> /root/.bashrc  && \
    apt-get clean

# Docker PHP Extensions
RUN docker-php-ext-install -j$(nproc) iconv gettext gd mysqli curl pdo pdo_mysql zip && \
    docker-php-ext-configure gd --with-freetype=/usr/include/ --with-jpeg=/usr/include/ && \
    docker-php-ext-configure curl --with-curl

WORKDIR /var/www/html

COPY . /var/www/html

EXPOSE 80

Which I am building using the below docker-compose.yml file.

  # The Application
  app:
    build:
      context: ./
      dockerfile: app.dockerfile
    working_dir: /var/www/html
    volumes:
      - ./webroot:/var/www/html
    environment:
      - "DB_PORT=3306"
      - "DB_HOST=database"
      - CHOKIDAR_USEPOLLING=true

  # The Web Server
  web:
    build:
      context: ./
      dockerfile: web.dockerfile
    working_dir: /var/www/html
    volumes_from:
      - app
    ports:
      - 80:80

In previous Node.js apps, I have copied over the data inside the dockerfile, and mounted the volume in the compose file, however this doesn't seem to be having the same effect with Laravel.

I am seeing the below output in Git Bash, however the web pages are not reloading with changes at all after I run npm run hot inside the container, not even with a manual refresh:

enter image description here

Despite this, npm run watch-poll, which I have used previously, still works as expected.

Typically I see logs in the console from HMR and WDS inside the browser when viewing the application. However in this situation I am not seeing any outputs.

Below I have also included my webpack.mix.js file. I have been messing around with some of the options, such as the port and host, as I know they need to be configured a certain way when running inside a container. Any help would be appreciated as I am struggling to work out where I am going wrong.

mix.options({
    hmrOptions: {
        host: 'localhost',
        port: '80'
    },
});

mix.webpackConfig({
    mode: "development",
    devtool: "inline-source-map",
    devServer: {
        disableHostCheck: true,
        headers: {
            'Access-Control-Allow-Origin': '*'
        },
        host: "0.0.0.0",
        port: 80
    },
});

Edit:

Error output when running npm run hot after setting both host values to web:

> @ hot /var/www/html
> cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js

events.js:298
      throw er; // Unhandled 'error' event
      ^

Error: listen EADDRNOTAVAIL: address not available 172.25.0.4:80
    at Server.setupListenHandle [as _listen2] (net.js:1292:21)
    at listenInCluster (net.js:1357:12)
    at GetAddrInfoReqWrap.doListen [as callback] (net.js:1496:7)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:69:10)
Emitted 'error' event on Server instance at:
    at emitErrorNT (net.js:1336:8)
    at processTicksAndRejections (internal/process/task_queues.js:84:21) {
  code: 'EADDRNOTAVAIL',
  errno: -99,
  syscall: 'listen',
  address: '172.25.0.4',
  port: 80
}

Upvotes: 12

Views: 6240

Answers (2)

Alan Darmasaputra
Alan Darmasaputra

Reputation: 468

Webpack might have issue with file watcher being inside docker. Try adding polling option in the devServer config.

mix.webpackConfig({
  mode: "development",
  devtool: "inline-source-map",
  devServer: {
    watchOptions: {
      poll: true
    }
  }
});

For the listen EADDRNOTAVAIL: address not available 172.25.0.4:80 issue:

  1. See if there's a container running with docker ps
  2. Kill the blocking container with docker stop [container_id]

Upvotes: 1

LinPy
LinPy

Reputation: 18578

the problem is in

mix.options({
    hmrOptions: {
        host: 'localhost',
        port: '80'
    },
});

you can not use localhost since it is refer to your APP container in this case, what should you do is using web instead since compose will resolve the service names for you:

mix.options({
    hmrOptions: {
        host: 'web',
        port: '80'
    },
});

mix.webpackConfig({
    mode: "development",
    devtool: "inline-source-map",
    devServer: {
        disableHostCheck: true,
        headers: {
            'Access-Control-Allow-Origin': '*'
        },
        host: "web",
        port: 80
    },
});

Upvotes: 4

Related Questions