Tips for running an efficient CI and CD system
Will Munn
works at: focusrite/novation
github: @willm
What is continuous integration?
- Checking every commit can integrate with the current system
- Alerting development teams of failures as quickly as possible
What is continuous delivery?
- Regularly deploying small changes to production
- Alerting development teams of failures as quickly as possible
Tools for CI / CD
![](http://cdn2.hubspot.net/hub/323094/file-857463070-jpeg/jenkins.jpeg#keepProtocol)
![](https://blog.jetbrains.com/teamcity/files/2008/09/teamcity512.png)
![](http://www.code-maze.com/wp-content/uploads/2016/02/go-cd-logo.png)
![](https://circleci.com/circleci-logo-stacked-fb.png)
![](http://site-cdn.microapps.com/wp-content/uploads/2015/11/Travis-CI.jpg)
Configuring your tool
Tip No1
keep your agents lean
![](http://i.imgur.com/pkqmF0k.png)
![](http://devstickers.com/assets/img/cat/nodejs.png)
Team A
![](http://www.clipartbest.com/cliparts/LiK/eMe/LiKeMe9ia.png)
Team B
Team C
![](http://devstickers.com/assets/img/cat/nodejs.png)
![](https://siliconangle.com/files/2013/05/git-logo.jpg)
![](http://securityaffairs.co/wordpress/wp-content/uploads/2014/12/google-app-engine.png)
4.x.x
7.10.0
![](http://www.simplybusiness.co.uk/media/tech/install-all-the-things-a-capistrano-extension-to-run-puppet/things.png)
Why is this bad
- Hard to scale
- Uses more resources
Solutions
- install npm packages locally
- Script the agent configuration process
- Use docker
Tip No2
Keep configuration in source control
#! /env/sh
npm install
npm test
git push heroku master
Your build script
git clone git@github.com:willm/speed-up-ci.git
Checkout source
Build step to build and deploy your code
#!/usr/bin/env/ sh
npm install
npm test
git push heroku master
Your build script
git clone git@github.com:willm/speed-up-ci.git
Checkout source
Build step to build and deploy your code
0 9 * * *
Cron to run build at 9:00am daily
![](http://media02.hongkiat.com/webdev-with-mongodb-part1/mongodb-logo.jpg)
Plugin that configures canned test data
![](http://cliparts.co/cliparts/6ir/6xz/6ir6xzzMT.png)
Plugin that reports awesome test output
Your build script
Plugin that emails stake holders when a release happens
Plugin that zips your built source only and stores it somewhere
![](http://feldmancreative.com/wp-content/uploads/2014/02/email.png)
![](https://upload.wikimedia.org/wikipedia/commons/f/fa/Simple_Comic_zip.png)
![](https://media.giphy.com/media/K3X9P8I343FLO/giphy.gif)
Super awesome plugin that is critical to making a release functional.
You can't deploy because the CI server that holds the of the necessary steps is down
Why this is bad
Solutions
- Keep all the CI logic in a script or task runner
- Resist the urge of using every feature / plugin of your CI tool.
- Commit your build definitions (jenkins pipeline, circle.yaml, etc...)
Tip No 3
Avoid npm bloat
#!/usr/bin/env bash
npm init
npm install --save express request mocha typescript grunt
![](http://images6.fanpop.com/image/photos/34000000/Female-Ninja-ninjas-34049725-600-451.jpg)
![](http://media02.hongkiat.com/facebook-likes-with-node-js/node-js.jpg)
![](http://devstickers.com/assets/img/pro/0mfj.png)
![](http://azu.github.io/js-test-fiddle/images/32ea98bb.mocha-logo.png)
![](http://www.shop-freelancer.de/wp-content/uploads/2013/11/grunt.png)
$ du -h -d 1
50M ./node_modules
50M .
$ ls -al node_modules | wc -l
199
$ find . -type f | wc -l
4086
![](https://s3.amazonaws.com/media-p.slid.es/uploads/653337/images/3820516/Screen_Shot_2017-05-18_at_23.04.39.png)
![](http://4.bp.blogspot.com/-EZltbinWLuE/UpbLe3jt-tI/AAAAAAAALyY/bpbPmuLkzeE/s400/10seconds.png)
Solutions
- learn node core!
- Install modules as you need them
- Avoid massive frameworks (angular2, ionic)
- Start with lightweight modules and solutions
const http = require('http');
http.createServer((req, res) => {
res.writeHead(200, {'Content-Type': 'application/json'});
res.end(JSON.stringify({greeting: 'Hello World'}));
}).listen(3000);
needle 808Kb vs request 6.3Mb
tape 2.1Mb vs ava 34Mb
router 1.1Mb vs express 1.7Mb
npm scripts vs $BUILD_TOOL
Tip No4
keep your docker images lean
Large Images
- Take up unnecessary disk space on your instances
- Take longer to build and deploy
- More software can = more things to go wrong
Suggested workflow
2 dockerfiles
Development
FROM node:7.10.0-alpine
RUN mkdir /app
ADD package.json /app/package.json
WORKDIR /app
RUN npm install
ADD . /app
RUN npm run build
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
node 6.9.2 178934e73268 6 days ago 651.2 MB
node 6.9.2-alpine de529845c111 6 days ago 50.69 MB
Production
FROM 7.10.0-alpine
ADD . /app
WORKDIR /app
CMD npm start
'.' should be a directory containing your built application without dev dependencies, tests and anything else that isn't needed by your application at runtime.
Build steps
- Build development docker image
- Run tests inside development container
- Remove all non runtime specific files
- Build and publish your production docker image with your built artefact.
- Run smoke tests on the running image in a test environment.
- Repeat in production.
Multi stage pipelines
- A new native docker (17.05+) solution for intermediate build and test containers in a single Dockerfile
https://codefresh.io/blog/node_docker_multistage/
Tip No5
Use docker-compose
![](https://www.codeforest.net/wp-content/uploads/2010/09/Database_1.png)
![](http://www.snow-mirror.com/wp-content/uploads/2014/08/learnmore-api.png)
![](http://www.obrienwebdesign.com/wp-content/uploads/2012/03/Solid-Web-Design.png)
![](http://www.unixstickers.com/image/cache/data/stickers/pivotal/RabbitMQ.sh-600x600.png)
![](https://yt3.ggpht.com/-gjxoCu8Fu3c/AAAAAAAAAAI/AAAAAAAAAAA/Uji17DdykF4/s900-c-k-no/photo.jpg)
version: '2'
services:
openshift:
build:
context: './src/test/containers/openshift'
dockerfile: 'Dockerfile'
service:
build:
context: './src/test/containers/service'
dockerfile: 'Dockerfile'
mutual-ssl-service:
build:
context: './src/test/containers/mutual-ssl-service'
dockerfile: 'Dockerfile'
api:
build:
context: '.'
dockerfile: dev.Dockerfile
image: 'yaapi'
expose:
- '3000'
links:
- service
- mutual-ssl-service
- openshift
environment: '...'
command: sh -c 'npm start | node_modules/.bin/bunyan'
tests:
container_name: tests
image: yaapi
command: 'npm test'
working_dir: /app
links:
- api
- service
Other tips
- Get a build monitor
- Integrate with pull requests
- Try yarn
- Run your tests in parallel
Faster CI with node and docker
By Will Munn
Faster CI with node and docker
- 339