Trust your Host machine to bring the application code, use Docker as a wrapper for executing it.
Node Specific ExampleWhat follows here is a NodeJS specific implementation of the above, generalPrerequisitesDocker: https://www.
com/get-startedThat’s it!Seriously, that is the whole point of doing this.
Use a container to wrap a consistent environment.
(Optional) Make your own Docker imageHere we make a Dockerfile to create a Docker image that has the exact versions of node and npm that we want.
You may have other external dependencies like imagemagick for your app which we would want to install for this step.
Let’s say we have a hypothetical app with node 8.
0and npm 5.
Then we will want to create a file called Dockerfile with the content below:FROM node:8.
0RUN npm install -g npm@5.
0# RUN npm config set registry https://npm.
io/USERNAME/ # set up private NPM registry# do any setup steps here.
installing imagemagick, etc.
ENV FORCE_COLOR=1 # this lets npm log colored outputWORKDIR /appYou should then docker build -t dev-node .
this Dockerfile to create your personal development image.
If you're starting a totally new project you could potentially skip this step entirely if you wanted to just use FROM node:10 with whatever those defaults are.
In which case, feel free to have no Dockerfile, and just use node:10 in place of dev-node in the later steps.
com/ first to see if there’s a well maintained public image that works for your use case.
Running the containerNow inside your source directory on your host machine, we do a few things.
We want node_modules to be persisted in a docker volume that is optimized for our container to write.
We want everything else in the source directory to be persisted on the host machine, mounted to the /app folder, and optimized for our container to read.
I’m also making the assumption that our node app exposes port 3000 (but if you're using a different port just replace with that).
In our hypothetical directory we want to install our node_modules inside of our container:docker run –rm -v MYAPP_modules:/app/node_modules -v $(pwd):/app:cached dev-node npm installNow we are ready to run our app!.Assuming we have a start script defined in our package.
json we simply:docker run –rm –name myapp -v MYAPP_modules:/app/node_modules -v $(pwd):/app:cached -p 3000:3000 dev-node npm startBreaking this down:docker run – This creates a new container and runs the appropriate docker image in it.
–rm – This tells docker to destroy the container upon exit.
–name myapp – Name's the container "myapp" (useful for other commands)-v drive-search-responsive-vol:/app/node_modules – creates a docker volume to mount the data located at /app/node_modules so any files the docker image writes to /app/node_modules will be stored in a volume named drive-search-responsive-vol.
This lets us remove and re-create docker images without needing to npm install each time-v $(pwd):/app:cached This mounts the pwd (present working directory) to the /app directory in the container using a cached configuration.
More info on cached here.
-p 3000:3000 – This tells docker to forward the containers port 3000 to the host machine's 3000, so it is accessible at localhost:3038-it – Short for –interactive and –tty.
Basically enables interactive terminal in docker so that you can send signals/STDIN to the container (ex.
The host typing ^C will pass through to the container)pcln-node – This is the docker image we want to run.
npm start – This is the command we want to run in the container (we could replace it with anything and see it get run in the container).
This will be run at the WORKDIR specified in the Dockerfile (In our case /app).
So as you see we pretty much have a docker run .
and then the command we would normally run locally.
We can continue this pattern for basically anything: docker run .
npm test, etc.
That’s it!!!Now you don’t need to make sure your whole team is always on the right version of npm and node, because docker run wraps everything.
But this is still not completely ideal.
What if someone mistypes one of those -v ______ statements.
Well, that’s where better tooling comes in handy!Making it easierUsing docker-compose.
ymlThe first thing that can be done to make this easier is to make a base docker-compose.
yml for your application.
This can function as a configuration file for the volume and port configurations.
For our example above this docker-compose.
yml probably makes the most sense.
version: '3'services: app: image: dev-node working_dir: /app volumes: – .
:/app:cached – node_modules-vol:/app/node_modules command: npm start ports: – "3000:3000"volumes: node_modules-vol:Okay, so how does this help us?Well, now instead of having to type `docker run –rm –name myapp -v MYAPP_modules:/app/node_modules -v $(pwd):/app:cached -p 3000:3000 dev-node npm start we should be able to type docker-compose up (since that’s what we set our command: to, for the same effect.
If you want to npm install instead ofdocker run –rm –name myapp -v MYAPP_modules:/app/node_modules -v $(pwd):/app:cached -p 3000:3000 dev-node npm installWe can do a simple docker-compose run –rm app npm install , and so forth npm test would be docker-compose run –rm app npm test.
We can do better!This is already much nicer, but let’s go even further with docker-dev-tools .
npm i -g docker-dev-toolsThis adds a few powerful aliases to your terminal.
Now instead of docker-compose run –rm app npm test that boilerplate docker-compose run –rm app npm can be replaced with 3 letters: dpm.
dpm installdpm testdpm start # this is a special command that runs docker-compose upIf you want to do more than just run npm , dssh creates an “ssh” like session inside your image.
I plan to follow up this blog post with some more details specifically on docker-dev-tools and it’s many uses.