Effective Docker Healthchecks For Node.js

Writing effective healthchecks will make your services running in Kubernetes or Docker Swarm more reliable

Here we go!

Let’s imagine a service.

The healthcheck

Here’s the healthcheck example. I store it in ./bin/healthcheck.mjs.

#!/bin/sh
':' //# https://medium.com/@patrickleet ; exec /usr/bin/env node --experimental-modules "$0" "$@"

import servicebus from 'servicebus-bus-common'
import { config } from '../config.mjs'
import mongoClient from 'sourced-repo-mongo/mongo'

export const exit = ({ healthy = true } = {}) => {
return healthy ? process.exit(0) : process.exit(1)
}

export const check = () => {
return Promise.all([
mongoClient.connect(config.sourced.mongo.url),
servicebus.makeBus(config.servicebus)
])
}

export const handleSuccessfulConnection = (healthcheck) => {
return () => {
healthcheck({ healthy: true })
}
}

export const handleUnsuccessfulConnection = (healthcheck) => {
return (e) => {
healthcheck({ healthy: false })
}
}

check()
.then(handleSuccessfulConnection(exit))
.catch(handleUnsuccessfulConnection(exit))

Let’s break it down, and then explore how we can use it in production.

#!/bin/sh
':' //# https://medium.com/@patrickleet ; exec /usr/bin/env node --experimental-modules "$0" "$@"
export const exit = ({ healthy = true } = {}) => {
return healthy ? process.exit(0) : process.exit(1)
}
export const check = () => {
return Promise.all([
mongoClient.connect(config.sourced.mongo.url),
servicebus.makeBus(config.servicebus)
])
}
export const handleSuccessfulConnection = (healthcheck) => {
return () => {
healthcheck({ healthy: true })
}
}

export const handleUnsuccessfulConnection = (healthcheck) => {
return (e) => {
healthcheck({ healthy: false })
}
}

check()
.then(handleSuccessfulConnection(exit))
.catch(handleUnsuccessfulConnection(exit))

Using the healthcheck

Now, to use the healthcheck easily, we are going to do two things.

  1. Set up the bin section of package.json to expose our healthcheck command.
  2. npm link to be able to call the healthcheck
{
"bin": {
"healthcheck": "./bin/healthcheck.mjs"
},
// rest of package.json
}
FROM node:10-alpine as build

# install gyp tools
RUN apk add --update --no-cache \
python \
make \
g++

ADD . /src
WORKDIR /src
RUN npm ci
RUN npm run lint
RUN npm run test
RUN npm prune --production
FROM node:10-alpine

ENV PORT=3010
EXPOSE 3010

COPY --from=build /src/package.json package.json
COPY --from=build /src/package-lock.json package-lock.json
COPY --from=build /src/node_modules node_modules
COPY --from=build /src/bin bin
COPY --from=build /src/handlers handlers
COPY --from=build /src/lib lib
COPY --from=build /src/config.mjs config.mjs

RUN npm link
HEALTHCHECK CMD healthcheck

CMD node --experimental-modules ./bin/start.mjs
RUN npm link
HEALTHCHECK CMD healthcheck

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Patrick Lee Scott

I make things for the internet, that scale, look nice, and make money!