Run a Federated GraphQL Server on Kubernetes with Docker

Timothy Miller
May 8 · 4 min read
Image for post
Image for post

In this tutorial we’ll be running a federated GraphQL (gql) server with Kubernetes (k8s) on Docker on your local machine. We’ll be deploying the Apollo Federation Demo project. For those who would rather skip ahead to the finished product you can find my altered clone of the project here.

  • Create a DockerHub account (you could also use my Docker images here)
  • Install Docker
  • Enable k8s with Docker by clicking on the Docker icon in the system tray, click on “Preferences”, then check the checkbox “Enable Kubernetes”.

Apollo Federation is Apollo’s answer for implementing gql in a microservice architecture. It’s designed to replace schema stitching and solve pain points such as coordination, separation of concerns, and brittle gateway code.

Pod: A set of running containers. We’ll have just 1 container per Pod.
Replica Set: A set of identical running pods. We’ll have just 1 Pod per Replica Set.
Deployment: Essentially a Replica Set with automatic rolling updates and autoscaling.
Service: A way to expose an application running on a set of Pods as a network service.

Let’s get started!

Image for post
Image for post
Visualization of the system we’ll be implementing.

We’ll start by cloning the Apollo Federation Demo project and installing its dependencies.

git clone https://github.com/apollographql/federation-demo.git
cd federation-demo
npm i

The demo project is comprised of 4 gql services and a gql gateway. We’ll Create 5 repos on DockerHub. One for each gql service, and one for the gateway. Use these repo names: accounts, reviews, products, inventory, and gateway.

Image for post
Image for post

K8s manifests are used to create, modify and delete k8s resources. We’ll be using manifests to define our Deployments and Services. In the root of your project, run the following:

mkdir manifests
cd manifests
touch workloads.yml
touch services.yml

In the workloads.yml file, we’ll create a Deployment for each of the gql services and the gql gateway. The Replica Set and Pods associated with each Deployment will be created automatically by the Deployment so there’s no need to define them separately. Here’s what your workloads.yml file should look like:

If you would rather use my Docker images, just replace <your_username> with timwebill.

Next up is a Service for each Deployment. As mentioned previously, Services provide us with a way to access a Pod or a set of Pods without having to know the actual IP addresses of the Pods. Here’s what your services.yml file should look like:

Note that our accounts, reviews, products, and inventory Services are of type ClusterIP. These Services are exposed on a cluster-internal IP and are only reachable from within the cluster. The k8s gateway Service is of type NodePort which exposes the service on the Node’s IP at the specified port. This means that we can access the gateway Service but not the other Services. When running k8s with Docker, the Node is available on localhost.

In the root of the project, in the gateway.js file, you will see that the gql services urls are pointing to localhost. This would work if we were running each service in the same Docker container but we aren’t. Instead, we need to make use of the k8s Services we’ve just defined. Change the domain in each url to the name of its corresponding k8s Service. Your gateway.js file should look like this:

K8s automatically configures the DNS system with the kube-dns Service. When a container makes a request to an unknown domain (such as http://accounts:4001), k8s will fetch the correct IP address from the kube-dns service and route the request to the correct IP address.

We’ll create a dockerfile for each gql service and for the gql gateway. From the root of your project run:

mkdir dockerfiles
cd dockerfiles
touch accounts.dockerfile
touch reviews.dockerfile
touch products.dockerfile
touch inventory.dockerfile
touch gateway.dockerfile

Update the dockerfiles to reflect the following:

For each of the 4 gql services and for the gql gateway run the following command from the root of your project:

docker build -f ./dockerfiles/accounts.dockerfile -t accounts . && docker tag accounts:latest <your_username>/accounts:latest && docker push <your_username>/accounts:latest

Be sure to replace the names of the services and also <your_username> with your DockerHub username.

To apply the k8s manifests run the following commands from the root of your project:

cd manifests
kubectl apply -f .
kubectl get all

The output should look something like this:

Periodically run kubectl get all until the all the pods have STATUS “Running”.

Finally, type localhost:30000 into your browser and hit enter. Voila! You now have a Federated GraphQL Service running on Kubernetes with Docker. Here’s a sample gql query to check that the service is running correctly:

To delete your k8s resources from the cluster run the following command from the manifests directory: kubectl delete -f .

If you’ve made it this far well done and thanks for reading!

WeBill

Startup Development and Design

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

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