Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Node.js dev environment in Docker on Windows

I have tried everything I can think of. I have read the docs, blogs and tried following samples on github.

But I can't seem to get it to work.

What I want to do is simple. I want to write my node.js code on my windows 8.1 machine, and I also want to run the code from within a Docker container without having to rebuild the container all the time. So I want to map a directory on my Windows Host to a directory inside the container.

I have created this Dockerfile

FROM node:0.10.38

RUN apt-get update -qq && apt-get install -y build-essential

ENV ZMQ_VERSION 4.1.3
ENV LIBSODIUM_VERSION 1.0.3

RUN curl -SLO "https://download.libsodium.org/libsodium/releases/libsodium-$LIBSODIUM_VERSION.tar.gz" \
    && tar xvf libsodium-$LIBSODIUM_VERSION.tar.gz \
    && cd libsodium-$LIBSODIUM_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r libsodium-$LIBSODIUM_VERSION \
    && rm libsodium-$LIBSODIUM_VERSION.tar.gz
RUN curl -SLO "http://download.zeromq.org/zeromq-$ZMQ_VERSION.tar.gz" \
    && tar xvf zeromq-$ZMQ_VERSION.tar.gz \
    && cd zeromq-$ZMQ_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r zeromq-$ZMQ_VERSION \
    && rm zeromq-$ZMQ_VERSION.tar.gz
RUN ldconfig

COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh

ENTRYPOINT ["/entrypoint.sh"]

RUN mkdir -p /usr/src/app
ADD . /usr/src/app
WORKDIR /usr/src/app
RUN npm install

EXPOSE 3000
EXPOSE 35729

CMD ["npm", "start"]

I have this simple server.js file

var express = require('express');
var app = express();
var zmq = require('zmq');

app.get('/', function (req, res) {
  res.send('ZMQ: ' + zmq.version);
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

And this simple package.json

{
  "name": "docker-node-hello-world",
  "version": "1.0.0",
  "description": "",
  "main": "server.js",
  "scripts": {
    "start": "node server.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.13.3",
    "zmq": "^2.14.0"
  }
}

I have installed the latest Docker Toolbox, and can run the Docker Hello World example fine. I try to build my docker image like this when I am in the directory where my Dockerfile is.

docker build -t dockernodetest:dockerfile .

I then try to run it, also from the same location inside the Docker Quickstart Terminal. I use the hash since the tag doesn't take for some reason:

docker run -v //c/Bitbucket/docker-node-hello-world/:/usr/src/app -p 3000:3000 -i -t 9cfd34e046a5 ls ./usr/src/app

The result of this is an empty directory. I was hoping I could just invoke

docker run -v //c/Bitbucket/docker-node-hello-world/:/usr/src/app -p 3000:3000 -i -t 9cfd34e046a5 npm start

But since the host directory isn't available it fails. I have the feeling that I have misunderstood something very basic. I just don't know what.

like image 681
Jay Pete Avatar asked Oct 26 '25 14:10

Jay Pete


1 Answers

First let's start from the Dockerfile

FROM node:0.10.38-onbuild

RUN apt-get update -qq && apt-get install -y build-essential

ENV ZMQ_VERSION 4.1.3
ENV LIBSODIUM_VERSION 1.0.3

RUN curl -SLO "https://download.libsodium.org/libsodium/releases/libsodium-$LIBSODIUM_VERSION.tar.gz" \
    && tar xvf libsodium-$LIBSODIUM_VERSION.tar.gz \
    && cd libsodium-$LIBSODIUM_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r libsodium-$LIBSODIUM_VERSION \
    && rm libsodium-$LIBSODIUM_VERSION.tar.gz
RUN curl -SLO "http://download.zeromq.org/zeromq-$ZMQ_VERSION.tar.gz" \
    && tar xvf zeromq-$ZMQ_VERSION.tar.gz \
    && cd zeromq-$ZMQ_VERSION \
    && ./configure \
    && make \
    && make install \
    && cd .. \
    && rm -r zeromq-$ZMQ_VERSION \
    && rm zeromq-$ZMQ_VERSION.tar.gz
RUN ldconfig

EXPOSE 3000 35729

From line 1 I've used the 0.10.38-onbuild tag because I want to take advantage of onbuild scripts that will run to create the /usr/src/app directory and run npm install

Then server.js and package.json are as you have written them. These are both in the same working directory as the Dockerfile as well.

Next we build the image

docker build -t dockernodetest .

I've omitted the dockerfile tag as it seemed unnecessary. The client will automatically add a latest tag anyway. To see what images you've have locally run docker images.

At this point we should have an image ready to run but let us first check that the files we wanted to load are then and that npm install created the node_modules directory

$ docker run dockernodetest ls /usr/src/app
Dockerfile
node_modules
package.json
server.js

We're ready at this point to run our little nodejs app

$ docker run -it -p 8080:3000 dockernodetest

> [email protected] start /usr/src/app
> node server.js

Example app listening at http://0.0.0.0:3000

In this instance I've used the -p 8080:3000 flag to map the container's 3000 port to port 8080 on my host machine. Note that I didn't have any other commands at the end because the -onbuild image I've pulled form has a CMD [ "npm", "start" ] and so the default action is to run the start package script.

So to make the development cycle even faster you want to mount your working directory to the container via the -v option

$ docker run -it -p 8080:3000 -v "$PWD":/usr/src/app dockernodetest

> [email protected] start /usr/src/app
> node server.js


module.js:340
    throw err;
          ^
Error: Cannot find module 'express'
    at Function.Module._resolveFilename (module.js:338:15)
    at Function.Module._load (module.js:280:25)
    at Module.require (module.js:364:17)
    at require (module.js:380:17)
    at Object.<anonymous> (/usr/src/app/server.js:1:77)
    at Module._compile (module.js:456:26)
    at Object.Module._extensions..js (module.js:474:10)
    at Module.load (module.js:356:32)
    at Function.Module._load (module.js:312:12)
    at Function.Module.runMain (module.js:497:10)

npm ERR! Linux 4.1.7-15.23.amzn1.x86_64
npm ERR! argv "node" "/usr/local/bin/npm" "start"
npm ERR! node v0.10.38
npm ERR! npm  v2.11.1
npm ERR! code ELIFECYCLE
npm ERR! [email protected] start: `node server.js`
npm ERR! Exit status 8

But what's happened here? Because we mounted the current working directory it overwrote what was previously there in /usr/src/app including our node_modules directory.

So the quick fix here is to now run a npm install in our current working directory and rerun the docker run command.

$ npm install
[email protected] /home/ec2-user/dockernode
└─┬ [email protected]
  ├─┬ [email protected]
  │ ├─┬ [email protected]
...
$ docker run -it -p 8080:3000 -v "$PWD":/usr/src/app dockernodetest

> [email protected] start /usr/src/app
> node server.js

Example app listening at http://0.0.0.0:3000

Now if you make an update to your server.js file just hit Ctrl+c and restart you docker image though you might want to use something like nodemon to make this even more seamless.

like image 143
jeedo Avatar answered Oct 29 '25 05:10

jeedo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!