Software Engineer, builder of webapps

How to run Node.js in a rocket container

Last time we talked about "Building a fedora-based rocket container", so today we're going to use that as a base to build a container for running NodeJS applications.

If you are just joining us, please go back and read "Building a fedora-based rocket container" as the post includes instructions on how to get set up with rkt, acbuild, and actool and introduces the basics of building a container.

Building a NodeJS rkt container

While it is possible to statically compile node, native npm modules will sometimes need to link off of libraries included in the system. So for this particular demonstration, we're going to use the Fedora container we created in the previous post as a base for our node container.

Back to acbuild

Our acbuild procedure is going to look something like this:

acbuild begin
sudo acbuild dependency add <your domain>/fedora:latest
sudo acbuild set-name <your domain>/nodejs
sudo acbuild label add version "4.2.3"sudo acbuild run -- /bin/bash -c "curl https://nodejs.org/dist/v4.2.3/node-v4.2.3-linux-x64.tar.gz | tar xvz --strip-components=1 -C /usr/local"sudo acbuild write nodejs-4.2.3-linux-amd64.aci
sudo acbuild end

Let's go through this step by step:

sudo acbuild dependency add <your domain>/fedora:latest

This tells acbuild to use the Fedora container we built in the previous post. As you can see, we're also specifying a version of latest. acbuild will first check the local container cache to see if it exists, otherwise it will use http based discovery to location the container (more on discovery and how to set it up to come in a later post)

acbuild label add version "4.2.3"

Since we're pulling in node v4.3.2, we'll tag the version of our container as such.

sudo acbuild run -- /bin/bash -c "curl https://nodejs.org/dist/v4.2.3/node-v4.2.3-linux-x64.tar.gz | tar xvz --strip-components=1 -C /usr/local"

acbuild run is analogous to the RUN parameter you would find in a docker file; it can be used to execute a command within the container. In the case of acbuild (and rkt), what happens is acbuild actually starts systemd-nspawn to run the command against the rootfs as defined by the included dependencies.

sudo acbuild write nodejs-4.2.3-linux-amd64.aci

Now we're getting a little more fancy with our file naming. In this case, we have named our aci in a way that allows us to make it discoverable later on, following the format of:

{name}-{version}-{os}-{arch}.{ext}

So if I named my container seanmcgary.com/nodejs, the discovery mechanism would at:

https://seanmcgary.com/nodejs-4.2.3-linux-amd64.aci

Packaging an application

Now that we have our nodejs base container, we can create another container to house our test application. A while back I wrote a little app called stupid-server that can be found over on github at seanmcgary/stupid-server. Let's create our container:

# first clone the repogit clone https://github.com/seanmcgary/stupidServer.git
acbuild begin
sudo acbuild dependency add <your domain>/nodejs:4.2.3
sudo acbuild set-name <your domain>/stupid-server
sudo acbuild label add version 1.0.0
sudo acbuild copy ./stupid-server /stupid-server
sudo acbuild set-exec -- /bin/bash -c "node /stupid-server"sudo acbuild write stupidServer-1.0.0-linux-amd64.aci
sudo acbuild end

We have some new commands in our process:

sudo acbuild copy ./stupid-server /stupid-server

This one is pretty straightforward - takes a local file/directory and a destination path of where to put it in your container.

sudo acbuild set-exec -- /bin/bash -c "node /stupid-server"

Here, we are specifying what to run when rkt executes our container. set-exec is analagous to CMD <command> found in a Dockerfile.

Running our application

As a quick recap, we have an application that inherits a chain of containers that looks like this:

fedora --> nodejs --> stupidServer

Now we can actually run our container with rkt:

sudo rkt run --insecure-options=all --net=host ./stupidServer-1.0.0-linux-amd64.aci

rkt: using image from local store for image name coreos.com/rkt/stage1-coreos:0.13.0
rkt: using image from file /home/core/node/stupidServer-1.0.0-linux-amd64.aci
rkt: using image from local store for image name seanmcgary.com/nodejs,version=latest
rkt: using image from local store for image name seanmcgary.com/fedora,version=latest

If you want to push it to the background, you can also run it with systemd-run:

sudo systemd-run rkt run --insecure-options=all --net=host /home/core/stupidServer-1.0.0-linux-amd64.aci

Now with your container running, you should be able to hit your server:

curl http://localhost:8000/
2015-12-16T00:36:46.694Z

Wrap up

That's it! Now that you know how to build containers based off of other containers, you should be able to figure out how to deploy your own app in a containerized fashion.

Next time, we'll talk about how to set up discovery so that you can host your containers in a central location.