Getting a graphQL server up and running against CockroachDB on Kubernetes

Cloud Platform (intermediate level) posted on 1st Feb 2018

In Getting cockroachDB running with Kubernetes I covered how to get your cockroach database orchestrated by Kubernetes. Next you'll want to get your API running. In this example I'm going to run it as a pod on the same Kubernetes cluster, then expose it as a service. This is actually the easy part. The more complicated part is exposing that service externally over SSL. That'll be the next post. 

The server App

I'm not going to go into the entire code of the app here now, as this assumes you have your own server app and this article is just about how to integrate it with your back end DB on Kubernetes. I'll cover the whole topic of GraphQL its own right in a different section.  I also assume you've read Getting cockroachDB running with Kubernetes to get grounded on the language of Kubernetes.

I'm using express to expose my API. Here's the code for the initialization part, which is of interest for the Kubernetes configuration.  The rest of server code is in ./app/server and not in scope of for this article.
const server = require ('./app/server');// to run the appconst express = require('express');const graphqlHTTP = require('express-graphql');// CORSconst copts = { origin: function (origin, callback) { callback (null, true);}};const app = express();// lets goserver.start() .then (options=> { const { pool, schema }= options; // allowing cors app.use(require('cors')(copts)); // express middleware app.use('/graphql', graphqlHTTP({ schema: schema, graphiql: true, context: { pool } })); // start listening app.listen(process.env.PORT || 4000 ,process.env.IP || ""); return app; });

This pretty standard structure for an express app. Interactive graphQL will be via the /graphql endpoint. 


The first step in getting this on Kubernetes is to create a Docker image. 
FROM node:alpineMAINTAINER Bruce Mcpherson <>#create a workdirectoryWORKDIR /usr/src/fidserver#get the package filesCOPY package*.json ./#install the dependenciesRUN npm install#copy the files requiredCOPY . .#expose portEXPOSE 4000EXPOSE 26257#secret these laterENV FIDPASS xxxxxxxxxENV FIDUSER xxxxxxxxxENV FIDHOST cockroachdb-public#how to run itCMD [ "npm", "start" ]

In case you're not familiar with Dockerfiles, a quick summary of what's going on here is 
  • The base image is being copied from a Nodejs public image called alpine
  • the app is going to be based in /usr/src/fidserver
  • the package.json and package-lock.json are copied over from my local VM (I'm using the cloud shell for that - Your own free linux VM)
  • npm installs the dependencies in package.json
  • the rest of my files are copied over
  • the Ports used by the app are exposed (ingress in on port 4000 and the database connection is on port 26257)
  • various environment variables are set for authenticating to the DB. I'm still using the insecure version of cockroach at this stage. Later on , I'll replace this with certificate access.
  • FIDHOST is the endpoint for the cockroachdb set up in Getting cockroachDB running with Kubernetes
  • CMD tells Docker how to run the app defined in package.json like this
"scripts": {
"start": "node index.js"

3 steps are required to build the image and put it somewhere that Kubernetes has access to - in this case the Google container registry -
  • build the image
  • tag the image, so it can be found later
  • push the image to the Google container registry. 
docker build -t brucemcpherson/fidserver .docker tag brucemcpherson/fidserver docker -- push


Now we're ready to deploy and create a service. As usual we'll use .yaml files. It's a good idea to use kubectl apply rather than create, as this will update any previous attempts, whereas create will  complain and fail.

kubectl apply -f fidserverDeploy.yaml

apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: fidserver-deploymentspec: replicas: 1 template: metadata: labels: app: fidserver spec: containers: - name: fidserver image: imagePullPolicy: Always ports: - containerPort: 8000

kubectl apply -f fidserverService.yaml

apiVersion: v1kind: Servicemetadata: name: fidserver labels: app: fidserverspec: selector: app: fidserver ports: - port: 4000 protocol: TCP nodePort: 30061 type: LoadBalancer

Ports and service types

With the various redirections going on, I find the most confusing part is keeping track of port numbers through the various components. We'll need to know these port numbers later on as the next step is to use google endpoints to expose this service externally, but first - some definitions of the complicated world of Kubernetes ports and IPS and how they relate to services.

You'll see from the earlier listing that each service has a type. A ClusterIP type of service can only be reached from inside the cluster. So you would see <none> as the EXTERNAL-IP of of one of these types of services. In the service listing above, the cockroachdb-public service is only accessible within the cluster - It's only the API that talks to the database that should be exposed externally.
This type of service can be used to expose a service externally, and will provide an external-ip that can be reached from outside. 
A Nodeport service provides a 


Why not join our forum, follow the blog or follow me on twitter to ensure you get updates when they are available.