Vittles for Developing Node.js Apps in Docker
This is a quick draft. I don’t have much time to write tonight, but I wanted to make a note of these things:
I work with boot2docker
on OS X currently. I decided to avoid the pain of NFS mounts / volumes etc that I would normally want to set up when developing an app within Docker, and instead just add my source every time (practical for teensy apps, not practical for big apps).
Whenever Docker builds an image, it uploads the entire contents of the folder that the Dockefile
resides in from the client to the Docker daemon. This can get terribly slow if you have any significant number of packages in your node_modules
directory.
Until this ticket is resolved: https://github.com/dotcloud/docker/issues/2224
Don’t keep the node_modules
directory in your local folder. Maybe create a symlink to a directory outside of the source? I haven’t tried this yet. I don’t know if Docker follows symlinks on context upload.
Use this tip when building your Dockerfile
for efficient image building: http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/
Essentially, ADD
the package.json
file to /tmp
, npm install
there, and then make a directory called /opt/app
or something. Move the node_modules there, and then WORKDIR /opt/app
, and ADD /opt/app .
That way, you’ll only be re-installing dependencies when your package.json changes.
Next, if you want automatic source file watching and server restarting, globally install nodemon
. Then, create a script inside of your project: bin/run
that has the commands to build your docker image and run it. Something like this:
docker kill tmp
docker build -t tmp .
docker run -t -i —rm —name tmp -p LOCAL:CONTAINER tmp
Then run nodemon -x bin/run index.js
and nodemon will automatically watch all .js
files for changes, and when a change happens, it’ll kill your docker container, rebuild it, and re-run it. It should all happen in under a second or two.
The only strangeness I noticed is that my express server in my mode container took sometimes more than ten seconds to respond to an initial request after a container reboot. Subsequent requests were snappy.