DEV Community

loading...
Cover image for Tie down scheme for an Apollo GraphQL server in a Node Docker container

Tie down scheme for an Apollo GraphQL server in a Node Docker container

preciouschicken profile image Precious Chicken Originally published at preciouschicken.com on ・4 min read

Photo by Johan Taljaard on Unsplash

Introduction

GraphQL is a query language for APIs, while Apollo Server is a popular server used for providing GraphQL APIs. This post is a concise handrail as to how to put an Apollo GraphQL server in a Node.js Docker container - a "standardized unit of software that allows developers to isolate their app from its environment." This tutorial uses the Linux command line and assumes you have already installed Docker and Node.

All code can be found in the PreciousChicken/apollo-server-docker-container repository.

Initialisation

At the terminal create a directory, and install the relevant packages:

mkdir apollo-docker
cd apollo-docker
npm init -y
npm install apollo-server graphql
Enter fullscreen mode Exit fullscreen mode

Create the GraphQL server, schema et al

Not good practice to put everything into the same file, but as this is a demo only create a file named index.js and copy / paste the below:

const { ApolloServer, gql } = require('apollo-server');

const data = {
  "beasts": [
    {
        "id": "md",
        "legs": 6,
        "binomial": "Musca domestica",
        "commonName": "housefly",
    },
    {
        "id": "nr",
        "legs": 8,
        "binomial": "Neriene radiata",
        "commonName": "filmy dome spider",
    },
    {
        "id": "cc",
        "legs": 2,
        "binomial": "Corvus corone",
        "commonName": "carrion crow",
    },
    {
        "id": "fc",
        "legs": 4,
        "binomial": "Felis catus",
        "commonName": "cat",
    }
  ]
};

const typeDefs = gql`
    type Beast {
        id: ID
        legs: Int
        binomial: String
        commonName: String
    }

    type Query {
        beasts: [Beast]
    }
`;

const resolvers = {
    Query: {
        // Returns array of all beasts.
        beasts: () => data.beasts
    }
};

const server = new ApolloServer({ typeDefs, resolvers });

// The `listen` method launches a web server.
server.listen(4000);
Enter fullscreen mode Exit fullscreen mode

This creates a very basic Apollo server with a minimal GraphQL schema. Running node index.js now would spin this up and allow interaction with the server - but the aim is to run within a Docker container, not directly on our machine: which is the next step.

Dockerfile

A dockerfile is a set of instructions that builds our image. Therefore create a file named Dockerfile and copy / paste the following:

# Uses the node base image with the latest LTS version
FROM node:14.16.0
# Informs Docker that the container listens on the 
# specified network ports at runtime
EXPOSE 4000
# Copies index.js and the two package files from the local 
# directory to a new app directory on the container
COPY index.js package.json package-lock.json  app/
# Changes working directory to the new directory just created
WORKDIR /app
# Installs npm dependencies on container
RUN npm ci
# Command container will actually run when called
CMD ["node", "index.js"]
Enter fullscreen mode Exit fullscreen mode

A keen reading might spot that npm ci is used in preference to npm install, this command is meant to be used in automated environments as explained by Demystifying npm install, npm ci & package-lock.json.

Build the image

Next we tell Docker to use the newly created Dockerfile to create the image:

docker build -t preciouschicken-apollo .
Enter fullscreen mode Exit fullscreen mode

If you encounter a permissions error, then try again but prefix your Docker commands with sudo. Assuming you encounter no errors, Docker should pull down the parent image and run through the Dockerfile.

The -t option names the image created, in this case as preciouschicken-apollo. To confirm success all images created can be listed with:

docker image ls
Enter fullscreen mode Exit fullscreen mode

Run the container

Now the image has been created, next run an instance of it:

docker run -p 4000:4000 --name apollo-server -d preciouschicken-apollo
Enter fullscreen mode Exit fullscreen mode

The options specified here are:

  • -p 4000:4000 - Connects the port on the local machine to the port on the container.
  • --name apollo-server - Names the actual running instance of the image, useful for identification.
  • -d - Runs the instance detached: that is hands your terminal back so you can type other commands.

To check the container is running it can be listed with:

docker ps
Enter fullscreen mode Exit fullscreen mode

Interact with the GraphQL server

If all went well Apollo server should be running in the container and listening on port 4000. Pointing your browser at localhost:4000 should display the built-in playground where you can test your API.

Below the statement #Write your query or mutation here enter the following query:

{
  beasts {
    commonName
    legs
  }
}
Enter fullscreen mode Exit fullscreen mode

This should produce a response similar to the below:

GraphQL playground

Stop the container

When we are done testing we can halt the container with:

docker stop apollo-server
Enter fullscreen mode Exit fullscreen mode

Conclusion

Comments, feedback? Post below.

Oh and if you are wondering, what is a tie down scheme anyway? It's a schematic for how to fasten a load within an aircraft or ISO container. Think of it like a very weak joke.

Related work

Node.js Docker Best Practices provides tips on production ready Docker containers.

Some other resources I have produced on GraphQL are:

Version Control

This was written on a Linux machine running Manjaro 21.0 Omara, using Docker Server 20.10.5, npm 7.7.5 and node 14.16.0.

Discussion (0)

pic
Editor guide