I’ve looked Docker a few times, but I never had much of a need in my workflow. Now though, I’m more interested – we’ve got a few microservices that need to be running for our main application. They each are run using Node.js, and the “simple” method is to just open a new terminal window for each, starting them up manually. Of course, that’s something I forget to do until the main app’s tests show failures.
Docker Last week, after watching Scott Hanselman‘s Computer Stuff They Didn’t Teach You video #8: Containers? So What? Docker 101 Explained, I got to thinking about better ways to have those Node servers running.
The first thing I did was to put together a very simple Node application, using Express to serve static html files. To follow along, install Node.js, then open Powershell in Windows Terminal or your favorite console, and create a basic server app:
md node-docker cd node-docker node init npm install express --save
This creates a simple Node application, which I then edited to serve files from a specific directory. In this case, I created a \content
folder at the root of my drive and put a simple index.html
file there.
var express = require('express'); var app = express(); var port = process.env.PORT || 5000; var path = require('path'); var options = { index: "index.html", extensions: ['htm', 'html'] }; app.use('/', express.static('/content', options)); var server = app.listen(port, function () { var host = server.address().address; console.log('listening at http://%s:%s', host, port); });
We can then start the little server using the command node server.js
. Opening a browser to http://localhost:5000/
displays the index file from the content directory. That’s done via line 10, which basically maps the root directory of the webserver (‘/’) to the \content
directory, and serves files from there. Control-C in the terminal will stop the server.
Next, install Docker. We’ll need to create a Dockerfile
file containing the instructions on how to build an image.
FROM node:12 WORKDIR \temp\dockerwork COPY package*.json ./ RUN npm install COPY . . CMD ["node","server.js"]
Docker’s build
command will use that to build an image:
docker build --tag nodedock .
You can use docker images
to see a list of all the images you have on your system, at this point you should see at least your newly-build nodedock
app and an image with Node version 12 itself.
If you were to start up that image now, the app would run but it would have no data – if you watched the video I mentioned above and look at the Dockerfile, you know that the image only contains the app – not the \content
directory. I created it this way on purpose, because I want to have a server app running but I want to be able to create data (html files) outside the app. This means we need give our container (running image) access to our hard disk.
docker run -p 3000:5000 -v /c/content:/content --name nodedock --rm nodedock
This command
* runs our nodedock application,
* maps its port (-p
) 5000 to docker’s port 3000,
* creates a volume (-v
) that points to our c:\content
directory and lets our Node app see it as /content
* and removes the container when we stop it running (--rm
).
Now with that image running in our container, we can open a browser to http://localhost:3000/
. We can open the Docker Desktop application to see all our containers, look at logs and other stats on each, and stop them when we don’t need them. If we don’t use the -rm
flag, they’ll stick around.
Code behind this blog post can be found in this github repo.