Reputation: 399
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:
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
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:
docker ps
docker stop [container_id]
Upvotes: 1
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