Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Without this, `COPY . .` copies the host's node_modules over the ones
# installed by `npm ci` in the image -- host-platform binaries and all.
node_modules
**/node_modules

# Build artefacts, regenerated in the container
opsimate-docs/build
opsimate-docs/.docusaurus
opsimate-docs/.cache-loader

.git
.github
*.log
.DS_Store
.env
.env.local
2 changes: 1 addition & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ updates:

# Docs site Docker image
- package-ecosystem: "docker"
directory: "/opsimate-docs"
directory: "/"
schedule:
interval: "weekly"
commit-message:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ jobs:
- name: Setup Node.js
uses: actions/setup-node@v7
with:
# Matches opsimate-docs/dockerfile. Docusaurus 3.10 requires >=20,
# Matches the Dockerfile. Docusaurus 3.10 requires >=20,
# so this must stay on a supported LTS line.
node-version: '24'
cache: 'npm'
Expand Down
3 changes: 0 additions & 3 deletions .github/workflows/link-check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,11 @@ jobs:
with:
node-version: '24'
cache: 'npm'
cache-dependency-path: 'opsimate-docs/package-lock.json'

- name: Install dependencies
working-directory: ./opsimate-docs
run: npm ci

- name: Build documentation
working-directory: ./opsimate-docs
run: npm run build
env:
# Fail on broken links
Expand Down
21 changes: 21 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM node:24-alpine

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/sh
set -eu
user="$(docker image inspect opsimate-docs --format '{{.Config.User}}')"
test -n "$user"
test "$user" != "0"
test "$user" != "root"

Repository: OpsiMate/documentation

Length of output: 204


🏁 Script executed:

#!/bin/sh
set -eu

echo "== repository files named Dockerfile =="
fd -a 'Dockerfile$' . || true

echo "== Dockerfile contents =="
if [ -f Dockerfile ]; then
  cat -n Dockerfile
fi

echo "== package metadata for workspace/start scripts =="
if [ -f package.json ]; then
  jq '.workspaces, .scripts' package.json
fi
if [ -d opsimate-docs ]; then
  jq '.workspaces, .scripts' opsimate-docs/package.json
fi

echo "== search for USER/opsimate-docs/.docusaurus references =="
rg -n --glob '!node_modules' --glob '!dist' --glob '!build' 'USER\s|\.docusaurus|opsimate-docs' . || true

Repository: OpsiMate/documentation

Length of output: 2891


🌐 Web query:

Docker official Node Dockerfile node:alpine base image USER default CMD node USER node

💡 Result:

In the official Node.js Docker images (including node:alpine), the default user at runtime is root [1][2][3]. Although these images include a pre-created, unprivileged user named node (typically with UID 1000) [4][5][3], the images are designed to start as root by default to provide maximum flexibility during the build and setup process [1]. If the user were set to node by default, any subsequent instructions in a Dockerfile that require root privileges (such as installing OS-level dependencies via apk or apt) would necessitate switching back to root [1]. To follow security best practices and adhere to the principle of least privilege, you should drop privileges after your setup is complete by adding USER node to your Dockerfile, typically just before your CMD instruction [6][7][8][3]. Example workflow in a Dockerfile: FROM node:alpine # Perform root-level operations (e.g., installing dependencies) RUN apk add --no-cache some-package WORKDIR /home/node/app # Switch to the unprivileged node user USER node # Run the application CMD ["node", "index.js"] Alternatively, you can run an existing image as the non-root user without modifying the Dockerfile by using the --user or -u flag in your docker run command: docker run -u "node" node:alpine node index.js [7][3]

Citations:


Run the documentation server as the unprivileged node user.

Dockerfile does not set USER, so CMD runs under the base image user. Add USER node before CMD after assigning /app ownership to that user.

Proposed fix
 WORKDIR /app
 
 ...
 COPY . .
+RUN chown -R node:node /app
+USER node
 
 EXPOSE 3000
🧰 Tools
🪛 Trivy (0.72.0)

[error] 1-1: Image user should not be 'root'

Specify at least 1 USER command in Dockerfile with non-root user as argument

Rule: DS-0002

Learn more

(IaC/Dockerfile)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Dockerfile` at line 1, Update the Dockerfile to assign /app ownership to the
unprivileged node user, then add USER node before CMD so the documentation
server runs without root privileges.

Source: Linters/SAST tools


WORKDIR /app

# Build from the repo root, not from opsimate-docs/. This is an npm workspace,
# so the root package-lock.json is the only lockfile -- it is what CI installs
# and what Dependabot maintains. Building from the subdirectory previously used
# a second, unmaintained lockfile that had drifted out of sync with
# package.json and broke `npm ci` outright.
COPY package.json package-lock.json ./
COPY opsimate-docs/package.json ./opsimate-docs/

RUN npm ci

COPY . .

EXPOSE 3000

# --host 0.0.0.0 so the server is reachable from outside the container;
# Docusaurus binds to localhost by default, which `docker run -p` cannot reach.
CMD ["npm", "run", "start", "--workspace=opsimate-docs", "--", "--host", "0.0.0.0"]
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,10 +53,11 @@ You can build and run the OpsiMate documentation inside a Docker container for a

### Build the Docker image

Run this from the repository root — the image builds the whole npm workspace,
so it needs the root `package-lock.json` in its build context.

```bash
cd opsimate-docs
docker build -t opsimate-docs .

```

### Run the Container
Expand Down
19 changes: 0 additions & 19 deletions opsimate-docs/dockerfile

This file was deleted.

Loading
Loading