Skip to main content

Deploying Docusaurus with Docker

What is Docusaurus?

Docusaurus is an open-source static site generator built by Facebook. It is designed for documentation websites, blogs, and knowledge bases. Docusaurus uses Markdown for content creation and provides a React-based frontend.

Key Components of Docusaurus

Docusaurus consists of several components that make it easy to build and maintain a documentation site.

1. docs/ (Documentation Pages)

  • Stores Markdown files for your documentation.
  • Each .md file in this directory becomes a documentation page.
  • The navigation order is controlled by sidebars.js.

2. blog/ (Blog Posts)

  • Contains Markdown blog posts (YYYY-MM-DD-title.md).
  • Docusaurus automatically generates a blog listing page.

3. static/ (Static Assets)

  • Stores images, CSS, JavaScript, and other static files.
  • These files are directly accessible via the / URL path.

4. src/ (Custom React Components)

  • Used for adding custom React components to enhance documentation.
  • Contains custom pages (src/pages/) and UI enhancements.

5. docusaurus.config.js (Configuration File)

  • The main configuration file for site settings, themes, and plugins.
  • Defines the site title, URL, navbar, footer, and more.

6. sidebars.js (Sidebar Navigation)

  • Controls the navigation structure of the documentation.
  • Organizes docs into categories and sections.

Docusaurus Build Process

To create a new Docusaurus project:

npx create-docusaurus@latest my-website classic
cd my-website
npm install

The process of containerizing and deploying your Docusaurus project to Google Compute Engine (GCE) involves the following steps:

Containerize the Docusaurus Project

  • Create a Dockerfile.
  • Build a Docker image.
  • Test the container locally.

Push the Docker Image to Google Container Registry (GCR)

  • Tag and push the image to Google Container Registry.
  • Deploy the Container on Google Compute Engine (GCE)

Install Docker on the VM.

  • Pull and run the container.
  • Expose it via Nginx or a firewall rule.

Detailed Steps

Containerize the Docusaurus Project

Ensure your Docusaurus project is built

npm install
npm run build

Create a Dockerfile in your project root.

What is a Dockerfile?

A Dockerfile is a text file that contains a set of instructions to build a Docker image. It automates the process of creating a container by specifying:

  • The base image (e.g., node:18-alpine for a Node.js-based app like Docusaurus)
  • Dependencies to install
  • Commands to run
  • Ports to expose
  • The application’s startup command

How to Create a Dockerfile To create a Dockerfile for your Docusaurus project, follow these steps:

  • Step 1: Navigate to Your Docusaurus Project Root

    Open a terminal and change into your project directory:

    cd /path/to/your/docusaurus-project
  • Step 2: Create the Dockerfile Run the following command:

    touch Dockerfile

    This creates an empty file named Dockerfile in your project directory.

  • Step 3: Open the Dockerfile and Add the Following Content Open the file in a text editor (nano, vim, or VS Code):

    nano Dockerfile

    Then, add the following lines:

    # Use a lightweight Node.js image as the base
    FROM node:18-alpine

    # Set the working directory
    WORKDIR /app

    # Copy package.json and install dependencies
    COPY package.json package-lock.json ./
    RUN npm install --omit=dev

    # Copy the rest of the Docusaurus files
    COPY . .

    # Build the Docusaurus static site
    RUN npm run build

    # Expose port 3000
    EXPOSE 3000

    # Start the Docusaurus server
    CMD ["npm", "run", "serve"]

Understanding the Dockerfile

LineExplanation
FROM node:18-alpineUses a lightweight Node.js image as the base.
WORKDIR /appSets /app as the working directory inside the container.
COPY package.json package-lock.json ./ Copies package files to install dependencies.
RUN npm install --omit=dev Installs dependencies without modifying package-lock.json.
COPY . .Copies all Docusaurus project files into the container.
RUN npm run build Builds the static Docusaurus site.
EXPOSE 3000Tells Docker that the app will run on port 3000.
CMD ["npm", "run", "serve"] Starts the Docusaurus web server inside the container.
  • Build the Docker Image
    docker build -t docusaurus-site .

  • Test Locally
    docker run -p 3000:3000 docusaurus-site

1. Difference Between EXPOSE and -p 3000:3000

CommandPurpose
EXPOSE 3000 (in Dockerfile)Documentation-only. Tells Docker that the container listens on port 3000 but does not automatically map it to the host machine.
docker run -p 3000:3000Maps port 3000 in the container to port 3000 on the host machine, making it accessible from the browser.

2. Why Do We Need to Specify the Port Twice?

The syntax:

docker run -p 3000:3000 docusaurus-site

Maps the container's internal port (3000) to an external port (3000) on the host.

  • First 3000 (Host Port) → The port you use to access the app (e.g., http://localhost:3000).
  • Second 3000 (Container Port) → The port exposed inside the container (where the app is running).

You can also map it to a different host port, for example:

docker run -p 8080:3000 docusaurus-site

Now, the app inside the container still runs on port 3000, but you can access it at http://localhost:8080

3. When is EXPOSE Useful?

  • It’s helpful when using Docker networking (e.g., linking multiple containers).
  • Some cloud services (like AWS ECS) detect EXPOSE ports for automatic mappings.
  • But for local development, you must use -p to expose it to your machine.

Explaining npm start or npm run start

When you run:

npm start

or

npm run start

Docusaurus does the following:

1. Looks for the start script inside package.json:

"scripts": {
"start": "docusaurus start"
}

This means npm start executes:

docusaurus start

2. Launches the Docusaurus Development Server:

  • Starts a local development server using Express.js.
  • Watches for Markdown and config file changes and hot-reloads them.
  • Serves the website at http://localhost:3000/ (default port).

3. Keeps the Process Running:

  • The server keeps running as long as the terminal is open.
  • If you close the terminal, the server stops.

Difference Between npm start and npm run start

CommandDifference
npm startA shortcut for npm run start, but it only works if "start" is defined in package.json.
npm run startThe recommended way to run scripts. Always works, even for custom scripts.

For example, if package.json contains:

"scripts": {
"dev": "docusaurus start"
}
  • Running npm start will fail because start is not defined.
  • Running npm run dev will work.

Running Docker as a Background Process

When you run:

docker run -p 3000:3000 docusaurus-site
  • The container runs in the foreground (attached to your terminal).
  • If you close the terminal, the container stops.

Solution: Run Docker in the Background (-d mode)

docker run -d -p 3000:3000 docusaurus-site
  • The -d flag (--detach) makes Docker run in the background.
  • The container keeps running even if you close the terminal.

Check Running Containers To verify that the container is running:

docker ps

This lists all active containers.

Stopping the Container

To stop the running container, find its CONTAINER ID using docker ps, then run:

docker stop <CONTAINER_ID>

Restarting a Stopped Container Find the container ID using:

docker ps -a

Then restart it:

docker start <CONTAINER_ID>

Automatically Restart on System Reboot If you want the container to start automatically after a reboot:

docker run -d --restart unless-stopped -p 3000:3000 docusaurus-site
  • --restart unless-stopped ensures it restarts unless manually stopped.

Breaking Down npm start Execution

When you run:

npm start

or

npm run start

the process works in two steps:

Step 1: npm Executes the Script

  • npm looks inside package.json for a script named "start", like this:
    "scripts": {
    "start": "docusaurus start"
    }
  • npm then launches the command in the "start" script, which in this case is:
    docusaurus start
  • This means npm itself does NOT start the web server; it just acts as a task runner, executing whatever is defined in package.json.

Step 2: Docusaurus Takes Over

  • Once npm starts the docusaurus start command, Docusaurus itself takes over and:
    • Launches an Express.js-based local development server.
    • Watches for changes to Markdown files.
    • Serves the website at http://localhost:3000/.

Analogy: npm as a Conductor, Docusaurus as the Orchestra

  • npm is only responsible for finding and executing the script inside package.json.
  • Docusaurus is responsible for:
    • Starting the web server
    • Handling Markdown files
    • Rendering the UI

So, while npm initiates the process, Docusaurus is the one actually running the web application.

Think of npm start as a conductor starting an orchestra:

  • npm = The conductor (tells the musicians what to play).
  • Docusaurus = The orchestra (actually performs the music).
  • Web Server = The sound you hear.

The conductor npm does not make the music; it just starts the musicians Docusaurus, who do the actual work.


Summary

  • npm start **only triggers the script defined in package.json.
  • docusaurus start **is the command that actually runs the web server.
  • npm does not start the web server. Docusaurus does.