feat(docs): add documentation around using the rootless Docker image

This commit is contained in:
perf3ct 2025-05-21 13:21:32 -07:00
parent cbbbae727f
commit a05e126d7d
2 changed files with 225 additions and 2 deletions

View File

@ -77,3 +77,110 @@ 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>
<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.&nbsp;</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-sh"># 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-sh"># 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/node/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/node/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-sh"># 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>
<p>&nbsp;</p>

View File

@ -118,3 +118,119 @@ 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
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:
```sh
# 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**
```sh
# 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/node/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/node/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
```sh
# 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)