mirror of
				https://github.com/TriliumNext/Notes.git
				synced 2025-10-31 04:51:31 +08:00 
			
		
		
		
	Merge pull request #1923 from TriliumNext/feat/add-rootless-dockerfiles
feat(ci): add rootless dockerfiles
This commit is contained in:
		
						commit
						c82c01fb41
					
				| @ -8,6 +8,9 @@ indent_style = space | ||||
| insert_final_newline = true | ||||
| trim_trailing_whitespace = true | ||||
| 
 | ||||
| [*.sh] | ||||
| end_of_line = lf | ||||
| 
 | ||||
| [{server,translation}.json] | ||||
| charset = utf-8 | ||||
| end_of_line = lf | ||||
|  | ||||
							
								
								
									
										2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.gitattributes
									
									
									
									
										vendored
									
									
								
							| @ -14,4 +14,6 @@ demo/**/*.txt eol=lf | ||||
| demo/**/*.js eol=lf | ||||
| demo/**/*.css eol=lf | ||||
| 
 | ||||
| *.sh eol=lf | ||||
| 
 | ||||
| apps/client/src/libraries/** linguist-vendored | ||||
							
								
								
									
										50
									
								
								apps/server/Dockerfile.alpine.rootless
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								apps/server/Dockerfile.alpine.rootless
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| FROM node:22.15.0-alpine AS builder | ||||
| RUN corepack enable | ||||
| 
 | ||||
| # Install native dependencies since we might be building cross-platform. | ||||
| WORKDIR /usr/src/app | ||||
| COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/ | ||||
| # We have to use --no-frozen-lockfile due to CKEditor patches | ||||
| RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild | ||||
| 
 | ||||
| FROM node:22.15.0-alpine | ||||
| # Create a non-root user with configurable UID/GID | ||||
| ARG USER=trilium | ||||
| ARG UID=1001 | ||||
| ARG GID=1001 | ||||
| ENV USER=${USER} | ||||
| ENV UID=${UID} | ||||
| ENV GID=${GID} | ||||
| 
 | ||||
| # Install runtime dependencies and create user with specific UID/GID | ||||
| RUN apk add --no-cache dumb-init && \ | ||||
|     apk add --no-cache bash && \ | ||||
|     # Alpine uses addgroup/adduser (from busybox) instead of groupadd/useradd | ||||
|     addgroup -g ${GID} ${USER} && \ | ||||
|     adduser -u ${UID} -G ${USER} -s /bin/sh -D -h /home/${USER} ${USER} | ||||
| 
 | ||||
| WORKDIR /home/${USER}/app | ||||
| COPY ./dist /home/${USER}/app | ||||
| # Also copy the rootless entrypoint script | ||||
| COPY rootless-entrypoint.sh /home/${USER}/app/ | ||||
| RUN rm -rf /home/${USER}/app/node_modules/better-sqlite3 | ||||
| COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /home/${USER}/app/node_modules/better-sqlite3 | ||||
| RUN chown -R ${USER}:${USER} /home/${USER} | ||||
| 
 | ||||
| # Configure container | ||||
| USER ${USER} | ||||
| EXPOSE 8080 | ||||
| 
 | ||||
| # By default, use UID/GID that was set during build | ||||
| # These can be overridden at runtime | ||||
| ENV TRILIUM_UID=${UID} | ||||
| ENV TRILIUM_GID=${GID} | ||||
| ENV TRILIUM_DATA_DIR=/home/${USER}/trilium-data | ||||
| 
 | ||||
| # Use dumb-init as entrypoint to handle signals properly | ||||
| ENTRYPOINT ["/usr/bin/dumb-init", "--"] | ||||
| 
 | ||||
| # Use the entrypoint script | ||||
| CMD [ "bash", "./rootless-entrypoint.sh" ] | ||||
| 
 | ||||
| HEALTHCHECK --start-period=10s CMD node /home/${USER}/app/docker_healthcheck.js | ||||
							
								
								
									
										48
									
								
								apps/server/Dockerfile.rootless
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								apps/server/Dockerfile.rootless
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,48 @@ | ||||
| FROM node:22.15.0-bullseye-slim AS builder | ||||
| RUN corepack enable | ||||
| 
 | ||||
| # Install native dependencies since we might be building cross-platform. | ||||
| WORKDIR /usr/src/app/build | ||||
| COPY ./docker/package.json ./docker/pnpm-workspace.yaml /usr/src/app/ | ||||
| # We have to use --no-frozen-lockfile due to CKEditor patches | ||||
| RUN pnpm install --no-frozen-lockfile --prod && pnpm rebuild | ||||
| 
 | ||||
| FROM node:22.15.0-bullseye-slim | ||||
| # Create a non-root user with configurable UID/GID | ||||
| ARG USER=trilium | ||||
| ARG UID=1001 | ||||
| ARG GID=1001 | ||||
| ENV USER=${USER} | ||||
| ENV UID=${UID} | ||||
| ENV GID=${GID} | ||||
| 
 | ||||
| # Install only runtime dependencies | ||||
| RUN rm -rf \ | ||||
|     /var/lib/apt/lists/* \ | ||||
|     /var/cache/apt/* && \ | ||||
|     # Create the user/group with the default UID/GID | ||||
|     groupadd -g ${GID} ${USER} && \ | ||||
|     useradd -u ${UID} -g ${USER} -s /bin/sh -m ${USER} | ||||
| 
 | ||||
| WORKDIR /home/${USER}/app | ||||
| COPY ./dist /home/${USER}/app | ||||
| # Also copy the rootless entrypoint script | ||||
| COPY rootless-entrypoint.sh /home/${USER}/app/ | ||||
| RUN rm -rf /home/${USER}/app/node_modules/better-sqlite3 | ||||
| COPY --from=builder /usr/src/app/node_modules/better-sqlite3 /home/${USER}/app/node_modules/better-sqlite3 | ||||
| RUN chown -R ${USER}:${USER} /home/${USER} | ||||
| 
 | ||||
| # Configure container | ||||
| USER ${USER} | ||||
| EXPOSE 8080 | ||||
| 
 | ||||
| # By default, use UID/GID that was set during build | ||||
| # These can be overridden at runtime | ||||
| ENV TRILIUM_UID=${UID} | ||||
| ENV TRILIUM_GID=${GID} | ||||
| ENV TRILIUM_DATA_DIR=/home/${USER}/trilium-data | ||||
| 
 | ||||
| # Use the entrypoint script | ||||
| CMD [ "bash", "./rootless-entrypoint.sh" ] | ||||
| 
 | ||||
| HEALTHCHECK --start-period=10s CMD node /home/${USER}/app/docker_healthcheck.js | ||||
| @ -154,6 +154,12 @@ | ||||
|           }, | ||||
|           "alpine": { | ||||
|             "command": "docker build . -t triliumnext-alpine -f Dockerfile.alpine" | ||||
|           }, | ||||
|           "rootless-debian": { | ||||
|             "command": "docker build . -t triliumnext-rootless-debian -f Dockerfile.rootless" | ||||
|           }, | ||||
|           "rootless-alpine": { | ||||
|             "command": "docker build . -t triliumnext-rootless-alpine -f Dockerfile.alpine.rootless" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
| @ -169,6 +175,12 @@ | ||||
|           }, | ||||
|           "alpine": { | ||||
|             "command": "docker run -p 8081:8080 triliumnext-alpine" | ||||
|           }, | ||||
|           "rootless-debian": { | ||||
|             "command": "docker run -p 8081:8080 triliumnext-rootless-debian" | ||||
|           }, | ||||
|           "rootless-alpine": { | ||||
|             "command": "docker run -p 8081:8080 triliumnext-rootless-alpine" | ||||
|           } | ||||
|         } | ||||
|       }, | ||||
|  | ||||
							
								
								
									
										28
									
								
								apps/server/rootless-entrypoint.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										28
									
								
								apps/server/rootless-entrypoint.sh
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,28 @@ | ||||
| #!/bin/bash | ||||
| # Rootless entrypoint script for Trilium Notes | ||||
| # Works with both Debian and Alpine-based images | ||||
| 
 | ||||
| # Check if runtime UID/GID match the expected values | ||||
| if [ "${TRILIUM_UID}" != "$(id -u)" ] || [ "${TRILIUM_GID}" != "$(id -g)" ]; then | ||||
|   echo "Detected UID:GID mismatch (current: $(id -u):$(id -g), expected: ${TRILIUM_UID}:${TRILIUM_GID})" | ||||
|   # Check GID mismatch | ||||
|   if [ "${TRILIUM_GID}" != "$(id -g)" ]; then | ||||
|     echo "ERROR: Cannot change GID at runtime in rootless mode." | ||||
|     echo "       Current GID: $(id -g), Expected GID: ${TRILIUM_GID}" | ||||
|     echo "       Please use docker run with --user $(id -u):$(id -g) instead." | ||||
|     exit 1 | ||||
|   fi | ||||
|   # Check UID mismatch | ||||
|   if [ "${TRILIUM_UID}" != "$(id -u)" ]; then | ||||
|     echo "ERROR: Cannot change UID at runtime in rootless mode." | ||||
|     echo "       Current UID: $(id -u), Expected UID: ${TRILIUM_UID}" | ||||
|     echo "       Please use docker run with --user $(id -u):$(id -g) instead." | ||||
|     exit 1 | ||||
|   fi | ||||
| fi | ||||
| 
 | ||||
| # Make sure data directory has correct permissions | ||||
| mkdir -p "${TRILIUM_DATA_DIR}" | ||||
| 
 | ||||
| # Start the app | ||||
| exec node ./main.cjs | ||||
| @ -77,3 +77,114 @@ docker inspect [container_name]</code></pre> | ||||
| <p>If you are having timezone issues and you are not using docker-compose, | ||||
|   you may need to add a <code>TZ</code> environment variable with the <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">TZ identifier</a> of | ||||
|   your local timezone.</p> | ||||
| <h2>Rootless Docker Image</h2> | ||||
| <aside class="admonition note"> | ||||
|   <p>Please keep in mind that the data directory is at <code>/home/trilium/trilium-data</code> instead | ||||
|     of the typical <code>/home/node/trilium-data</code>. This is because a new | ||||
|     user is created and used to run Trilium within the rootless containers.</p> | ||||
| </aside> | ||||
| <p>If you would prefer to run Trilium without having to run the Docker container | ||||
|   as <code>root</code>, you can use either of the provided Debian (default) | ||||
|   and Alpine-based images with the <code>rootless</code> tag. </p> | ||||
| <p><em><strong>If you're unsure, stick to the “rootful” Docker image referenced above.</strong></em> | ||||
| </p> | ||||
| <p>Below are some commands to pull the rootless images:</p><pre><code class="language-text-x-trilium-auto"># For Debian-based image | ||||
| docker pull triliumnext/notes:rootless | ||||
| 
 | ||||
| # For Alpine-based image | ||||
| docker pull triliumnext/notes:rootless-alpine</code></pre> | ||||
| <h3>Why Rootless?</h3> | ||||
| <p>Running containers as non-root is a security best practice that reduces | ||||
|   the potential impact of container breakouts. If an attacker manages to | ||||
|   escape the container, they'll only have the permissions of the non-root | ||||
|   user instead of full root access to the host.</p> | ||||
| <h3>How It Works</h3> | ||||
| <p>The rootless Trilium image:</p> | ||||
| <ol> | ||||
|   <li>Creates a non-root user (<code>trilium</code>) during build time</li> | ||||
|   <li>Configures the application to run as this non-root user</li> | ||||
|   <li>Allows runtime customization of the user's UID/GID via Docker's <code>--user</code> flag</li> | ||||
|   <li>Does not require a separate Docker <code>entrypoint</code> script</li> | ||||
| </ol> | ||||
| <h3>Usage</h3> | ||||
| <h4><strong>Using docker-compose (Recommended)</strong></h4><pre><code class="language-text-x-trilium-auto"># Run with default UID/GID (1000:1000) | ||||
| docker-compose -f docker-compose.rootless.yml up -d | ||||
| 
 | ||||
| # Run with custom UID/GID (e.g., match your host user) | ||||
| TRILIUM_UID=$(id -u) TRILIUM_GID=$(id -g) docker-compose -f docker-compose.rootless.yml up -d | ||||
| 
 | ||||
| # Specify a custom data directory | ||||
| TRILIUM_DATA_DIR=/path/to/your/data TRILIUM_UID=$(id -u) TRILIUM_GID=$(id -g) docker-compose -f docker-compose.rootless.yml up -d | ||||
| </code></pre> | ||||
| <h4><strong>Using Docker CLI</strong></h4><pre><code class="language-text-x-trilium-auto"># Build the image | ||||
| docker build -t triliumnext/notes:rootless -f apps/server/Dockerfile.rootless . | ||||
| 
 | ||||
| # Run with default UID/GID (1000:1000) | ||||
| docker run -d --name trilium -p 8080:8080 -v ~/trilium-data:/home/trilium/trilium-data triliumnext/notes:rootless | ||||
| 
 | ||||
| # Run with custom UID/GID | ||||
| docker run -d --name trilium -p 8080:8080 --user $(id -u):$(id -g) -v ~/trilium-data:/home/trilium/trilium-data triliumnext/notes:rootless | ||||
| </code></pre> | ||||
| <h3>Environment Variables</h3> | ||||
| <ul> | ||||
|   <li><code>TRILIUM_UID</code>: UID to use for the container process (passed | ||||
|     to Docker's <code>--user</code> flag)</li> | ||||
|   <li><code>TRILIUM_GID</code>: GID to use for the container process (passed | ||||
|     to Docker's <code>--user</code> flag)</li> | ||||
|   <li><code>TRILIUM_DATA_DIR</code>: Path to the data directory inside the container | ||||
|     (default: <code>/home/node/trilium-data</code>)</li> | ||||
| </ul> | ||||
| <h3>Volume Permissions</h3> | ||||
| <p>If you encounter permission issues with the data volume, ensure that:</p> | ||||
| <ol> | ||||
|   <li>The host directory has appropriate permissions for the UID/GID you're | ||||
|     using</li> | ||||
|   <li>You're setting both <code>TRILIUM_UID</code> and <code>TRILIUM_GID</code> to | ||||
|     match the owner of the host directory</li> | ||||
| </ol><pre><code class="language-text-x-trilium-auto"># For example, if your data directory is owned by UID 1001 and GID 1001: | ||||
| TRILIUM_UID=1001 TRILIUM_GID=1001 docker-compose -f docker-compose.rootless.yml up -d | ||||
| </code></pre> | ||||
| <h3>Considerations</h3> | ||||
| <ul> | ||||
|   <li>The container starts with a specific UID/GID which can be customized at | ||||
|     runtime</li> | ||||
|   <li>Unlike the traditional setup, this approach does not use a separate entrypoint | ||||
|     script with <code>usermod</code>/<code>groupmod</code> commands</li> | ||||
|   <li>The container cannot modify its own UID/GID at runtime, which is a security | ||||
|     feature of rootless containers</li> | ||||
| </ul> | ||||
| <h3>Available Rootless Images</h3> | ||||
| <p>Two rootless variants are provided:</p> | ||||
| <ol> | ||||
|   <li><strong>Debian-based</strong> (default): Uses the Debian Bullseye Slim | ||||
|     base image | ||||
|     <ul> | ||||
|       <li>Dockerfile: <code>apps/server/Dockerfile.rootless</code> | ||||
|       </li> | ||||
|       <li>Recommended for most users</li> | ||||
|     </ul> | ||||
|   </li> | ||||
|   <li><strong>Alpine-based</strong>: Uses the Alpine base image for smaller | ||||
|     size | ||||
|     <ul> | ||||
|       <li>Dockerfile: <code>apps/server/Dockerfile.alpine.rootless</code> | ||||
|       </li> | ||||
|       <li>Smaller image size, but may have compatibility issues with some systems</li> | ||||
|     </ul> | ||||
|   </li> | ||||
| </ol> | ||||
| <h3>Building Custom Rootless Images</h3> | ||||
| <p>If you would prefer, you can also customize the UID/GID at build time:</p><pre><code class="language-text-x-trilium-auto"># For Debian-based image with custom UID/GID | ||||
| docker build --build-arg USER=myuser --build-arg UID=1001 --build-arg GID=1001 \ | ||||
|   -t triliumnext/notes:rootless-custom -f apps/server/Dockerfile.rootless . | ||||
| 
 | ||||
| # For Alpine-based image with custom UID/GID | ||||
| docker build --build-arg USER=myuser --build-arg UID=1001 --build-arg GID=1001 \ | ||||
|   -t triliumnext/notes:alpine-rootless-custom -f apps/server/Dockerfile.alpine.rootless . | ||||
| </code></pre> | ||||
| <p>Available build arguments:</p> | ||||
| <ul> | ||||
|   <li><code>USER</code>: Username for the non-root user (default: trilium)</li> | ||||
|   <li><code>UID</code>: User ID for the non-root user (default: 1000)</li> | ||||
|   <li><code>GID</code>: Group ID for the non-root user (default: 1000)</li> | ||||
| </ul> | ||||
							
								
								
									
										31
									
								
								docker-compose.rootless.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								docker-compose.rootless.yml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| version: '3.8' | ||||
| 
 | ||||
| # Running `docker-compose -f docker-compose.rootless.yml up` will create/use the "trilium-data" directory in the user home | ||||
| # Run `TRILIUM_DATA_DIR=/path/of/your/choice docker-compose -f docker-compose.rootless.yml up` to set a different directory | ||||
| # To run in the background, use `docker-compose -f docker-compose.rootless.yml up -d` | ||||
| # To use the Alpine-based image, run with `TRILIUM_VARIANT=alpine docker-compose -f docker-compose.rootless.yml up` | ||||
| services: | ||||
|   trilium: | ||||
|     # Optionally, replace `latest` with a version tag like `v0.90.3` | ||||
|     # Using `latest` may cause unintended updates to the container | ||||
|     image: triliumnext/notes:rootless | ||||
|     restart: unless-stopped | ||||
|     environment: | ||||
|       - TRILIUM_DATA_DIR=/home/trilium/trilium-data | ||||
|       # Set the desired UID/GID for the Trilium process. Will be used during docker run | ||||
|       # These should match the owner of your data directory on the host | ||||
|       - TRILIUM_UID=${TRILIUM_UID:-1001} | ||||
|       - TRILIUM_GID=${TRILIUM_GID:-1001} | ||||
|     # Use the specified UID/GID for the container process | ||||
|     user: ${TRILIUM_UID:-1001}:${TRILIUM_GID:-1001} | ||||
|     ports: | ||||
|       # By default, Trilium will be available at http://localhost:8080 | ||||
|       # It will also be accessible at http://<host-ip>:8080 | ||||
|       # You might want to limit this with something like Docker Networks, reverse proxies, or firewall rules | ||||
|       - '8080:8080' | ||||
|     volumes: | ||||
|       # Unless TRILIUM_DATA_DIR is set, the data will be stored in the "trilium-data" directory in the home directory. | ||||
|       # This can also be changed by replacing the line below with `- /path/of/your/choice:/home/trilium/trilium-data | ||||
|       - ${TRILIUM_DATA_DIR:-~/trilium-data}:/home/trilium/trilium-data | ||||
|       - /etc/timezone:/etc/timezone:ro | ||||
|       - /etc/localtime:/etc/localtime:ro | ||||
| @ -54,6 +54,7 @@ | ||||
|     *   For read-only notes, a floating button allows copying the code snippet to clipboard. | ||||
| *   [Math in text notes: equations can now be displayed on multiple lines](https://github.com/TriliumNext/Notes/pull/2003) by @SiriusXT | ||||
| *   [Metrics endpoint](https://github.com/TriliumNext/Notes/pull/2024) by @perfectra1n | ||||
| *   Docker: Rootless [Dockerfiles are now available](https://github.com/TriliumNext/Notes/pull/1923/files) by @perfectra1n | ||||
| 
 | ||||
| ## 📖 Documentation | ||||
| 
 | ||||
|  | ||||
| @ -118,3 +118,122 @@ The `--user` directive is unsupported. Instead, use the `USER_UID` and `USER_GID | ||||
| ### Note on timezones | ||||
| 
 | ||||
| If you are having timezone issues and you are not using docker-compose, you may need to add a `TZ` environment variable with the [TZ identifier](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones) of your local timezone. | ||||
| 
 | ||||
| ## Rootless Docker Image | ||||
| 
 | ||||
| > [!NOTE] | ||||
| > Please keep in mind that the data directory is at `/home/trilium/trilium-data` instead of the typical `/home/node/trilium-data`. This is because a new user is created and used to run Trilium within the rootless containers. | ||||
| 
 | ||||
| If you would prefer to run Trilium without having to run the Docker container as `root`, you can use either of the provided Debian (default) and Alpine-based images with the `rootless` tag.  | ||||
| 
 | ||||
| _**If you're unsure, stick to the “rootful” Docker image referenced above.**_ | ||||
| 
 | ||||
| Below are some commands to pull the rootless images: | ||||
| 
 | ||||
| ``` | ||||
| # For Debian-based image | ||||
| docker pull triliumnext/notes:rootless | ||||
| 
 | ||||
| # For Alpine-based image | ||||
| docker pull triliumnext/notes:rootless-alpine | ||||
| ``` | ||||
| 
 | ||||
| ### Why Rootless? | ||||
| 
 | ||||
| Running containers as non-root is a security best practice that reduces the potential impact of container breakouts. If an attacker manages to escape the container, they'll only have the permissions of the non-root user instead of full root access to the host. | ||||
| 
 | ||||
| ### How It Works | ||||
| 
 | ||||
| The rootless Trilium image: | ||||
| 
 | ||||
| 1.  Creates a non-root user (`trilium`) during build time | ||||
| 2.  Configures the application to run as this non-root user | ||||
| 3.  Allows runtime customization of the user's UID/GID via Docker's `--user` flag | ||||
| 4.  Does not require a separate Docker `entrypoint` script | ||||
| 
 | ||||
| ### Usage | ||||
| 
 | ||||
| #### **Using docker-compose (Recommended)** | ||||
| 
 | ||||
| ``` | ||||
| # Run with default UID/GID (1000:1000) | ||||
| docker-compose -f docker-compose.rootless.yml up -d | ||||
| 
 | ||||
| # Run with custom UID/GID (e.g., match your host user) | ||||
| TRILIUM_UID=$(id -u) TRILIUM_GID=$(id -g) docker-compose -f docker-compose.rootless.yml up -d | ||||
| 
 | ||||
| # Specify a custom data directory | ||||
| TRILIUM_DATA_DIR=/path/to/your/data TRILIUM_UID=$(id -u) TRILIUM_GID=$(id -g) docker-compose -f docker-compose.rootless.yml up -d | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| #### **Using Docker CLI** | ||||
| 
 | ||||
| ``` | ||||
| # Build the image | ||||
| docker build -t triliumnext/notes:rootless -f apps/server/Dockerfile.rootless . | ||||
| 
 | ||||
| # Run with default UID/GID (1000:1000) | ||||
| docker run -d --name trilium -p 8080:8080 -v ~/trilium-data:/home/trilium/trilium-data triliumnext/notes:rootless | ||||
| 
 | ||||
| # Run with custom UID/GID | ||||
| docker run -d --name trilium -p 8080:8080 --user $(id -u):$(id -g) -v ~/trilium-data:/home/trilium/trilium-data triliumnext/notes:rootless | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| ### Environment Variables | ||||
| 
 | ||||
| *   `TRILIUM_UID`: UID to use for the container process (passed to Docker's `--user` flag) | ||||
| *   `TRILIUM_GID`: GID to use for the container process (passed to Docker's `--user` flag) | ||||
| *   `TRILIUM_DATA_DIR`: Path to the data directory inside the container (default: `/home/node/trilium-data`) | ||||
| 
 | ||||
| ### Volume Permissions | ||||
| 
 | ||||
| If you encounter permission issues with the data volume, ensure that: | ||||
| 
 | ||||
| 1.  The host directory has appropriate permissions for the UID/GID you're using | ||||
| 2.  You're setting both `TRILIUM_UID` and `TRILIUM_GID` to match the owner of the host directory | ||||
| 
 | ||||
| ``` | ||||
| # For example, if your data directory is owned by UID 1001 and GID 1001: | ||||
| TRILIUM_UID=1001 TRILIUM_GID=1001 docker-compose -f docker-compose.rootless.yml up -d | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| ### Considerations | ||||
| 
 | ||||
| *   The container starts with a specific UID/GID which can be customized at runtime | ||||
| *   Unlike the traditional setup, this approach does not use a separate entrypoint script with `usermod`/`groupmod` commands | ||||
| *   The container cannot modify its own UID/GID at runtime, which is a security feature of rootless containers | ||||
| 
 | ||||
| ### Available Rootless Images | ||||
| 
 | ||||
| Two rootless variants are provided: | ||||
| 
 | ||||
| 1.  **Debian-based** (default): Uses the Debian Bullseye Slim base image | ||||
|     *   Dockerfile: `apps/server/Dockerfile.rootless` | ||||
|     *   Recommended for most users | ||||
| 2.  **Alpine-based**: Uses the Alpine base image for smaller size | ||||
|     *   Dockerfile: `apps/server/Dockerfile.alpine.rootless` | ||||
|     *   Smaller image size, but may have compatibility issues with some systems | ||||
| 
 | ||||
| ### Building Custom Rootless Images | ||||
| 
 | ||||
| If you would prefer, you can also customize the UID/GID at build time: | ||||
| 
 | ||||
| ``` | ||||
| # For Debian-based image with custom UID/GID | ||||
| docker build --build-arg USER=myuser --build-arg UID=1001 --build-arg GID=1001 \ | ||||
|   -t triliumnext/notes:rootless-custom -f apps/server/Dockerfile.rootless . | ||||
| 
 | ||||
| # For Alpine-based image with custom UID/GID | ||||
| docker build --build-arg USER=myuser --build-arg UID=1001 --build-arg GID=1001 \ | ||||
|   -t triliumnext/notes:alpine-rootless-custom -f apps/server/Dockerfile.alpine.rootless . | ||||
| 
 | ||||
| ``` | ||||
| 
 | ||||
| Available build arguments: | ||||
| 
 | ||||
| *   `USER`: Username for the non-root user (default: trilium) | ||||
| *   `UID`: User ID for the non-root user (default: 1000) | ||||
| *   `GID`: Group ID for the non-root user (default: 1000) | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Elian Doran
						Elian Doran