The Ops Community ⚙️

Cover image for How to Containerize Your Docusaurus (And Why You Should)
Natalie Lunbeck
Natalie Lunbeck

Posted on

How to Containerize Your Docusaurus (And Why You Should)

This post was originally published on the Shipyard Blog


Containerizing your project’s documentation might be one of the easiest ways you can remove friction from iterating. Your docs are also probably one of the easiest things you can containerize. Here’s how you can get your docs up and running with Docker Compose in just a few minutes.

Why should I containerize my docs?

Simply put, containerizing your docs lets you hit the ground running when writing documentation.

Here are a few QoL improvements that come with doing this:

  • No need to install/update/manage dependencies
  • Work with the same development environment across machines
  • Start developing with just a single command

In short, it’s just easier. You don’t have to think about building and running the dev server, you can just open your terminal and your IDE, then start writing. When writing docs, you’re likely iterating often and adding small chunks at a time, so it makes sense to optimize your local dev environment to spin up as efficiently as possible.

Containerizing your Docusaurus build

At Shipyard, we’re big fans of Docusaurus. We’ve been using it to write our public documentation for three years. We’ve also been using Docker Compose for local docs development just as long. A lesson we've learned is that sometimes the best tools are the ones we're already using. We were using Docker Compose for everything else, why not extend it to our docs?

Writing the Dockerfile

Since Docusaurus is Node-based, the Dockerfile is pretty standard. You might need to swap in your docs’ custom run commands.

FROM node:16-alpine

WORKDIR /app

COPY package*.json ./

RUN npm install

COPY . .

CMD ["npm", "start"]
Enter fullscreen mode Exit fullscreen mode

This Dockerfile Explained

If you’re newer to Docker, here’s a line-by-line rundown of what this Dockerfile is doing:

  1. Start with a Node base image
  2. Create and set the working directory within the container
  3. Copy the Node dependencies to the working directory
  4. Install dependencies within container
  5. Copy the rest of the repo’s contents to the working directory
  6. Run the Node project’s start command

Setting the host

In order to make the application accessible from outside the container (e.g. from your web browser), you’ll want to set the --host option to 0.0.0.0.

This can be done from your package.json:

 "scripts": {
    "docusaurus": "docusaurus",
    "start": "docusaurus start --host 0.0.0.0",
Enter fullscreen mode Exit fullscreen mode

Or in your Dockerfile as an argument to your project’s start command:

CMD ["npm", "start", “--host”, “0.0.0.0”]
Enter fullscreen mode Exit fullscreen mode

Writing the Docker Compose file

Now that we have the Dockerfile, we can write a single-service Compose file to leverage it. Here, we’ll specify any Docker config options (so we don’t need to remember them for complex docker build and docker run commands).

version: '3'

services:
  docusaurus:
    build:
      context: .
    ports:
      - '3000:3000'
    volumes:
      - './docs:/app/docs'
      - './src:/app/src'
      - './static:/app/static'
      - './docusaurus.config.js:/app/docusaurus.config.js'
      - './sidebars.js:/app/sidebars.js'
Enter fullscreen mode Exit fullscreen mode

Because we’re optimizing this Compose file for local development, we’ll want to define bind mounts from any files and directories that we plan to edit. This way, any local changes will be reflected in the Docker container.

In this example, I have a few bind mounts defined under the volumes option. The syntax for this involves specifying the local path (relative to the build context), followed by a colon, then followed by the corresponding location in the container.

Bonus: Writing the .dockerignore

Docker images tend to run pretty large, so writing a .dockerignore can help slim them down by weeding out any files irrelevant to your Docker build.

To exclude any Markdown files in the root directory (e.g. your README.md and LICENSE.md, but not your actual Markdown doc pages), you can use this glob pattern in the .dockerignore:

/*.md
Enter fullscreen mode Exit fullscreen mode

Your Docker build also doesn’t need to include the Dockerfile or the Compose file. These glob patterns will match most naming conventions for those:

*compose*
*Dockerfile*
Enter fullscreen mode Exit fullscreen mode

You can also exclude node_modules (likely the biggest bloat culprit):

node_modules
Enter fullscreen mode Exit fullscreen mode

Docs that work right out of the box

Now that you’ve containerized your Docusaurus docs, you can spin them up locally with docker compose up and start editing.

Thanks for reading!

If you enjoyed this Docker Compose tutorial, check out this post I made a few months ago on how to write a Compose file for a Wordle clone.

Top comments (0)