DEV Community

Cindy Le
Cindy Le

Posted on

How to Dockerize a Docusaurus v2 application

Let's get started with the most basic Docusaurus application.

Getting started with Docusaurus

  1. Create a new Docusaurus site ```

npx create-docusaurus@latest my-website classic


Your directory structure should look like this:

![Directory structure](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/uzsk43jvyqbgbu0ozbeh.png)

2. Start the site:
Enter fullscreen mode Exit fullscreen mode

cd my-website
npx docusaurus start


3. Open `http://localhost:3000`. Once you see that your website is running locally you can close the server then proceed to the next section.

## Adding the Dockerfile

1. Add the `host` flag to the `start` and `serve` scripts in the `package.json` file

```diff


  "scripts": {
    "docusaurus": "docusaurus",
--  "start": "docusaurus start",
++  "start": "docusaurus start --host 0.0.0.0",
    "build": "docusaurus build",
    "swizzle": "docusaurus swizzle",
    "deploy": "docusaurus deploy",
    "clear": "docusaurus clear",
--  "serve": "docusaurus serve",
++  "serve": "docusaurus serve --host 0.0.0.0",
    "write-translations": "docusaurus write-translations",
    "write-heading-ids": "docusaurus write-heading-ids"
  },


Enter fullscreen mode Exit fullscreen mode
  1. Create a new file called Dockerfile in the root of the project


## Base ########################################################################
# Use a larger node image to do the build for native deps (e.g., gcc, python)
FROM node:lts as base

# Reduce npm log spam and colour during install within Docker
ENV NPM_CONFIG_LOGLEVEL=warn
ENV NPM_CONFIG_COLOR=false

# We'll run the app as the `node` user, so put it in their home directory
WORKDIR /home/node/app
# Copy the source code over
COPY --chown=node:node . /home/node/app/

## Development #################################################################
# Define a development target that installs devDeps and runs in dev mode
FROM base as development
WORKDIR /home/node/app
# Install (not ci) with dependencies, and for Linux vs. Linux Musl (which we use for -alpine)
RUN npm install
# Switch to the node user vs. root
USER node
# Expose port 3000
EXPOSE 3000
# Start the app in debug mode so we can attach the debugger
CMD ["npm", "start"]

## Production ##################################################################
# Also define a production target which doesn't use devDeps
FROM base as production
WORKDIR /home/node/app
COPY --chown=node:node --from=development /home/node/app/node_modules /home/node/app/node_modules
# Build the Docusaurus app
RUN npm run build

## Deploy ######################################################################
# Use a stable nginx image
FROM nginx:stable-alpine as deploy
WORKDIR /home/node/app
# Copy what we've installed/built from production
COPY --chown=node:node --from=production /home/node/app/build /usr/share/nginx/html/


Enter fullscreen mode Exit fullscreen mode

Working with Docker container in development

  1. To build the Docker container for development, run


docker build --target development -t docs:dev .


Enter fullscreen mode Exit fullscreen mode
  1. To run the Docker container in development, run


docker run -p 3000:3000 docs:dev


Enter fullscreen mode Exit fullscreen mode

Note: Remember to stop the container before proceeding to the next step

Working with Docker container in production

  1. To build the Docker container for production, run


docker build -t docusaurus:latest .


Enter fullscreen mode Exit fullscreen mode
  1. To run the Docker container in production, run


docker run --rm -p 3000:80 docusaurus:latest


Enter fullscreen mode Exit fullscreen mode

Top comments (7)

Collapse
 
grodrigo profile image
grodrigo • Edited

I was getting this error in the development mode
ERROR [development 2/5] RUN mkdir -p /home/node/app/.docusaurus

If anyone is getting the same error, just put the line USER node before the WORKDIR /home/node/app in the base stage, so the folder will be owned by node.
In addition, you can remove both lines of the development stage.

And to run the container maybe for development is better to use it with a volume and with a container name like docker run --rm --name docusaurus -p 3000:3000 -v ./:/home/node/app/ docs:dev
Thanks for this post!

Collapse
 
danroscigno profile image
Dan Roscigno

Hi Cindy,
Thanks for this. I made one change as I saw that the node_modules/.cache dir could not be created (I think docusaurus writes there) at runtime. Here is the change I made to the Dockerfile (add a chown on the homedir for node):

# We'll run the app as the `node` user, so put it in their home directory
WORKDIR /home/node/app
# Do the chown so that the node_modules/.cache can be updated
RUN chown -R node:node /home/node

# Copy the source code over
COPY --chown=node:node . /home/node/app/
Enter fullscreen mode Exit fullscreen mode
Collapse
 
schatzopoulos profile image
Serafeim Chatzopoulos

I get the following error in the last step:

unable to convert uid/gid chown string to host mapping: can't find uid for user node: no such user: node
Any ideas? thanks

Collapse
 
schatzopoulos profile image
Serafeim Chatzopoulos

I found that removing the "--chown=node:node" part of the last COPY command solves the issue.
But I wonder if it is going to cause other issues.

Thread Thread
 
cauldyclark15 profile image
Joselie Castaneda
FROM node:lts as base
ENV NPM_CONFIG_LOGLEVEL=warn
ENV NPM_CONFIG_COLOR=false
WORKDIR /app
COPY . ./
RUN yarn install
RUN yarn build

FROM nginx:stable-alpine
COPY nginx.conf /etc/nginx/conf.d/configfile.template
ENV PORT 3000
ENV HOST 0.0.0.0
WORKDIR /home/node/app
RUN sh -c "envsubst '\$PORT'  < /etc/nginx/conf.d/configfile.template > /etc/nginx/conf.d/default.conf"
COPY --from=base /app/build /usr/share/nginx/html
EXPOSE 3000
CMD ["nginx", "-g", "daemon off;"]
Enter fullscreen mode Exit fullscreen mode

I simplified mine to just do production version and it worked.

Collapse
 
jackcrane profile image
jackcrane

Here is my docusaurus v2 dockerfile which is based on this one but I found to run more reliably. Worth a shot!

# Dockerfile built by Jack Crane. - https://jackcrane.rocks
# Build step

FROM node:16 AS build
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build

# Deployment step

FROM busybox:1.35 as deploy

RUN adduser -D static
USER static
WORKDIR /home/static

COPY --from=build /usr/src/app/build/ ./

EXPOSE 3000

CMD ["busybox", "httpd", "-f", "-v", "-p", "3000"]
Enter fullscreen mode Exit fullscreen mode
Collapse
 
jitvimol profile image
Jitvimol

Thanks for the tutorial. I follow the instructions and slighly modify by creating docker-compose.yml and it works!