My Docker Setup for Gatsby

3 min read ⚡️Last tended 2 years ago
Budding 🌿Planted 2 years ago
Tags: GATSBY, DOCKER, SWE
cover

Recently, I decided to dockerize my website to practice my docker skills. I have documented the steps / issues that led to the solution that I am using. You may skip ahead and refer to the final solution.

The objectives of this exercise:

While researching this topic, I found plenty of tutorials and guides revolving around dockerizing react apps. However, there is very little documentation on how we can achieve the objectives above with a Gatsby site.

It shouldn't be that different, right? Boy, was I wrong.

Getting a Fresh Gatsby Site up and Running on Docker

I managed to get a fresh Gatsby site up and running on docker in a Windows machine based on this tutorial by Daniel Graham. However, HMR is not working.

We have to specify the host port as Gatsby specifically listens to 0.0.0.0 for localhost.

Getting HMR to Work

Turns out we have to add an extra environment variable GATSBY_WEBPACK_PUBLICPATH to specify the webpack config as recommended in this setup guide by Daniel Stout. However, this only solves half the problem, as HMR only worked on Mac.

Getting HMR to Work (Again) On Windows

I took another dive into the Gatsby issues section and turns out someone had a similar issue as me just a month ago.

We just have to specify the webpack config on gatsby-node.js and we can remove environment variables such as GATSBY_WEBPACK_PUBLICPATH: / and CHOKIDAR_USEPOLLING: 'true'

exports.onCreateWebpackConfig = ({ actions }) => {
  actions.setWebpackConfig({
    watchOptions: {
      aggregateTimeout: 200,
      poll: 1000,
    },
  })
}

For anyone who is interested to test this solution, you may refer to this commit.

Getting an Existing Gatsby Site Running on Docker

I thought we could set up an existing Gatsby site running on Docker with minor issues since we have figured everything out on a fresh setup. It turns out I was wrong again and there are still plenty of surprises for this exercise.

Getting Sharp to Work Across Platforms

My website uses sharp for image processing and the current version, v0.29.0, isn't as platform-agnostic as I thought.

While I was building the Docker image (Alpine) from a Windows host machine, I received the following error.

Error in "/app/node_modules/gatsby-transformer-sharp/gatsby-node.js":

Something went wrong installing the "sharp" module


Error relocating /usr/lib/libvips-cpp.so.42:

_ZSt28__throw_bad_array_new_lengthv: symbol not found


Possible solutions:

- Install with the --verbose flag and look for errors: "npm install

--ignore-scripts=false --verbose sharp"

- Install for the current runtime: "npm install --platform=linux --arch=x64

sharp"

- Consult the installation documentation:

https://sharp.pixelplumbing.com/install

The issue persists even after adding the platform and arch flags in my Dockerfile. Following the same solution from this issue, I decided to change from an Alpine Node image to a Debian "Bullseye" image.

I also added a platform config available only on docker compose v2.4, after checking the Docker Compose documentation

version: "2.4"
services:
  web:
    platform: linux/amd64
    build:
      context: .
      dockerfile: Dockerfile.dev

Resolving Gatsby EACCES Issue

Another issue arises following this setup. Different EACCES permissions errors such as mkdir, unlink, starts to appear when I try to run from the node user with the least privileges.

I managed to get my website running on Docker on both Windows and Mac machine after making this last change. (although it is not recommended.)

# RUN chown -R node /app/node_modules
# USER node
RUN mkdir node_modules/.cache && chmod -R 777 node_modules/.cache

Final Solution

  1. Add Webpack Config in gatsby-node.js
exports.onCreateWebpackConfig = ({ actions }) => {
  actions.setWebpackConfig({
    watchOptions: {
      aggregateTimeout: 200,
      poll: 1000,
    },
  })
}
  1. Add Dockerfile
FROM node:16-bullseye
EXPOSE 8000

RUN npm config set unsafe-perm true
RUN npm install -g gatsby-cli
WORKDIR /app
COPY ./package.json /app
RUN npm cache clean --force
RUN npm install --arch=x64 --platform=linux --legacy-peer-deps
COPY . /app

RUN mkdir node_modules/.cache && chmod -R 777 node_modules/.cache
CMD ["gatsby", "develop", "-H", "0.0.0.0" ]
  1. Add docker-compose.yml
version: "2.4"
services:
  web:
    platform: linux/amd64
    build:
      context: .
      dockerfile: Dockerfile.dev
    ports:
      - "8000:8000"
    volumes:
      - /app/node_modules
      - .:/app
    environment:
      - NODE_ENV=development

Note that HMR is not working for changes in "data" files such as Markdown. I will continue to look for solution to fix this part. Click here for more info.

Conclusion

I learnt a lot about Docker and the inner workings of Gatsby from this exercise. I hope these notes can shed some light for other wanderers who are trying to explore the same topic of running Gatsby on Docker. My solution for this exercise is not perfect and I would love to hear any feedback to optimize my solution. I will continue to update as my knowledge on Gatsby/Docker deepens.

References

Getting Gatsby to run on Docker

Getting HMR to work on Docker and Windows

Fixing EACCES: Permission denied issue

Getting Sharp to work on Docker with cross platform setup

Docker and Node.js Best Practices

It makes my day when I see it.
😊
Postman Tips and TricksTech Communities and Resources
Walter Teng © 2023