Skip to main content

Running Docusaurus using Docker

Streamline Docusaurus blog development! Build a single Docker image for production and use VS Code Dev Containers for consistent, fast, and isolated editing.

· 10 min read
View raw
Christophe
Markdown, WSL and Docker lover ~ Insatiable curious.
Cet article existe aussi en français — lire la version française.

This article is over a year old. The information may be outdated.

Running Docusaurus using Docker

⚡
TL;DR

This guide details how to streamline Docusaurus blog development using Docker. It outlines creating a single Docker image for production builds and leveraging VS Code Dev Containers for a consistent, fast, and isolated development environment. The setup enhances the workflow with integrated tools like LanguageTool and Code Spell Checker for improved content quality.

Streamline your Docusaurus workflow with a clean, reproducible setup. In this updated guide, you'll learn how to maintain a Docusaurus blog using a single Docker image, VSCode DevContainers, and a workflow that makes both production builds and day-to-day writing fast and reliable.

Eighteen months ago, I published Encapsulate an entire Docusaurus site in a Docker image but, since then, I've refined the approach, especially around separating production and development environments cleanly (see One Docker Image for Production and Devcontainers - The Clean Way).

With this setup:

  • You run make build once to create a base Docker image.
  • You launch your editing environment with make devcontainer.
  • VSCode automatically builds and opens an isolated container with everything configured.

If Docusaurus itself is new to you, start with Running Docusaurus with Docker; and once the site is built, GitHub - Use Actions to deploy this blog takes care of publishing it.

Let’s walk through the complete workflow.

Here's where we're headed: make build once, make up, and the blog is already running.

https://localhost/blog

The blog is running

A few commands below and you'll be there too.

What we'll learn here:

  • Retrieve a Docusaurus blog,
  • Create a Docker image to run the blog
  • Open the project in VSCode using DevContainers
  • Enhance the environment with extensions like LanguageTool, Code Spell Checker or Markdown lint.

Retrieve a Docusaurus blog​

If you already have a Docusaurus blog, just skip this chapter. For demonstration purposes, we'll use my friend's blog, Docux who is publishing very useful Docusaurus components and plugins.

Grab a copy of his blog by running commands below:

>user@machine: ~/yourproject

Create the base Docker image​

If you're new to Docusaurus, you might wonder: How can I just run the blog locally?. The fast answer is: by running a self-contained Docker image and we'll learn that in this chapter.

Please first open VSCode by running code .:

>user@machine: ~/yourproject

You should now see the project structure in your editor.

The blog opened in VSCode

Create required files​

Your values for this page
default
Applies to the commands on this pageSaved on this device only

In the root of the project, create the following files:

📦 Project setup: /tmp/docux-blog
Help

Need help here? Click the "Help" button above for setup instructions.

Build and run the production image​

Once the files are in place, in a console, please run make and you'll get a screen like this:

Getting the list of targets

If make isn't yet installed on your machine, you'll get an error so please make sure to first install make:

>user@machine: ~/yourproject

Now we have to run two commands, the first one will create a Docker image for production i.e. where everything is included in the image.

>user@machine: ~/yourproject

You'll get a screen like this one and you'll have to wait something like 80 seconds until the image is built.

Running make build for PROD

This done, please run the second command to create a running instance of the image i.e. a container:

>user@machine: ~/yourproject

This will be very fast and you'll see on the console a message telling Open the PROD blog (https://localhost).

And you know what? It's already done: just surf to https://localhost and be surprised — the blog is running, the same result already teased at the top of this article.

What have we done?

By running TARGET=production make build we've created a standalone version of the blog running on nginx. We've encapsulated all articles from the blog (as Markdown files) and we've fired all the required commands to generate the static version of the blog. We've parked these files in a temporary location.

We've created the final image by using nginx and by copying static files created earlier in the image.

By running TARGET=production make up we've created a running instance (called container) of that image and we've asked our operating system to access the container on port 443 (the one of the https protocol). That's why, if we access https://localhost we get the website.

Using DevContainers for Development​

Building the production image is nice and helpful if you want to publish it on Docker Hub, but we also need a smooth editing workflow. Using VS Code DevContainers, we get a fully isolated environment tailored for Docusaurus.

First, run make build (notice, we don't specify TARGET=production here). It'll be extremely fast since everything was already created before.

Next, run make devcontainer to open VSCode and nothing happens right now: it's normal, we need to create additional files.

Run both in one command

Under Linux, you can run make build && make devcontainer to run both in just one command.

Create the .devcontainer folder​

We'll need to create a new .devcontainer folder with a few files:

📦 Project setup: /tmp/docux-blog
Help

Need help here? Click the "Help" button above for setup instructions.

Make sure to use your own UID/GID

Please edit the .devcontainer/.env file and make sure these values are the ones you're using: please run id -u in your console and check if you get 1000. If not, please report the obtained figure (f.i. 1002) as OS_USERID and do the same with the command id -g, here, it's for the OS_GROUPID variable.

Since we have two bash scripts, we need to make them executable. Please run this command in a terminal:

>user@machine: ~/yourproject

Now we have to open the devcontainer so please run:

>user@machine: ~/yourproject

Once in VSCode, please press F1 to open the Command Palette and run Dev Containers: Rebuild Without Cache and Reopen in Container.

Don't have it?

If you don't have this command, please make sure to install the VSCode Dev Container from Microsoft.

Devcontainer

Please click and thus run the Dev Containers: Rebuild and Reopen in Container action. If you look at the terminal (from inside VSCode), you'll get a lot of messages like the ones below:

Building the devcontainer

At some point in time, you'll see this:

Yarn run

It means that Docusaurus is ready to serve your content.

Please surf to https://localhost:3000 and tadaaa.

https://localhost:3000

The site is running

Let's play. Open the blog folder and create a new file called index.md:

Creating a new blog post

Save it and, oh?, your browser will immediately reflect the change (hot reload is indeed enabled):

https://localhost/blog/index/

The new blog post is already running

Running the terminal from the devcontainer​

Something really cool too is the use of the Terminal still inside VSCode.

In case of need, press CTRL+ù to open the Terminal and see the + button top right in that window. Click on the + to create a new one:

Using the terminal in the devcontainer

Did you see? You get a welcome screen with a few actions you can run. For instance, to upgrade Docusaurus to the latest version, you just need to run upgrade and that's all.

Could we make easier than this?

From where comes this welcome screen?

See the .devcontainer/bash_helpers.sh file you've previously copied/pasted.

You'll in the Bash script the design of the welcome screen and also a few aliases like version to get the version of the installed Docusaurus instance.

What are the advantages of such approach?​

There are so numerous... Let's start with this one: on my host, I've just Docker and that's all. I don't need to install Node as needed by Docusaurus neither any Linux dependencies.

I can also build my blog as a standalone image. Just look at my cavo789/blog Docker image on https://hub.docker.com/r/cavo789/blog. If you want to run it on your own machine, you just need to run docker pull cavo789/blog && docker run -d -p 443:443 --name blog cavo789/blog then surf on https://localhost and that's all.

Using a Devcontainer like illustrated in this article, you can also fine-tune your environment i.e. tell which extension in VSCode has to be installed and how that extension has to be configured. You can also define the look&feel of the editor (the font, size, color, template, ...).

Since everything is isolated, you can drop the container and recreate it without pain.

Working with a team? Devcontainer is then the way-to-go since everyone will have the exact same environment.

Using LanguageTool in VSCode​

Let's see one of the many advantages: instead of just using VSCode to write our posts, let's use LanguageTool which provides basic grammar and spellchecking for your posts.

And you know what? You already have it. See your .devcontainer/compose.yaml file. You'll see a service called languagetool based on a Docker image called erikvl87/languagetool. And now, see your .devcontainer/devcontainer.json file. Search for languageToolLinter and you'll see a local URL (based on an IP); this is the one exposed by the service. And look further for the davidlday.languagetool-linter extension, this is the one that'll make the magic happen.

Here's an example of how LanguageTool works:

LanguageTool in action

For sure, the correct sentence should be This example illustrates LanguageTool in action.

Code Spell Checker​

Here is another example, a mistake a French-speaking person can make inadvertently:

The word example is misspelled

Here, the extension used is Code Spell Checker from streetsidesoftware.

Markdown lint​

And perhaps, while you write your Markdown content, VSCode will show you errors displayed in orange like MD047/single-training-newline to tell you that you forgot to add an empty line at the very bottom of the file.

These warnings come from Markdownlint which is another extension already installed in the devcontainer.


🦋 Join the conversation on BlueskyRequires a free Bluesky account to like, repost or comment. This block talks to Bluesky's public API directly from your browser (no cookies, no sign-in) — that means your IP address reaches Bluesky's servers just by this section loading.

Loading comments…

Was this article helpful?
Did you try the steps in this article?