If you are one of the few that have not yet taken the plunge into Docker don’t feel ashamed. I haven’t either. I’ve been too busy doing other stuff lately. But yesterday I actually started using Docker because I had a real life use case. I have a Node application that I wanted to ship in a Docker container. And I wanted it quickly.
So here is what you need to package a Node application in a Docker container.
Docker for Mac and Docker for Windows
Step 1 is to install the Docker engine for Mac or Windows. Head over to https://docs.docker.com/engine/installation/mac/ and install Docker for Mac or Docker for Windows.
What happens? You just transformed your machine into a Docker engine. With this Docker engine you can host containers, from images containing your applications.
This is how you get started and start developing. Production environments are better installed in another Docker Engine, somewhere in the cloud or in a datacenter.
Docker on Linux
The Docker Engine on Linux is in its natural habitat and installing it (on Ubuntu Xenial) is as easy as:
sudo apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D echo "deb https://apt.dockerproject.org/repo ubuntu-xenial main" | sudo tee /etc/apt/sources.list.d/docker.list sudo apt-get update apt-cache policy docker-engine sudo apt-get install -y docker-engine sudo usermod -aG docker $USER
First steps
First, check the installation:
docker version
1.12 is the latest version:
Let's go ahead and create our first image for a Node Express app.
Package a Node.js Express app
Cd into a Node application you want to package, or clone mine. If you clone mine, install Node.js on your platform if you haven't already. and check if it runs.
git clone https://github.com/jacqinthebox/node-express-starter cd node-express-starter npm install gulp serve
If all is well you will be presented with a static website. The theme is from Black Tie.
First step is to create a Dockerfile.
Assuming you are still in the node-express-starter dir, run:
touch Dockerfile
This will be the folder structure from node-express-starter:
. ├── Dockerfile ├── app ├── bower.json ├── gulpfile.js ├── main.js ├── node_modules └── package.json
This is how the Dockerfile should look like:
FROM mhart/alpine-node:6.3.0 MAINTAINER Jacqueline # copy all the files from the Node app to /var/www in the container: COPY . /var/www #set it as workdir WORKDIR /var/www #install dependencies from package.json RUN npm install # Expose port 3000 from the container to the host EXPOSE 3000 ENTRYPOINT ["node","app.js"]
What does this mean?
- FROM: here we need to put the base image for our image. Lots of these images yoy can find on the [Docker Hub](https://hub.docker.com/explore/). I want the image to be as small as possible. So that's why I'm using an [Alpine](https://github.com/mhart/alpine-node) based image.
- COPY: I copy all the files from my node project to the /var/www folder on my Docker image
- WORKDIR: /var/www is the workdir (pwd)
- RUN: while in /var/www, the npm install is run to install all dependencies of the Node app.
- EXPOSE: here you can set the port for communication with the outside world. My Node app runs on port 3000
- ENTRYPOINT: the command 'node app.js' will run upon starting the container (not when creating the image of course)
Now create the container image. You should still be in the node-express-starter dir. Run the following command (don't forget the dot):
docker build -t jacqueline/impatient .
This has created a Docker image with the tag (-t) 'jacqueline/impatient'.
Now run it
docker run -d -p 8080:3000 jacqueline/impatient
With -d the container instance is ran as a daemon and the -p is the port redirection (3000 we exposed in our image will be forwarded to port 8080)
Now head over to http://localhost :8080 and you should be presented with the Node web application:
Recap:
- We installed the Docker Engine on our computer
- We created a Docker image containing our Node app
- We started an instance of this image
Stopping and cleaning up
If you work with containers, lots of harddrive space will be consumed. This is how you clean up stuff.
First, check which containers are currently running with 'docker ps':
docker ps
Obviously, the one we just ran is active:
Notice the container ID. You can stop this instance with:
docker stop 45
Next, delete the container. First list all the containers:
docker ps -a
Again, notice the ID:
docker rm 45
Now that the container is deleted, we can go ahead and remove the image. First check which images are present:
docker images
There are 2. I'm only going to remove my own image, not the Alpine one.
docker rmi 78
In the screenshot above notice how I forgot to delete the container, but I could still delete the image with the -f flag.
The End. But will be continued.
Of course now that we took the Docker plunge, we now want to host our container in the cloud. At Digital Ocean, AWS or even Azure. This will be covered in part 2.