Using codeship to deploy to

In this post, I will show you how to build a CI/CD pipeline with codeship and As an example app, I will use hackathon-starter which is a great boilerplate to start new projects.

hackathon-starter comes with a MVC project structure, bootstrap 3, CSRF protection and more. If you want to use your own app, skip the hackathon part and carry on.


Ok, let’s get started.

Clone the hackathon repository and cd into your new working directory:

git clone --depth=1 myproject
cd myproject

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

version: '2'

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

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


Check this blog post if you want to know what happens in the compose file.

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, running and ready for your changes so let’s do a simple one.

Open views/home.pugand and change the headline in line 3:

h1 Hackathon Starter with

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


Let’s say we are done developing our new app and want to create a deploy-ready container. First, we need to build our own docker image. 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'

    image: yourdockerhubname/hackathon-starter:0.1
      - "80:3000"
      - mongo
      - all
      MONGODB_URI: "mongodb://mongo:27017/hackathon"

    image: mongo:3
    command: mongod --smallfiles
      - 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.


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, simply remove this section from the command line.

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

Let’s deploy your hackathon project to now.

Create the following sloppy.yml file but change the image section to your just uploaded image name and choose your own free domain (also at ROOT_URL):

version: "v1"
project: "hackathon-starter"
      image: "mikemichel/hackathon-starter:0.1"
      instances: 1
      mem: 512
      port: 3000
        - MONGODB_URI: "mongodb://mongodb.backend.hackathon-starter/hackathon"
        - ROOT_URL: ""
        - "../backend/mongodb"
      image: "mongo"
      cmd: "mongod --smallfiles"
      instances: 1
      mem: 512
        - path: "/data/db"
        - path: "/data/configdb"

and start it with the cli

sloppy start sloppy.yml
| frontend | 1 | 0 / 1 | 512 MiB |
| backend | 1 | 0 / 1 | 512 MiB |

check the status using the UI


and open your first version in the browser clicking at the link icon next to “node”.

How to create a rolling update with

What we want to achieve is every push to the master branch of our own git repo will do a rolling update to As we cloned our git repo from hackathon-starter, we now have all the commits from the original repo in the history and our clone still points to the orig. repo so let’s fix this first.

Create a new repo in GitHub (You have to be logged in)(I will name mine “hackathon”) Then, do the needed changes for the cloned repo on the commandline:

cd myproject
rm -R .git # start with a clean git base
git init # initalize a new git repository
git add . # add all files for commit
git commit -m "initial commit"
git remote add origin # use your own created repo here
git push -u origin master # push it

Now let’s configure to do the following when we push changes to our git repo:

– pull code and do some tests
– build a new container and push it to dockerhub
– deploy the new version to

Create a new project:



Connect it to your github repo:



Choose “Basic Infrastructure” and then “nodejs” as technology stack:



Save it and go back to the dashboard. Codeship will now pull and test our code, but what if we want more? We need a new docker image from our code in the dockerhub and it should replace the version already running at

First, we will switch our project to the docker infrastructure by changing it in the general project settings:



An AES key is now displayed. Copy and save it into a file called codeship.aes (gitignore?) inside your git directory. Now download the codeship jet CLI. This tool is used to create encrypted sensitive information like the dockerhub login, which is needed by codeship to be able to push to your docker repo.

After installation, log in into your dockerhub account using docker login and use jet (still inside your git repo) and encrypt your credentials:


docker login
jet encrypt ${HOME}/.docker/config.json dockercfg.encrypted

There should now be a dockercfg.encrypted which is used later by codeship to push the new docker image into your dockerhub repo.

We also want to encrypt the API token when codeshp deploys the new image. We will do this by encrypting the token as environment variable. Following we create a file sloppytoken.env with your own token from (skip the export part!):


Encrypt it:

jet encrypt sloppytoken.env sloppytoken.env.encrypted

sloppytoken.env.encrypted will be created so we should delete sloppytoken.env (!). We don`t want to push our token to github, right?!

Now everything is saved and can configure the actual build and deploy jobs. This is done in codeship via services and steps . In short services is where you configure each service needed to run to CI/CD and builds with Codeship. During the build, these services will be used to run the testing steps you’ve defined in your codeship-steps.yml process. Let’s create the codeship-services.yml file:

    image: mikemichel/hackathon-starter
    dockerfile_path: Dockerfile
  encrypted_env_file: sloppytoken.env.encrypted

Here we define a build with the image output name mikemichel/hackathon-starter, Dockerfile file is used in the current build directory and our encrypted token login is defined for the following codeship-steps.yml we create now:

- service: app
  type: push
  image_name: mikemichel/hackathon-starter
  image_tag: "{{ .CommitID }}"
  encrypted_dockercfg_path: dockercfg.encrypted

- service: app
  command: ./

The first block defines the push to dockerhub and that we want to use the git commit id as image tag. The second part is about the deployment to via which we will create now:

#set -e


# install latest cli
curl -L`uname -s`-`uname -m` > /usr/local/bin/sloppy
chmod +x /usr/local/bin/sloppy

# deploy new image
echo "Deploying new image using the CLI"
sloppy change -img mikemichel/hackathon-starter:$CI_COMMIT_ID hackathon-starter/frontend/node is a bash script so let’s make it executable with chmod +x

It’s a simple bash script, installing the CLI and then uses change command to update your running app to the just created image.

More infos about services and steps at the

Now save, commit and push the changes to your Git repo and codeship will start working. Follow the process live in the codeship user interface.

git add .
git commit -am "changed header"
git push


The last step ( will trigger the deployment. Check the UI:


You will see that only the node container is updated and the version for the node app will change to the git commit id. Every git push will trigger this flow. This will also create a new version in you can always go back to. Just, click on “DEPLOYED” and choose a version for a rollback.

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