From dev to prod with nodejs and hackathon starter using docker compose (Part 1)

In this series of posts I want to show you how to use docker-compose to quickly get up your next nodejs project by working with hackathon-starter. Of course, you can apply this tutorial to other nodejs projects as well. At the end of the series you will have a dev to production workflow with full CI/CD.

Note: For this post the docker version was 1.11.0 and the docker-compose version was 1.7.1

The local dev environment

hackathon-starter is a great boilerplate to start with, so you don’t lose time choosing a programming language, a web framework or a CSS framework. hackathon-starter comes with a MVC project structure, bootstrap 3, CSRF protection and more.

home

Even if you need the “sign in” and the “register” functionality, hackathon-starter supplies you with OAuth 2.0 and plenty of providers (G+, Facebook, Twitter etc.) to use.

sign in

All the difficult parts are already done and you can focus on developing your actual app. Check the example running on sloppy.io: https://hackathon.sloppy.zone (I did not configure any of the auth providers yet, we will cover this in one of the next posts).

api

 

Ok, let’s get started. Clone the repository and cd into your new working directory:

git clone --depth=1 https://github.com/sahat/hackathon-starter.git myproject
cd myproject

Create a docker-compose-dev.yml file with the following content:

version: '2'
services:

  web:
    image: node:6.1
    volumes:
      - ./:/usr/src/app
    working_dir: /usr/src/app
    command: sh -c 'npm install; npm install -g nodemon ; nodemon -e js,jade app.js'
    ports:
      - "80:3000"
    depends_on:
      - mongo
    networks:
      - all
    environment:
      MONGODB_URI: "mongodb://mongo:27017/hackathon"

  mongo:
    image: mongo:3
    command: mongod --smallfiles
    networks:
      - all

networks:
  all:

The following happens here:

We define a service called web using the official docker image node:6.1. Then we mount our current path to /usr/src/app (default working directory of the node container) into the container. We do npm install and also install nodemon like suggested at the github-page  so every code change triggers a reload of the app. On default nodemon only watches .js files for changes. hackathon-starter makes use of jade so we make nodemon also watch .jade files using the -e parameter.

Furthermore, we make use of depends_on so that first mongodb is started and then our app. Using links is deprecated so we are using networks and put both services into the network called all. hackathon-starter uses the environment variable MONGODB_URI to point to mongodb so let’s define that too. In the mongo section we start mongodb with mongod --smallfiles which reduces the initial size for data files means mongodb uses less diskspace. Last but not least we define the network where we already put both services in.

volumes

Note: Even though I had no problems while using vagrant with volumes on mongodb, issues can occur when utilizing Windows & OS X.  So let’s skip it here though it seems to work when using the latest docker beta for Windows & OS X.

Fire it up with

docker-compose -f docker-compose-dev.yml up

and point your browser to http://ip-where-you-started-docker-compose

hackathon-starter is up and running and ready for your changes so let’s do a simple one. Open views/home.jade and change the headline in line 3:

h1 Hackathon Starter with docker compose

By saving the file you will notice nodemon reloading the app. If you reload the browser window you can see the changes too.

hack

Say we have finished developing our new app and want to create a deploy ready container of it. First we need our own docker image so let’s build it. Create a file called Dockerfile inside your working directory:

FROM node:6.1.0

RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY . /usr/src/app/
RUN npm install

CMD [ "node", "app.js" ]

Build it (with your own dockerhubname):
docker build -t yourdockerhubname/hackathon-starter:0.1 .

Then create a docker-compose.yml file to test if your just build image is running like expected.

version: '2'
services:

  web:
    image: yourdockerhubname/hackathon-starter:0.1
    ports:
      - "80:3000"
    depends_on:
      - mongo
    networks:
      - all
    environment:
      MONGODB_URI: "mongodb://mongo:27017/hackathon"

  mongo:
    image: mongo:3
    command: mongod --smallfiles
    networks:
      - all

networks:
  all:

Finally, fire it up. This time we don’t need -f because by default docker-compose.yml is started.

docker-compose up

If everything is fine push your image to the dockerhub. Again don’t forget to replace your dockerhubname.

docker push yourdockerhubname/hackathon-starter:0.1

Now everybody is able to start your app locally using the docker-compose.yml file and a simple docker-compose up. If you want to keep your project private use a private repository instead. In the next blog post we will transform the docker-compose.yml to a sloppy.json file so we can deploy it to sloppy.io. Yes, that will be an easy one 😉

Notes:

docker-compose-dev.yml is doing npm install and  npm install -g nodemon everytime you start it. If you don’t want this to happen just remove this part from the command line.

command: sh -c 'npm install -g nodemon ; nodemon -e js,jade app.js'

Don’t have a sloppy.io account yet? Sign up now, it’s free.