Dockerize Your GatsbyJS Workflow with GatsD

19 October, 2018 — Read time: 7 Min. — Category: Full-Stack

I have previously written about why you want to develop your websites with GatsbyJS. Today, I'm going to let you know why you want to do your local development in a containerized environment such as Docker, and then give you an example using Gatsby and GatsD. (Note: I created the GatsD project.)

Developing in a Containerized Environment

If you don't already use programs like Docker and Kubernetes, I'm here to tell you that the future has arrived. The container wars are in the rear-view mirror with Docker as the clear victor. Containers are now mature enough be a standard part of every developer's toolkit.

If you haven't used Docker yet, it may seem intimidating. Docker can do incredibly complicated things, but it can also be very simple. If you, like most of us, use your machine for more than developing a single project — using Docker may turn out to be easier than what you're doing right now.

Dependency Isolation

When using global packages on your local system to run your development workflow, any link in the precarious dependency chain can stop you in your tracks.

System Updates

Often the issue starts with a system update. Some unseen global dependency (python, vips, ffts, etc.) is upgraded, and suddenly your project won't compile. In the case of NodeJS-based projects like Gatsby, this usually happens when yarn install or another command fails.

When projects have a global dependency that stays on an old version, you're stuck with it — no matter the opportunity cost to the rest of your system. The system may be used for programming, music, video and general browsing, but the configuration will be constrained by project global dependencies. Unfortunately, these dependencies aren't always obvious.

Conflicting Project Global Dependencies

Projects may require different versions of global packages than you use. Perhaps it's the Node version, and you haven't (or don't want to) set up NVM to maintain several local versions. Or you want to use your NVIDIA GPU for machine learning, but also want to globally use something newer than CUDA 9.0.

Complicating things further, different projects may have different global requirements. Conflicts can be difficult to manage — a project that works today may be unexpectedly broken tomorrow by an unfortunate upgrade.

Dependencies You Don't Want

Sometimes, you just don't want to taint your system by installing a dependency. Maybe it's only needed for one project, maybe you consider it bloated, or it makes system changes you don't like. If you share those concerns, or harbor some of your own, it your system - just don't install it.

Consistent Environment

Managing even one project becomes more complicated as soon as it's developed on more than one machine. There may be multiple contributors, you may have multiple environments in your pipeline or you may be using more than one computer. Now all the machines are constrained by the global dependencies of this one project.

How to Use GatsD with GatsbyJS

This section will cover creating a new project and starting development with Gatsby and GatsD. This workflow is intended for use on Linux and OSX machines. I'll treat Windows separately in an upcoming post in order to discuss the peculiarities of working with Windows Subsystem for Linux (WSL) and Docker for Windows. Yet another upcoming post will discuss how you can publish your site with Github and Netlify.

Prerequisites

This install method was designed to work with minimal global dependencies on your machine. So, it doesn't require anything not already required to run Docker (no need for git, node, python, etc). If you can run the prerequisites below, you're good to go.

Docker

This tutorial assumes you have already installed Docker and at least run docker run hello-world to confirm your install is working. There's a lot of good documentation available out there for getting Docker started.

curl

I use curl for http(s) requests. It's small, simple, lightweight, open-source, awesome. I chose cURL over the alternatives because it's installed as a prerequisite in the Docker installation instructions. You should be fine if you made it through your Docker hello-world.

Text Editor

Have your preferred text editor ready. I use VSCode for most (non-JupyterLab) development. It's pretty handy. Of course, anything will do here - including textpad variants and in-terminal editors (vi, vim, xed, nano, pico, ect.).

Here's a meta look at my current editor setup.

A look at my VSCode setup

Initialize Project

Alright, time to get to work.

1. Create directory for new site and enter the new directory.

mkdir mysite
cd mysite

Keep in mind that this directory name will be your project name. Your docker image will be tagged with it and your docker container will be named with it. Pick something that doesn't run afoul of Docker naming restrictions.

2. Download gatsd sub-directory into new site.

# For latest release
RELEASE=$(curl -s https://api.github.com/repos/imburbank/gatsd/releases/latest | <span class="token tag">sed</span> -n 's/"tag_name": "v\(.*\)",/\1/p' | tr -d ' ')
curl -L https://www.github.com/imburbank/gatsd/archive/v${RELEASE}.tar.gz | tar xzv gatsd-${RELEASE}/gatsd/ --strip=1

Releases can also be selected by version, such as RELEASE=0.3.3

Your directory structure should look pretty simple at this point.

.
└── gatsd

3. Initialize Gatsby project with GatsD.

./gatsd/new https://github.com/gatsbyjs/gatsby-starter-default

# To use the gatsby-start-default template, you can just run:
./gatsd/new

GatsD will build the Docker container and download the selected Gatsby starter template from Github. By default, the container will be tagged with the mysite name. If no site is passed as an argument to ./gatsd/new, then the https://github.com/gatsbyjs/gatsby-starter-default template will be downloaded.

Your project tree will now look similar to this, allowing some variation between templates.

.
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── gatsd
│   ├── .bashrc
│   ├── build
│   ├── _default.conf
│   ├── develop
│   ├── docker-build
│   ├── Dockerfile
│   ├── _entry.sh
│   ├── _gatsd.sh
│   ├── _gatsd-shim
│   ├── new
│   ├── run
│   ├── serve
│   └── stage
├── node_modules
│   └── ...(excluded)
├── LICENSE
├── package.json
├── .prettierrc
├── README.md
├── src
│   ├── components
│   │   ├── header.js
│   │   ├── layout.css
│   │   └── layout.js
│   ├── images
│   │   └── gatsby-icon.png
│   └── pages
│       ├── 404.js
│       ├── index.js
│       └── page-2.js
└── yarn.lock

The project directory will be accessible from inside the container and any changes made to the project inside the container, or on the local host, will be visible to both.

Start Developing

Start the Gatsby dev server inside your Docker environment.

./gatsd/develop

After successful compilation, Gatsby will tell you where to navigate in you browser to view the site. Go there.

You should see your template!

View of default Gatsby template in browser

Lets make a quick change to show how it works. Open pages, make the following edit and save the file.

-	<h1>Hi people</h1>
+	<h1>Hi World!</h1>

You should immediately see the changes in your browser.

View of changed Gatsby template in browser

And just like that, you're developing with Gatsby in a Docker container!

Further Development

If you're new to Gatsby, I highly recommend going through their tutorials to familiarize yourself.

More detailed GatsD instructions can be found at the github repo, or by using the --help flag.

# From outside a running container
./gatsd/run gatsd --help

# From inside a running container
gatsd --help

Happy coding.

This tutorial is the first in a series on development with GatsbyJS and GatsD. I will update with links as they're published.

Like this post? Read other posts from the category Full-Stack