Docker Flows for Web Development
Docker can be used in lots of ways as a solution for several different problems, so different that there don't seem to be a consensus on how Docker should be used as part of a development workflow. Here are some flows I've developed while using Docker for webdevelopment (originally written as an answer to this question on Reddit.
Disclaimer: I'm not a docker expert. I'm just figuring out docker as I go along- I've still not completely got my head around volumes and how to manage non-stateless containers. If you have a better process than this please let me know!
#1
First, if you just want to run npm / bower without installing it on the host, you can find a docker image with npm / bower installed (lets say, this one found on docker hub: digitallyseamless/nodejs-bower-grunt, then run this instead of how you would normally run npm:
docker run -v $(pwd)/:/data digitallyseamless/nodejs-bower-grunt npm install
Let's break it down:
-v $(pwd)/:/data
Will mount your current (host) working directory to /mnt inside the container so that npm can actually install files that will remain on the host after the container finishes. Normally the image's readme would describe where to mount your files to, but I think the creators expect this to be used as a base for building an entire app, not a one-off run of npm so they don't explicitly mention /data in the readme. I looked at the image's dockerfile to find that it's using /data.
digitallyseamless/nodejs-bower-grunt
The name of the image to pull & run.
npm install
The command to run in the container. Replace this with whatever you want to run (eg. bower install).
Doing the above allows you to run npm / bower without installing it on the host. Useful for if you need to build on coworkers machines, or on machines with different versions of npm. It's more lightweight (low memory usage) than a fully-blown virtual-machine, starts up quickly, and doesn't need to be kept running (the container will stop as soon as npm completes its task, like npm normally would).
#2
Another use of Docker is to build an image that contains your app for easy deployment. For this, use a Dockerfile starting from the same image above (so we already have node, npm and bower installed in the container). This example assumes you're writing a node program called server.js that listens on port 80. Create a file named Dockerfile in your project's root directory:
FROM digitallyseamless/nodejs-bower-grunt ADD package.json /data/ RUN npm install ADD bower.json /data/ RUN bower install ADD server.js /data/ #ADD any other files required here that are not installed by npm or bower EXPOSE 80 CMD node server.js
Now run `docker build .` and a new image will be built, with all of your npm & bower dependencies installed. You can do `docker run -p 80:80 <hash>` to run it and make it accessible on the host's port 80. Open a browser and point to http://localhost to see it.
This gives you an image that you can test, then push to a docker repository and deploy from there, and know it's identical to what you tested. The downside is that it's slow during development- you have to rebuild the image and re-run every time you make a change. There are tweaks to make sending the build context faster and use layers effectively to avoid a *complete* rebuild every time, but it's still slower than the traditional flow if you've only made a one-line change in your server.js program or added a single dependency which slows down development.
#3
I've just started using a flow where I use the above build process (#2) when I'm ready to test / deploy, but use multiple containers to operate on a mounted host directory while I'm actually developing. So, I'm still running commands like in a traditional development-flow (install a package here using npm like in flow #1, make a change to a file there using my IDE), but have a container permanently running node with a watch (or apache) which picks up the changes and relaunches node to show the changes without needing to do a docker build / run cycle after every change. Then when I'm done I do `docker build` (or actually, have tutum do an automated build on a remote server based off a github commit) which pulls all the dependencies and wraps them into an immutable image which I run tests on / gets sent to QA and then is released using `docker run` on my production server. I've only just started using this flow #3, as I found the flow #2 too slow during actual web-development compared with everything running on my host, but we'll see how it goes!










