The New Modern Backend: Node, GraphQL, Prisma & Docker

avatar
Marshal Murphy
May 19, 2020 - 9 MIN READ

GraphQL has emerged as a very popular alternative to REST, being adopted by such household names as GitHub and Shopify.

Developed internally at Facebook in 2012 and publicly released in 2015, GraphQL is a query language for your API. You can think of GraphQL as an API gateway between your app and a database.

Prisma pairs well with GraphQL by auto-generating a type-safe query builder that’s tailored to your database schema.

This means that with Prisma we can focus on our data without having to worry about complex SQL queries.

Today we are going to set up a new modern backend to carry us into the future.

Feature

Using Node.js as a base for our backend app, we will be implementing GraphQL and Prisma, configuring a cloud database in Heroku, and connecting our local app to it through Docker.

Then, in the follow-up to this article, we will dive into some practical GraphQL and Prisma, where I will show you how to write a mutation for authenticating, signing up and logging in a new user.

Ready?


Prisma Scaffolding

We are going to begin by creating our project folder, initializing the package.json file for out Node app, and installing a couple dependencies.

In your command line (terminal), start by creating a folder for our project. I’m calling mine modern-backend. Change directory into the project folder and initialize it with npm.

> mkdir modern-backend
> cd modern-backend
> npm init -y

Now let’s install the dependencies we need.

We are going to use graphql-yoga to easily set up a GraphQL server, and we will need the prisma client library to support all things Prisma.

> npm install --save graphql-yoga  prisma-client-lib

This will update your package.json and create package-lock.json, as well as a node_modules directory for our dependencies.

Now, in order to use Prisma, we will need to install the Prisma command line interface (Prisma-CLI). In your terminal run:

> npm install -g prisma

That’s it! We have everything we need.

In your project root directory, initialize Prisma and select the following options as they are presented to you:

> prisma init prisma
> Create new database
> PostgreSQL
> Prisma Javascript Client

When the initialization is complete we will have a project structure that looks as follows:

files

Now that we have our Prisma scaffolding in place, let’s set up our Node server!


Node Server & GraphQL

Alrighty so, we have put together a base scaffolding for Prisma.

Now we need to create the necessary config for using Node and graphql-yoga to launch our local GraphQL server.

Let’s start by creating a new /src directory in the root of the project, and adding an index.js file.

In src/index.js begin by adding our dependencies. We are going to import GraphQLServer from graphql-yoga, and prisma from the Prisma resources we generated.

After that we need to build the server, so create a server variable from graphql-yoga, and set it up as follows:

Here, we are using context to receive a function that returns the merged object of anything contained in the GraphQL response with Prisma.

Lastly, we cap the file by starting the server. But if we started the server right now, it would fail.😕

This is because the server requires two more important pieces: resolvers & type definitions.

When we generated our Prisma scaffolding, out-of-the-box it supports a User model. In the follow up to this article we will expand upon this and create additional models, but for now let’s use the Prisma User definition in the default generated prisma schema to round out our setup and get this server up and running.

Create a file called ./src/schema.graphql and add the User type definition:

// src/schema.graphql

type User {
  id: ID!
  name: String!
}

This defines the User type, which has a required( ! ) ID and name.

Now let’s import this type definition into our server config:

TypeDefs down. Now for resolvers.

Resolvers are functions that allow GraphQL to populate the data for a single field in our schema.

Here we will simply write a resolver called users that returns all users in the database.

Create a new directory for resolvers and a file called Query.js. Then use the following code for our users resolver.

Any resolver can take the arguments of parent, args, context, and info. We’ll leave the details of this for the next article.

All we really need to know is that we are accessing the context object within our server. This allows us to access the action to return all users from the generated Prisma schema.

Let’s update our schema.graphql to have a Query type for retrieving users from this query.

// src/schema.graphql

type Query {
  users: [User!]!
}

type User {
  id: ID!
  name: String!
}

And lastly, import our resolvers and add them to our server variable:

Well, I don’t know about you, but as a front end engineer, I’d really like to see some visual result of the work we’ve done so far.

Let’s add a script to package.json to launch this app.

Now from the root of our project folder, run that script!

> npm start

This will start the server on localhost:4000.

In your browser you’ll now have a GraphQL playground courtesy of Prisma.

If you open up the sidebar by clicking on Docs, you will see that Prisma has populated Queries with our users query.

Graphiql

Similarly, if you open Schema from the sidebar, you will see our typeDefs reflected here.

Graphiql

What do you say we query for users?

In the left pane, add the following...

query {
  users {
    id
    name
  }
}

… and click the play button to execute it!

Graphiql

Ah shoot, it failed… but I guess that makes sense. We created the infrastructure, but we have not yet connected our app to a database!

I would be doing us a disservice were I to end the tutorial here.

Let’s set up a remote database together in Heroku, and use Docker as the glue between Heroku and our local app.

Onwards! 🐳


Heroku & a Postgres Database

So far we have created a GraphQL server, defined types for User and Query, and wrote the resolver to handle querying said User.

When we start our server and view the schema and docs in the playground, we can confirm that our setup has so far been successful.

But this is just the local architecture. We have not yet created and connected to a database.

To create our database, we first need to create a new app on Heroku, and then add a database to the Heroku app as a resource.

Go to Heroku, log in, and go to your dashboard. Then select the New button in the top-right and click Create new app.

Graphiql

Just click Create App with an empty name field and it will generate a name for you (I’ve always liked the heroku name generator). The name really isn't important for a hobby app; I wouldn't worry too much about it.

Next we are going to partition a database for this app.

Select Resources from the top navigation bar and then select Find more add-ons.

Graphiql

In the new tab that opened, search for postgres. Select the search result add-on Heroku Postgres and click the button Install Heroku Postgres...

Graphiql

It will then ask you what app you want to provision it to. No drop down here, but it will auto-fill. Type the name of your app and select the option.

Finalize this by clicking Provision add-on.

Graphiql

Now, back in the resources tab of your app you will see your Heroku Postgres attached as DATABASE.

Let’s grab the credentials we need to connect to this database, shall we?

Click on your database add-on to open it in a new browser tab and select Settings from the top nav bar.

Again, this is the settings for the database, not the settings for the heroku app.

Graphiql

From Settings, click View Credentials...

Keep this tab open, we will come back to it in a moment.

Back in your project, let’s replace the code in the file /prisma/docker-compose.yml to the following:

You must input you credentials for Host, Database, User, and Password, all of which are found in your database credentials open in the other tab.

With your the remote database set up and the credentials saved in your local app, the last piece of the puzzle is to install Docker Desktop to connect the two.

We’re almost there!


Docker

Docker is a tool that allows us to containerize applications.

Our Node server will send a GraphQL request through our Prisma schema layer, which will live on a Docker server at localhost:4466.

Visit Docker Desktop to download and install it.

Assuming you’re using a Mac, drag it into your applications folder and launch it. You will see the little Docker whale in the top status bar of your computer.

You will likely have to log in / create an account with docker, so, yeah, do that too.

Graphiql

With Docker up and running, we can connect to our database now.

In your command line, run docker-compose from the our project’s Prisma directory to start up the Docker app:

> cd prisma
> docker-compose up -d

Follow this up by deploying the Prisma schema to Docker.

> cd prisma
> prisma deploy

This builds a GraphQL schema with Prisma bindings on Docker.

Graphiql

You can view this in our Docker server at http://localhost:4466/_admin, which is now connected to our database on Heroku 🤗.

Yes! Finally!

Let’s launch our Node server and ping our remote cloud database with that users query we wrote earlier.

> npm start

At localhost:4000 in the Prisma playground, again, run the users query:

Graphiql

Beautiful!

The query was successful, returning a grand total of ZERO users! 🎉


Conclusion

Remember, our database is empty, as we have not written and executed any mutations to create a new User.

What we have done is:

  • Set up a local app using Node.js.
  • Implemented Prisma, an auto-generated GraphQL query-builder.
  • Established our GraphQL typedefs and a resolver for queries.
  • Created a Heroku app and partitioned a remote database.
  • Set up Docker Desktop to host our Prisma layer and be the connector between our Heroku database and our local Node app.

For a setup like this, I felt it useful to separate the architecture from the theory and usage of GraphQL.

Next up, we are going to dive deep into GraphQL queries, mutations, and subscriptions.

Then we will cap this project off by building out a production-ready authentication flow.

By that point, you will have everything you need to begin building out an app for anything you can dream, with the confidence that your back-end is solid and scalable.

Here is the Final Project Repo if you ran into any issues on the way.

See you in the next article: Authentication with GraphQL & Prisma

Marshal Murphy 2020