Skip to content
This repository was archived by the owner on Jun 24, 2025. It is now read-only.

Commit c82c01f

Browse files
authored
Merge pull request #1923 from TriliumNext/feat/add-rootless-dockerfiles
feat(ci): add rootless dockerfiles
2 parents 46bffca + 521f4c2 commit c82c01f

File tree

12 files changed

+448
-43
lines changed

12 files changed

+448
-43
lines changed

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ indent_style = space
88
insert_final_newline = true
99
trim_trailing_whitespace = true
1010

11+
[*.sh]
12+
end_of_line = lf
13+
1114
[{server,translation}.json]
1215
charset = utf-8
1316
end_of_line = lf

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,6 @@ demo/**/*.txt eol=lf
1414
demo/**/*.js eol=lf
1515
demo/**/*.css eol=lf
1616

17+
*.sh eol=lf
18+
1719
apps/client/src/libraries/** linguist-vendored

apps/server/Dockerfile

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,28 @@
11
FROM node:22.16.0-bullseye-slim AS builder
2-
RUN corepack enable
2+
RUN corepack enable
33

4-
# Install native dependencies since we might be building cross-platform.
5-
WORKDIR /usr/src/app/build
6-
COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
7-
# We have to use --no-frozen-lockfile due to CKEditor patches
8-
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
4+
# Install native dependencies since we might be building cross-platform.
5+
WORKDIR /usr/src/app/build
6+
COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
7+
# We have to use --no-frozen-lockfile due to CKEditor patches
8+
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
99

1010
FROM node:22.16.0-bullseye-slim
11-
# Install only runtime dependencies
12-
RUN apt-get update && \
13-
apt-get install -y --no-install-recommends \
14-
gosu && \
15-
rm -rf \
16-
/var/lib/apt/lists/* \
17-
/var/cache/apt/*
11+
# Install only runtime dependencies
12+
RUN apt-get update && \
13+
apt-get install -y --no-install-recommends \
14+
gosu && \
15+
rm -rf \
16+
/var/lib/apt/lists/* \
17+
/var/cache/apt/*
1818

19-
WORKDIR /usr/src/app
20-
COPY ./dist /usr/src/app
21-
RUN rm -rf /usr/src/app/node_modules/better-sqlite3
22-
COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /usr/src/app/node_modules/better-sqlite3
23-
COPY ./start-docker.sh /usr/src/app
19+
WORKDIR /usr/src/app
20+
COPY ./dist /usr/src/app
21+
RUN rm -rf /usr/src/app/node_modules/better-sqlite3
22+
COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /usr/src/app/node_modules/better-sqlite3
23+
COPY ./start-docker.sh /usr/src/app
2424

25-
# Configure container
26-
EXPOSE 8080
27-
CMD [ "sh", "./start-docker.sh" ]
28-
HEALTHCHECK --start-period=10s CMD exec gosu node node /usr/src/app/docker_healthcheck.cjs
25+
# Configure container
26+
EXPOSE 8080
27+
CMD [ "sh", "./start-docker.sh" ]
28+
HEALTHCHECK --start-period=10s CMD exec gosu node node /usr/src/app/docker_healthcheck.cjs

apps/server/Dockerfile.alpine

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
11
FROM node:22.16.0-alpine AS builder
2-
RUN corepack enable
2+
RUN corepack enable
33

4-
# Install native dependencies since we might be building cross-platform.
5-
WORKDIR /usr/src/app
6-
COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
7-
# We have to use --no-frozen-lockfile due to CKEditor patches
8-
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
4+
# Install native dependencies since we might be building cross-platform.
5+
WORKDIR /usr/src/app
6+
COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
7+
# We have to use --no-frozen-lockfile due to CKEditor patches
8+
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
99

1010
FROM node:22.16.0-alpine
11-
# Install runtime dependencies
12-
RUN apk add --no-cache su-exec shadow
11+
# Install runtime dependencies
12+
RUN apk add --no-cache su-exec shadow
1313

14-
WORKDIR /usr/src/app
15-
COPY ./dist /usr/src/app
16-
RUN rm -rf /usr/src/app/node_modules/better-sqlite3
17-
COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /usr/src/app/node_modules/better-sqlite3
18-
COPY ./start-docker.sh /usr/src/app
14+
WORKDIR /usr/src/app
15+
COPY ./dist /usr/src/app
16+
RUN rm -rf /usr/src/app/node_modules/better-sqlite3
17+
COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /usr/src/app/node_modules/better-sqlite3
18+
COPY ./start-docker.sh /usr/src/app
1919

20-
# Add application user
21-
RUN adduser -s /bin/false node; exit 0
20+
# Add application user
21+
RUN adduser -s /bin/false node; exit 0
2222

23-
# Configure container
24-
EXPOSE 8080
25-
CMD [ "sh", "./start-docker.sh" ]
26-
HEALTHCHECK --start-period=10s CMD exec su-exec node node /usr/src/app/docker_healthcheck.cjs
23+
# Configure container
24+
EXPOSE 8080
25+
CMD [ "sh", "./start-docker.sh" ]
26+
HEALTHCHECK --start-period=10s CMD exec su-exec node node /usr/src/app/docker_healthcheck.cjs
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
FROM node:22.15.0-alpine AS builder
2+
RUN corepack enable
3+
4+
# Install native dependencies since we might be building cross-platform.
5+
WORKDIR /usr/src/app
6+
COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
7+
# We have to use --no-frozen-lockfile due to CKEditor patches
8+
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
9+
10+
FROM node:22.15.0-alpine
11+
# Create a non-root user with configurable UID/GID
12+
ARG USER=trilium
13+
ARG UID=1001
14+
ARG GID=1001
15+
ENV USER=${USER}
16+
ENV UID=${UID}
17+
ENV GID=${GID}
18+
19+
# Install runtime dependencies and create user with specific UID/GID
20+
RUN apk add --no-cache dumb-init && \
21+
apk add --no-cache bash && \
22+
# Alpine uses addgroup/adduser (from busybox) instead of groupadd/useradd
23+
addgroup -g ${GID} ${USER} && \
24+
adduser -u ${UID} -G ${USER} -s /bin/sh -D -h /home/${USER} ${USER}
25+
26+
WORKDIR /home/${USER}/app
27+
COPY ./dist /home/${USER}/app
28+
# Also copy the rootless entrypoint script
29+
COPY rootless-entrypoint.sh /home/${USER}/app/
30+
RUN rm -rf /home/${USER}/app/node_modules/better-sqlite3
31+
COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /home/${USER}/app/node_modules/better-sqlite3
32+
RUN chown -R ${USER}:${USER} /home/${USER}
33+
34+
# Configure container
35+
USER ${USER}
36+
EXPOSE 8080
37+
38+
# By default, use UID/GID that was set during build
39+
# These can be overridden at runtime
40+
ENV TRILIUM_UID=${UID}
41+
ENV TRILIUM_GID=${GID}
42+
ENV TRILIUM_DATA_DIR=/home/${USER}/trilium-data
43+
44+
# Use dumb-init as entrypoint to handle signals properly
45+
ENTRYPOINT ["/usr/bin/dumb-init", "--"]
46+
47+
# Use the entrypoint script
48+
CMD [ "bash", "./rootless-entrypoint.sh" ]
49+
50+
HEALTHCHECK --start-period=10s CMD node /home/${USER}/app/docker_healthcheck.js

apps/server/Dockerfile.rootless

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
FROM node:22.15.0-bullseye-slim AS builder
2+
RUN corepack enable
3+
4+
# Install native dependencies since we might be building cross-platform.
5+
WORKDIR /usr/src/app/build
6+
COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/
7+
# We have to use --no-frozen-lockfile due to CKEditor patches
8+
RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild
9+
10+
FROM node:22.15.0-bullseye-slim
11+
# Create a non-root user with configurable UID/GID
12+
ARG USER=trilium
13+
ARG UID=1001
14+
ARG GID=1001
15+
ENV USER=${USER}
16+
ENV UID=${UID}
17+
ENV GID=${GID}
18+
19+
# Install only runtime dependencies
20+
RUN rm -rf \
21+
/var/lib/apt/lists/* \
22+
/var/cache/apt/* && \
23+
# Create the user/group with the default UID/GID
24+
groupadd -g ${GID} ${USER} && \
25+
useradd -u ${UID} -g ${USER} -s /bin/sh -m ${USER}
26+
27+
WORKDIR /home/${USER}/app
28+
COPY ./dist /home/${USER}/app
29+
# Also copy the rootless entrypoint script
30+
COPY rootless-entrypoint.sh /home/${USER}/app/
31+
RUN rm -rf /home/${USER}/app/node_modules/better-sqlite3
32+
COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /home/${USER}/app/node_modules/better-sqlite3
33+
RUN chown -R ${USER}:${USER} /home/${USER}
34+
35+
# Configure container
36+
USER ${USER}
37+
EXPOSE 8080
38+
39+
# By default, use UID/GID that was set during build
40+
# These can be overridden at runtime
41+
ENV TRILIUM_UID=${UID}
42+
ENV TRILIUM_GID=${GID}
43+
ENV TRILIUM_DATA_DIR=/home/${USER}/trilium-data
44+
45+
# Use the entrypoint script
46+
CMD [ "bash", "./rootless-entrypoint.sh" ]
47+
48+
HEALTHCHECK --start-period=10s CMD node /home/${USER}/app/docker_healthcheck.js

apps/server/package.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,12 @@
154154
},
155155
"alpine": {
156156
"command": "docker build . -t triliumnext-alpine -f Dockerfile.alpine"
157+
},
158+
"rootless-debian": {
159+
"command": "docker build . -t triliumnext-rootless-debian -f Dockerfile.rootless"
160+
},
161+
"rootless-alpine": {
162+
"command": "docker build . -t triliumnext-rootless-alpine -f Dockerfile.alpine.rootless"
157163
}
158164
}
159165
},
@@ -169,6 +175,12 @@
169175
},
170176
"alpine": {
171177
"command": "docker run -p 8081:8080 triliumnext-alpine"
178+
},
179+
"rootless-debian": {
180+
"command": "docker run -p 8081:8080 triliumnext-rootless-debian"
181+
},
182+
"rootless-alpine": {
183+
"command": "docker run -p 8081:8080 triliumnext-rootless-alpine"
172184
}
173185
}
174186
},

apps/server/rootless-entrypoint.sh

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#!/bin/bash
2+
# Rootless entrypoint script for Trilium Notes
3+
# Works with both Debian and Alpine-based images
4+
5+
# Check if runtime UID/GID match the expected values
6+
if [ "${TRILIUM_UID}" != "$(id -u)" ] || [ "${TRILIUM_GID}" != "$(id -g)" ]; then
7+
echo "Detected UID:GID mismatch (current: $(id -u):$(id -g), expected: ${TRILIUM_UID}:${TRILIUM_GID})"
8+
# Check GID mismatch
9+
if [ "${TRILIUM_GID}" != "$(id -g)" ]; then
10+
echo "ERROR: Cannot change GID at runtime in rootless mode."
11+
echo " Current GID: $(id -g), Expected GID: ${TRILIUM_GID}"
12+
echo " Please use docker run with --user $(id -u):$(id -g) instead."
13+
exit 1
14+
fi
15+
# Check UID mismatch
16+
if [ "${TRILIUM_UID}" != "$(id -u)" ]; then
17+
echo "ERROR: Cannot change UID at runtime in rootless mode."
18+
echo " Current UID: $(id -u), Expected UID: ${TRILIUM_UID}"
19+
echo " Please use docker run with --user $(id -u):$(id -g) instead."
20+
exit 1
21+
fi
22+
fi
23+
24+
# Make sure data directory has correct permissions
25+
mkdir -p "${TRILIUM_DATA_DIR}"
26+
27+
# Start the app
28+
exec node ./main.cjs

apps/server/src/assets/doc_notes/en/User Guide/User Guide/Installation & Setup/Server Installation/1. Installing the server/Using Docker.html

Lines changed: 112 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)