Gatsby, Tailwind & Docker

Gatsby and Tailwind are a formidable combination for putting together a robust and attractive site. Throw Docker into the mix and you also have robust and reliable deployments. Here’s how to set that up for a minimal site.

🚀 TL;DR The code for this project can be found here.

Install Gatsby CLI & Other Packages

There are various ways to do this. See this for the options.

You’ll also need to install the Gatsby package, along with Tailwind and a few other dependencies.

npm install gatsby tailwindcss postcss autoprefixer

Create Gatsby Project

Use gatsby to create a new project folder.

gatsby new gatsby-tailwind

💡 Depending on how you installed the Gatsby CLI you might need to precede that command with npx.

And move into that folder.

cd gatsby-tailwind

This is what the initial project structure should look like:

tree -I node_modules
.
├── gatsby-browser.js
├── gatsby-config.js
├── gatsby-node.js
├── gatsby-ssr.js
├── LICENSE
├── package.json
├── package-lock.json
├── README.md
└── src
    ├── components
    │   ├── header.js
    │   ├── index.module.css
    │   ├── layout.css
    │   ├── layout.js
    │   └── seo.js
    ├── images
    │   ├── example.png
    │   └── gatsby-icon.png
    ├── pages
    │   ├── 404.js
    │   ├── index.js
    │   ├── page-2.js
    │   ├── using-ssr.js
    │   └── using-typescript.tsx
    └── templates
        └── using-dsg.js

6 directories, 21 files

Initialise & Configure Tailwind

Now initialise Tailwind.

npx tailwindcss init -p

That will add two new files: tailwind.config.js and postcss.config.js.

To enable JIT mode we need to add the paths to the site template files to tailwind.config.js.

/** @type {import('tailwindcss').Config} */
module.exports = {
  content: [
          "./src/**/*.{js,jsx,ts,tsx},"
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

Next we create a CSS file for the project in src/styles/global.css with the following content.

@tailwind base;
@tailwind components;
@tailwind utilities;

And import that file in gatsby-browser.js.

import "./src/styles/global.css"

Test on Host

With all of that setup in place we can launch the project directly on the host. Start a development server.

gatsby develop

💡 Use npx if you need to!

Open http://127.0.0.1:8000/ in your browser to see the minimal Tailwind-enabled site.

Actually Use Tailwind

It might not have escaped your attention that at this point we have not actually used Tailwind in the project. Let’s fix that. Edit src/pages/index.js.

import React from "react"

export default function Home() {
  return (
    <div className="min-h-screen bg-gray-100 flex flex-col justify-center items-center">
      <h1 className="text-5xl text-blue-600 font-bold">
        Gatsby & Tailwind!
      </h1>
      <p className="text-lg text-gray-700 mt-4">
        A sample project using Gatsby and Tailwind CSS.
      </p>
    </div>
  )
}

Restart Gatsby and head over to http://127.0.0.1:8000/. Our test site has become a lot more minimal. But now it uses a bunch of Tailwind classes (take a careful look at the definition of the React component above, paying attention to the className attributes). What’s happened behind the scenes is the Tailwind JIT compiler has generated the required (and minimal) CSS for the project. Take a look at http://127.0.0.1:8000/commons.css to see for yourself.

Wrap it in Docker!

Let’s start with some housekeeping. Create a .dockerignore file. We’ll use this to reduce the volume of data being copied into the Docker build context.

node_modules
.cache
public

Now create Dockerfile.

FROM node:18-slim

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

RUN npm install -g gatsby-cli
RUN gatsby build

CMD ["gatsby", "serve", "-H", "0.0.0.0"]

Build the Docker image.

docker build -t gatsby-tailwind .

And finally create a running container.

docker run --rm -p 8000:9000 gatsby-tailwind

Head back to http://127.0.0.1:8000/ to see the site now served from the Docker container. If you try to use http://127.0.0.1:8000/commons.css to see the CSS though you’ll be disappointed. Take a look at the contents of the <head> in the page at http://127.0.0.1:8000/ (you’ll need to use Developer Tools in your browser to do this) and you’ll find that the CSS path is now a bit of a random muddle.

<head>
  <style data-href="/styles.7ad68bcdaf01d23bf817.css" data-identity="gatsby-global-css">
</head>

If you go to http://127.0.0.1:8000/styles.7ad68bcdaf01d23bf817.css though you’ll see the CSS rendered by Tailwind JIT.

The difference comes from the fact that we are running a production server on the Docker container (see the Dockerfile where we launched Gatsby using gatsby serve). You can restore the development server by changing the last line of the Dockerfile.

CMD ["gatsby", "develop", "-H", "0.0.0.0"]

Rebuild the Docker image and then run. Make sure to update the port mapping because the development server runs on port 8000.

docker run --rm -p 8000:8000 gatsby-tailwind

You should now be able to open http://127.0.0.1:8000/commons.css again (but this time from the Docker container).

🐳 See this for a similar approach using Next.js.