23
votes

I have created a docker image which serves a simple react app using webpack from inside the container, but I get nothing in the browser.

Here are my config files

package.json

{
  "name": "invas_client",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "webpack --inline --content-base ."
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "react": "^0.14.7",
    "react-dom": "^0.14.7",
    "react-router": "^2.0.0"
  },
  "devDependencies": {
    "babel-core": "^6.5.1",
    "babel-loader": "^6.2.2",
    "babel-preset-es2015": "^6.5.0",
    "babel-preset-react": "^6.5.0",
    "http-server": "^0.8.5",
    "webpack": "^1.12.13",
    "webpack-dev-server": "^1.14.1"
  }
}

webpack.config.js

module.exports = {
    entry: './index.js',

    output: {
        filename: 'bundle.js',
        publicPath: ''
    },

    module: {
        loaders: [
            { test: /\.js$/, exclude: /node_modules/, loader: 'babel-loader?presets[]=es2015&presets[]=react' }
        ]
    }
}

Dockerfile

# Use starter image
FROM node:argon

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install

# Bundle app source
COPY . /usr/src/app

# Expose port
EXPOSE 8080

# Default command to run
CMD ["npm", "start"]

What's working fine

When I run npm start, the webpack-dev-server runs normally, and when I go to http://localhost:8080, I see my page.

What isn't working

When I run my server using docker, with the following command:

docker build -t anubhav756/app . && docker run -p 80:8080 anubhav756/app

the logs show everything working normally from inside the container, but when I point my browser to http://localhost, I get ERR_CONNECTION_RESET

Sample code's over here

3
Are you running Docker natively on Linux, or in a VM with Docker Machine? If it's a VM then your container port is published inside the VM, so you need to browse to its IP address - docker-machine ip. - Elton Stoneman
@EltonStoneman natively on Linux - Anubhav Dhawan
Hmm. Anything interesting in the Docker chain from iptables -L? - Elton Stoneman
docker ps shows this: CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES c25001e81847 anubhav756/invas_client "npm start" 16 seconds ago Up 14 seconds 0.0.0.0:80->8080/tcp berserk_hoover - Anubhav Dhawan
iptables -L shows: Chain DOCKER (3 references) target prot opt source destination ACCEPT tcp -- anywhere 172.17.0.2 tcp dpt:http-alt Chain DOCKER-ISOLATION (1 references) target prot opt source destination DROP all -- anywhere anywhere DROP all -- anywhere anywhere DROP all -- anywhere anywhere RETURN all -- anywhere anywhere - Anubhav Dhawan

3 Answers

54
votes

You are actualy listening on localhost only. To be reachable from outside replace the following line in your package.json file:

"start": "webpack-dev-server --inline --content-base ."

by :

"start": "webpack-dev-server --host 0.0.0.0 --inline --content-base ."

Related discussion : https://github.com/webpack/webpack-dev-server/issues/147

6
votes

I just want to add something to Raphayol answer if you couldn't enable hot-reloading of webpack-dev-server inside container.
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.

1
votes

When using webpack-dev-server with Encore and exposing it through Docker, you we'll need to use --host 0.0.0.0 and --public localhost:8080 so files are served even on browsers not navigating to 0.0.0.0 adresses.

Here is what I used :

webpack-dev-server --hot --host=0.0.0.0 --public=localhost:8080