Schedule a FREE onboarding and start making pipelines fast.

Up and running with io.js and Docker

Docker Tutorial | April 17, 2015

This is a quick post for getting up and running with io.js and a single, simple Dockerfile using Docker 1.6, which was just released. It is not an exhaustive post on using either io.js or Docker.

Install Docker

Go get Docker and install it from here.

Verify that Docker 1.6 is running:

Get the iojs image

Now go get the official iojs image:

This will download the latest iojs image from the official iojs repo on Docker Hub.

An image is used by Docker to launch a process in a container. An image is comprised of all the bits that provide an operating system environment for running a process. When the process runs, it runs in a “container” completely isolated from any other process as if it were running in its own machine.

You can verify that the image has been downloaded successfully by entering:

You can verify that no containers are currently running by entering:

(Note that the column header names wrap, and so do any container entries, based on the width of your terminal)

If you have already been using Docker, you may see a few containers listed, but you shouldn’t see any with the image name ‘iojs’ yet.

Run a container

The iojs image was built to run the iojs command if you don’t explicitly specify a different command to run. Like node, the iojs command creates a REPL for entering JavaScript commands

You can test it like this:

The REPL just waits for you to enter JavaScript. You can enter <Ctrl-c> twice to exit the REPL.

What did we do? We told docker to start a container based on the iojs image. The default command for the iojs image is iojs, so it started a REPL and waited for JavaScript to be entered.

The reason it waited is because of the -it options. The i option keeps STDIN open for the process, and the t option allocates a pseudo-TTY. The combination is what allows us to interact with the REPL as if we had started it directly in a terminal instead of inside of a container.

When trying things out, you will create a lot of containers. It’s a good idea to use the -rm option to automatically delete the container when you stop it to keep things tidy.

Override the default command

When we tell Docker to start a container from the iojs image, we can explicitly provide a command to override the default one. The following will run bash instead of

This will put you at a bash prompt in the container. You can check the version of iojs you’re running:

Since node is symlinked to iojs when iojs is installed, you can also just enter:

As you can see, the current iojs image runs iojs v.1.6.4.

The docker-iojs team tracks the latest io.js versions and updates the official iojs image for Docker as quickly as they can.

The io.js team releases new versions fairly rapidly and the newest version is now 1.7.1. The docker-iojs team supports three different iojs images (explained later). They move pretty quickly to update the iojs Dockerfiles (used to build images) with a pull request. They then submit yet another pull request with the information necessary to update the official repo and make the new images publicly available. The latest version (1.7.1) should be available within the next day or so.

Using the iojs:onbuild image

The iojs image we used above is not the only image the docker-iojs team maintains. They also maintain a slim version (not recommended except under specific circumstances) and an onbuild version that makes building derivative images easier.

The onbuild version is based on the plain iojs version used above, but it copies your node application to the container and then runs its. Creating a derivative of this image can be as simple as referencing it and specifying the port you want to expose.

Here’s a simple example to illustrate. Create a demo directory.

Create a package.json file with the following:

Create app.js and just print something to the console to prove it works:

Create a Dockerfile:

Now create an image:

Docker will create an image based on the Dockerfile in the current directory and name it demo-app. As part of creating the image, it ran instructions from the onbuild base image that we specified in our Dockerfile that included copying the contents of the current directory to /usr/src/app/ and running npm install.

You can see what the instructions look like here.

Now run demo-app in a container:

The iojs app is trivial, but the mechanics of how this works is the same for more complicated examples. One thing you will probably want to do is export a port for accessing your node application, which we cover in the next section.

Pushing your image

If you are happy with your application at this point, you might want to push your image to Docker Hub. You will need to create an account on Docker Hub, then login from the command line:

Only official images (such as iojs) can have simple names. To push your own image, you will need to change the name of the image. Instead of demo-app, you will need to create the image using your login name. Mine is subfuzion so my docker build and docker push commands would look like this:

Exposing a port for a server

Modify the demo to make it an express app. Install express:

Then edit app.js:

And update Dockerfile:

Rebuild the image:

Now we can run it, but we want to map port 3000 inside the container to a port we can access from our system. We’ll pick port 49100:

Now we can access the app via port 49100, which will be mapped to port 3000 in the container.

If you’re using boot2docker on a Mac, the port is actually mapped to the Docker host virtual machine. To determine the IP address, enter this at the command line:

You should be able to test http://192.168.59.103:49100/ in your browser.

The app looks for the environment variable PORT to be set, otherwise it defaults to 3000. We could specify an alternate port via the environment from the command line like this:

You will still access the app using the external port 49100, but it is now mapped to port 8080, which is what the app is listening to since the environment variable PORT was set.

Next time

We will cover the networking aspects in a bit more detail, show how you can mount the source instead of copying during development, and begin to cover the topic of orchestration, starting with a simple mongo dependency.

Raziel Tabib

About Raziel Tabib

Co-Founder and CEO, Codefresh

Reader Interactions

Enjoy this article? Don't forget to share.

Comments

Your email address will not be published. Required fields are marked *

Follow me on Twitter