What is Gatsby JS?

Gatsby is a static site generator built on React.

In this tutorial we will be building a Todo App using Gatsby, TDD (test driven development) and Docker.

Gatsby will be serving the frontend of our site but we also need an API for Gatsby to pull data from. For that we are going to use Django as our API. Using Django Graphene the API will serve Graphql end points for Gatsby to consume.

To get started we need to:

  • Install the Gatsby command line tool (CLI) on your host machine
  • Generate a Gatsby starter site
  • Delete the Gatsby Git repo
  • Mock out the frontend file structure

Setting Up the Directory Structure

# 1) Install Gatsby CLI on local computer
npm install -g gatsby-cli

# 2) Generate Gatsby starter site
gatsby new frontend https://github.com/gatsbyjs/gatsby-starter-hello-world

# 3) Remove the Gatsby git resources since we will use our git installation at the root of our project
rm -rf frontend/.git
rm -rf frontend/.gitignore

# 4) Create our frontend Dockerfile script
touch frontend/Dockerfile

# 5) Create a directory for Nginx to serve in production
mkdir nginx

# 6) Create a Dockerfile and nginx.conf files for Nginx
touch nginx/Dockerfile
touch nginx/nginx.conf

# 7) Create a new Docker Compose files for production and development
touch docker-compose.yml
touch docker-compose-dev.yml

This is how our current directory structure should look:

  • todo_gatsby-django-graphene (directory root of the project)
    • frontend (directory)Dockerfile
    • nginx (directory)
      • Dockerfile
      • nginx.conf
    • server (the Django Graphene app we created in Part 1)
    • docker-compose.yml
    • docker-compose-dev.yml
    • .env
    • .gitignore
    • Makefile

Populate the Frontend Files

  1. Our goal is to build a todo application with Gatsby as our frontend which will interface with the Django Graphene server we built in Part 1 of this tutorial. We start by installing the Gatsby CLI on our local computer which is the main entry point for setting Gatsby up on our computer.
  2. We created a new Gatsby project using the Gatsby Hello World starter site which we renamed to frontend.
  3. When Gatsby generated its own git repo which we don’t need since we already have our git repo at the root of our project. We also deleted the .gitignore from the frontend directory.
  4. Create our frontend Dockerfile to configure the Gatsby env.
  5. Create a directory for nginx.
  6. Create a nginx/Dockerfile and nginx/nginx.conf file to configure Nginx server for our production build.
  7. Create two Docker Compose files, one for deploying our Gatsby build to nginx which will serve our site using SSR, (server side rendering), which comes with the Gatsby build.

Next we populate the frontend Dockerfile with instructions on how to build the Gatsby image.

Frontend Dockerfile

# frontend/Dockerfile

# 1)
FROM node:16-alpine

# 2)
EXPOSE 8000

# 3)
WORKDIR /frontend

# 4)
RUN apk update && apk add python3 g++ make && rm -rf /var/cache/apk/*

# 5)
RUN npm install -g gatsby-cli

# 6)
COPY . .

# 7)
RUN npm install

# 8) Building Gatsby generating public directory that can be copied to Nginx service in production
CMD [ "gatsby", "build" ]
  1. Using node:16-alpine image we build our node environment. I’m specifying node version 16 here because Gatsby requires a minimum of node 14 for Gatsby 3.14.4 which is the latest version at the time of writing this blog. I found that Gatsby
  2. Open a port on the frontend container.
  3. Set the working directory with the WORKDIR Docker command. Doing this in one of the first layers is very important otherwise when we run npm install Gatsby will be installed at the root of the container instead of the working directory frontend. When we try running Gatsby commands such as Gatsby build, an error will be thrown saying that Gatsby is not installed. Declaring the WORKDIR early fixes this problem.
  4. Since Node.js is built with node-gyp which is written in Python we need Python installed. You can read more about this Python requirement for GYP here.
  5. Install Gatsby CLI.
  6. Copy the contents of the frontend directory on the host machine into the frontend container that we are building. Note that in step 3 when we set the working directory with WORKDIR, Docker creates the frontend directory for us and cd into the frontend directory so all the subsequent commands are executing in the frontend directory.
  7. Install all the packages defined in the package.json file.
  8. Using the Dockerfile CMD we define the default command to set Gatsby into production mode which will serve the production build from the /www/public.

Next populate the Nginx Dockerfile.

Before we can build our frontend Gatsby image we need to update the docker-compose.yml file populated.

Docker-Compose.yml

# docker-compose.yml

version: '3'
 
services:
    database:
        container_name: postgres
        image: postgres:latest
        environment:
            - POSTGRES_DB=$DATABASE_NAME
            - POSTGRES_USER=$DATABASE_USER
            - POSTGRES_PASSWORD=$DATABASE_PASSWORD
            - POSTGRES_PORT=$DATABASE_PORT
        volumes:
            #- ./server/initial.sql:/docker-entrypoint-initdb.d/initial.sql
            - ./server/db_backups/backup.sql:/docker-entrypoint-initdb.d/backup.sql
            - postgres-data:/var/lib/postgresql/data
 
    server:
        build: ./server/
        container_name: dj02
        working_dir: /var/www/server
        ports:
            - '$SERVER_PORT:$SERVER_PORT'
        volumes:
            - ./server/:/var/www/server
        command: python manage.py runserver 0.0.0.0:$SERVER_PORT
        environment:
            - DJANGO_SETTINGS_MODULE=$DJANGO_SETTINGS_MODULE
            - PGHOST=$DATABASE_HOST
        env_file:
            - .env
        depends_on:
            - database

    
    # 1)
    frontend:
        # 2)
        build:
            context: ./frontend
            dockerfile: Dockerfile
        # 3)
        ports:
            - 8000:8000
        # 4)
        volumes:
          - ./frontend/:/frontend
        # 5)
        container_name: frontend
        # 6)
        depends_on:
          - server

volumes:
    postgres-data:

With the docker-compose.yml file we are defining the backend service infrastructure (database and server) which we built in part I of this tutorial as well as our new frontend Gatsby service.

Lets look at the frontend service in detail:

  1. Name of service.
  2. Tell docker-compose where the Dockerfile is for the frontend service.
  3. Map the outside port 8000 to port 8000 the container’s port.
  4. Map the /frontend files from the frontend container onto our host machine which allows us to edit and save files from our host machine dynamically updating the files in the frontend container and triggers a browser hot-reload.
  5. Give the container the name frontend
  6. Using depends_on tell the frontend to wait for the server to finish launching

Development Docker Compose Override

To run Gatsby in development mode we override the docker-compose file with the docker-compose-dev file.

# docker-compose-dev.yml
version: '3'

services:
  frontend:
    # 1)
    command: gatsby develop --host 0.0.0.0 --port 8000
  1. The command: develop –host 0.0.0.0 –port 8000 sets Gatsby in development mode

Building the Frontend Service

With