3

I have a simple Dockerfile to create an image to act as a dev environment for me node app. The problem is the port binding between the container and my machine doesn't work as expected.

Dockerfile:

FROM node:10.12.0
EXPOSE 8080

From this file I create an image with the following command:

docker build -t node:10.12.0.bern ./images/node/

I start a container with the following command:

docker run --rm --name=run-client \
    -v $(CURDIR)/client:/app/client:rw \
    -v $(CURDIR)/kawax-js:/app/kawax-js:rw \
    -v $(CURDIR)/enigma:/app/enigma:rw \
    -v $(CURDIR)/client-init/init-client.sh:/usr/local/bin/init-client.sh:rw \
    -p 8080:8080 \
    node:10.12.0.bern \
    /bin/sh -c "sh /usr/local/bin/init-client.sh"

and here is my script init-client.sh:

#!/usr/bin/env bash

cd /app/enigma/
npm link

cd /app/kawax-js/
npm link

cd /app/client/
npm link enigma
npm link kawax-js

npm run dev

which at the end runs my dev script from the package.json file:

  "scripts": {
    "dev": "npm run dev:server & npm run sass:watch & npm run lint:watch",
    "build": "npm run client:build && npm run sass:build",
    "dev:server": "webpack-dev-server --mode development --hot",
    "dev:watchOnly": "webpack --progress --watch -d",
    "client:build": "webpack --mode production",
    "client:minify": "NODE_ENV=production npm run client:build",
    "client:analyze": "___WEBPACK_ANALYZE__=true webpack",
    "sass:build": "node-sass --source-map true --include-path scss scss/app.scss dist/css/bernstein.css",
    "sass:watch": "npm run sass:build & nodemon -e scss -x 'npm run sass:build'",
    "lint": "eslint src/**",
    "lint:changed": "git status | grep .js\\$ | awk '{print $NF}' | xargs eslint ",
    "lint:watch": "nodemon -e js -x 'npm run lint -- --fix'",
    "test": "jest --verbose",
    "test:watch": "jest --verbose --debug --watchAll",
    "deploy:staging": "./scripts/deploy.staging.sh",
    "deploy:production": "./scripts/deploy.production.sh"
  },

Running this script on my machine or the container will start webpack server at port 8080. There is no issues at all starting the server on my machine or from the docker container (logs from the container):

Rendering Complete, saving .css file...
Wrote Source Map to /app/client/dist/css/bernstein.css.map
Wrote CSS to /app/client/dist/css/bernstein.css
[nodemon] clean exit - waiting for changes before restart
clean-webpack-plugin: /app/client/dist/js has been removed.
ℹ 「wds」: Project is running at http://localhost:8080/
ℹ 「wds」: webpack output is served from /assets
ℹ 「wds」: Content not from webpack is served from /app/client/public
ℹ 「wds」: 404s will fallback to /index.html

I can see all the bundling was done correctly if I look to my mounted volume. Running docker ps I get:

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                      NAMES
db2c5d45c9a6        node:10.12.0.bern        "sh /usr/local/bin/i…"   2 minutes ago       Up 2 minutes        0.0.0.0:8080->8080/tcp   run-client

The problem is when I go to 0.0.0.0:8080 on my browser I see nothing. I don't get it, why is the port binding not working although the server has started and running fine in the container?

Salah Saleh
  • 793
  • 9
  • 29
  • Why do you use `0.0.0.1`? Do you mean `127.0.0.1:8080`? Can you post the output of `netstat -nptl`? – charli Oct 19 '18 at 15:14
  • `Project is running at http://localhost:8080/` means the service can't be reached from outside the container at all. – David Maze Oct 19 '18 at 15:16
  • Sorry that is a typo, it is 0.0.0.0. I will fix. – Salah Saleh Oct 19 '18 at 15:16
  • @DavidMaze how can I fix that? – Salah Saleh Oct 19 '18 at 15:18
  • Could be related to https://stackoverflow.com/questions/52346212/expose-node-js-app-with-host-as-localhost-on-kubernetes Note that `localhost` from within the container is effectively internal to the container – Ryan Dawson Oct 19 '18 at 15:30
  • @charli I also tried the -p flag with 127.0.0.1:8080:8080 and it also didn't work. I think the p flag in netstat -nptl is not working for me and the log is huge, I don't know if it is a good idea to put all of it here. What are you looking for? – Salah Saleh Oct 19 '18 at 15:31

2 Answers2

4

Watch out for webpack-dev-server! It is bound to localhost by default.

Change it to :

"dev:server": "webpack-dev-server --mode development --hot --host 0.0.0.0"

You need to update your webpack-dev-server (in your package.json command and webpack.config.json) configuration to bind host to 0.0.0.0 instead of localhost (default!). localhost is just an alias in your operating system, it is not available within the container.

https://webpack.js.org/configuration/dev-server/#devserver-host

nakwa
  • 1,157
  • 1
  • 13
  • 25
0

Important change replace Project is running at http://localhost:8080/

should be running at http://0.0.0.0:8080/

in your app.

Use netstate -tulpn . OR ss -tln on the host machine and find the port 8080 , and make sure it is bound to 0.0.0.0 or the ip of the host machine.

Also , in you browser , access it like this if its bound to localhost only:

http://127.0.0.1:8080

OR this if is bound to host ip or 0.0.0.0

http://host-ip:8080

also make sure you can curl it on 8080 both inside the container and on host using either 127.0.0.1 or localhost and host IP

Ijaz Ahmad
  • 11,198
  • 9
  • 53
  • 73
  • curl localhost:8080 inside the container return the index.html but from my local machine returns nothing. `netstat -ntl | grep 8080` on my machine returns nothing – Salah Saleh Oct 19 '18 at 15:57
  • ok then it should return something on ur machines , othervise you will never get something in broswer , please make sure you app is serving on 0.0.0.0 instead of localhost then do the binding of port and then test – Ijaz Ahmad Oct 19 '18 at 17:17