Jayaram
Jayaram

Reputation: 6606

Enabling webpack hot-reload in a docker application

I have a docker app with the following containers

  1. node - source code of the project. it serves up the html page situated in the public folder.
  2. webpack - watches files in the node container and updates the public folder (from the node container) on the event of change in the code.
  3. database

this is the webpack/node container setup

 web:
    container_name: web
    build: .
    env_file: .env
    volumes:
      - .:/usr/src/app
      - node_modules:/usr/src/app/node_modules
    command: npm start
    environment:
      - NODE_ENV=development
    ports:
      - "8000:8000"

  webpack:
    container_name: webpack
    build: ./webpack/
    depends_on:
      - web
    volumes_from:
      - web
    working_dir: /usr/src/app
    command: webpack --watch

So currently , the webpack container monitors and updates the public folder. i have to manually refresh the browser to see my changes.

I'm now trying to incorporate webpack-dev-server to enable automatic refresh in the browser

these are my changes to the webpack config file

module.exports = {
  entry:[
    'webpack/hot/dev-server',
    'webpack-dev-server/client?http://localhost:8080',
    './client/index.js'
  ],

  ....

  devServer:{
    hot: true,
    proxy: {
      '*': 'http://localhost:8000'
    }
  }
}

and the new docker-compose file file webpack

  webpack:
    container_name: webpack
    build: ./webpack/
    depends_on:
      - web
    volumes_from:
      - web
    working_dir: /usr/src/app
    command: webpack-dev-server --hot --inline
    ports:
      - "8080:8080"

i seem to be getting an error when running the app

Invalid configuration object. Webpack has been initialised using a configuration object that does not match the API schema.
webpack     |  - configuration.entry should be one of these:
webpack     |    object { <key>: non-empty string | [non-empty string] } | non-empty string | [non-empty string] | function
webpack     |    The entry point(s) of the compilation.
webpack     |    Details:
webpack     |     * configuration.entry should be an object.
webpack     |     * configuration.entry should be a string.
webpack     |     * configuration.entry should NOT have duplicate items (items ## 1 and 2 are identical) ({
webpack     |         "keyword": "uniqueItems",
webpack     |         "dataPath": ".entry",
webpack     |         "schemaPath": "#/definitions/common.nonEmptyArrayOfUniqueStringValues/uniqueItems",
webpack     |         "params": {
webpack     |           "i": 2,
webpack     |           "j": 1
webpack     |         },
webpack     |         "message": "should NOT have duplicate items (items ## 1 and 2 are identical)",
webpack     |         "schema": true,
webpack     |         "parentSchema": {
webpack     |           "items": {
webpack     |             "minLength": 1,
webpack     |             "type": "string"
webpack     |           },
webpack     |           "minItems": 1,
webpack     |           "type": "array",
webpack     |           "uniqueItems": true
webpack     |         },
webpack     |         "data": [
webpack     |           "/usr/src/app/node_modules/webpack-dev-server/client/index.js?http://localhost:8080",
webpack     |           "webpack/hot/dev-server",
webpack     |           "webpack/hot/dev-server",
webpack     |           "webpack-dev-server/client?http://localhost:8080",
webpack     |           "./client/index.js"
webpack     |         ]
webpack     |       }).
webpack     |       [non-empty string]
webpack     |     * configuration.entry should be an instance of function
webpack     |       function returning an entry object or a promise..

As you can see , my entry object doesnt have any duplicate items.

Is there something additional i should be doing? anything i missed?

webpack-dev-server should basically proxy all requests to the node server.

Upvotes: 19

Views: 35016

Answers (6)

Maksym Dudyk
Maksym Dudyk

Reputation: 1164

Hot Module Reload is the coolest development mode, and a tricky one to set up with Docker. In order to bring it to life you'll need 8 steps to follow:

  1. For Webpack 5 install, in particular, these NPM packages:
npm install webpack webpack-cli webpack-dev-server --save-dev --save-exact
  1. Write this command into 'scripts' section in 'package.json' file:
"dev": "webpack serve --mode development --host 0.0.0.0 --config webpack.config.js"
  1. Add this property to 'webpack.config.js' file (it'll enable webpack's hot module reloading)
devServer: {
      port: 8080,
      hot: "only",
      static: {
        directory: path.join(__dirname, './'),
        serveIndex: true,
      },
    },
  1. Add this code to the very bottom of your 'index.js' (or whatever), which is the entry point to your app:
if (module.hot) {
  module.hot.accept()
}
  1. Expose ports in 'docker-compose.yml' to see the app at http://localhost:8080
ports:
      - 8080:8080
  1. Sync your app's /src directory with 'src' directory within a container. To do this use volumes in 'docker-compose.yml'. In my case, directory 'client' is where all my frontend React's files sit, including 'package.json', 'webpack.config.js' & Dockerfile. While 'docker-compose.yml' is placed one leve up.
volumes:
      - ./client/src:/client/src
  1. Inside the volume group you'd better add the ban to syncronize 'node_modules' directory ('.dockerignore' is of no help here).
volumes:
      ...
      - /client/node_modules

  1. Fire this whole bundling from Docker's CMD, not from RUN command inside your 'docker-compose.yml'.
WORKDIR /client
CMD ["npm", "run", "dev"]

P.S. If you use Webpack dev server, you don't need other web servers like Nginx in your development. Another important thing to keep in mind is that Webpack dev server does not recompile files from '/src' folder into '/disc' one. It performs the compilation in memory.

Upvotes: 5

Tomas Vancoillie
Tomas Vancoillie

Reputation: 3868

Had this trouble from a windows device. Solved it by setting WATCHPACK_POLLING to true in environment of docker compose.

frontend:
  environment:
    - WATCHPACK_POLLING=true

Upvotes: 8

STEVE  K.
STEVE K.

Reputation: 909

I had the same problem. it was more my fault and not webpack nor docker. In fact you have to check that the workdir in your Dockerfile is the target for your bindmount in docker-compose.yml

Dockerfile

FROM node
...
workdir /myapp
...

on your docker-compose.yml

web:
   ....
   -volumes:
        ./:/myapp

It should work if you configure the reloading on your webpack.config.js

Upvotes: -1

Mihail Ignatiev
Mihail Ignatiev

Reputation: 853

Docker & webpack-dev-server can be fully operational without any middleware or plugins, proper configuration is the deal:

devServer: {
  port: 80, // use any port suitable for your configuration
  host: '0.0.0.0', // to accept connections from outside container
  watchOptions: {
      aggregateTimeout: 500, // delay before reloading
      poll: 1000 // enable polling since fsevents are not supported in docker
  }
}

Use this config only if your docker container does not support fsevents.

For performance efficient way check out HosseinAgha answer #42445288: Enabling webpack hot-reload in a docker application

Upvotes: 12

HosseinAgha
HosseinAgha

Reputation: 833

I couldn't make webpack or webpack-dev-server watch (--watch) mode work even after mounting my project folder into container.
To fix this you need to understand how webpack detects file changes within a directory.
It uses one of 2 softwares that add OS level support for watching for file changes called inotify and fsevent. Standard Docker images usually don't have these (specially inotify for linux) preinstalled so you have to install it in your Dockerfile.
Look for inotify-tools package in your distro's package manager and install it. fortunately all alpine, debian, centos have this.

Upvotes: 12

Jos&#233; Quinto Zamora
Jos&#233; Quinto Zamora

Reputation: 2118

try doing this:

  1. Add watchOptions.poll = true in webpack config.

    watchOptions: { poll: true },

  2. Configure host in devServer config

    host:"0.0.0.0",

Upvotes: 5

Related Questions