Skip to content

Commit d59ed4e

Browse files
cevhericlaude
andcommitted
fix(docker): make mounted data volume writable for the non-root user (0.9.22)
Railway (and other platforms) mount persistent volumes owned by root, so the non-root 'nextjs' user could not open the SQLite store at /app/data, failing with 'SqliteError: unable to open database file'. Add docker-entrypoint.sh: when started as root, chown the data dir to nextjs and drop privileges via gosu; otherwise exec directly. Drop the hardcoded USER nextjs so the container can fix volume perms at startup, then run as nextjs. Verified the mechanism locally: entrypoint chowns /app/data to nextjs and pid 1 runs as uid 1001. Bump to 0.9.22 and point the Railway template at the new image. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 3aceda4 commit d59ed4e

6 files changed

Lines changed: 34 additions & 5 deletions

File tree

Dockerfile

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,17 @@ COPY --from=builder /usr/src/app/node_modules/file-uri-to-path ./node_modules/fi
6464
RUN addgroup --system --gid 1001 nodejs && \
6565
adduser --system --uid 1001 nextjs && \
6666
chown -R nextjs:nodejs /app
67-
USER nextjs
67+
68+
# gosu lets the entrypoint drop from root to the app user after fixing the
69+
# permissions of a mounted (often root-owned) data volume.
70+
RUN apt-get update && apt-get install -y --no-install-recommends gosu && \
71+
rm -rf /var/lib/apt/lists/*
72+
73+
# Entrypoint makes the SQLite data dir writable by `nextjs` then drops privileges.
74+
# The container starts as root only long enough to chown the volume mount; the
75+
# app process itself runs as the non-root `nextjs` user.
76+
COPY docker-entrypoint.sh /usr/local/bin/docker-entrypoint.sh
77+
RUN chmod +x /usr/local/bin/docker-entrypoint.sh
6878

6979
# Render uses PORT env variable, default to 3000
7080
EXPOSE 3000/tcp
@@ -73,4 +83,5 @@ ENV HOSTNAME="0.0.0.0"
7383

7484
# server.js is created by next build from the standalone output
7585
# https://nextjs.org/docs/pages/api-reference/next-config-js/output
86+
ENTRYPOINT ["docker-entrypoint.sh"]
7687
CMD ["node", "server.js"]

deploy/railway/PUBLISH.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ values to enter are in [`template.json`](./template.json).
1313

1414
- In the editor, click **+ New** (top-right), or open the command palette
1515
(`⌘K` / `Ctrl+K`) → **+ New Service****Docker Image**.
16-
- Image: `ghcr.io/libredb/libredb-studio:0.9.21` (pinned — never `:latest`).
16+
- Image: `ghcr.io/libredb/libredb-studio:0.9.22` (pinned — never `:latest`).
1717
- Rename the service to `libredb-studio`.
1818

1919
## 3. Variables

deploy/railway/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ Or browse the Railway template marketplace and search **LibreDB Studio**.
2929
## Deploy (manual — works today, before publishing)
3030

3131
Railway dashboard → **New Project**, then in the project view click **+ New → Docker Image**
32-
enter `ghcr.io/libredb/libredb-studio:0.9.21`, then configure the service to
32+
enter `ghcr.io/libredb/libredb-studio:0.9.22`, then configure the service to
3333
match [`template.json`](./template.json):
3434

3535
- **Networking:** enable a public domain, target port `3000`.

deploy/railway/template.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"name": "libredb-studio",
99
"icon": "https://raw.githubusercontent.com/libredb/libredb-studio/main/deploy/railway/libredb-studio.png",
1010
"source": {
11-
"image": "ghcr.io/libredb/libredb-studio:0.9.21"
11+
"image": "ghcr.io/libredb/libredb-studio:0.9.22"
1212
},
1313
"networking": {
1414
"public": true,

docker-entrypoint.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/bin/sh
2+
set -e
3+
4+
# Make the SQLite data directory writable by the non-root app user.
5+
#
6+
# Some platforms (e.g. Railway) mount persistent volumes owned by root, which
7+
# the non-root `nextjs` user cannot write to — causing the SQLite store to fail
8+
# with "unable to open database file". When this container starts as root we
9+
# chown the data directory to the app user and then drop privileges. When it is
10+
# already running as non-root (the default for plain `docker run`), we just exec.
11+
if [ "$(id -u)" = "0" ]; then
12+
DATA_DIR="$(dirname "${STORAGE_SQLITE_PATH:-/app/data/libredb-storage.db}")"
13+
mkdir -p "$DATA_DIR"
14+
chown -R nextjs:nodejs "$DATA_DIR" || true
15+
exec gosu nextjs:nodejs "$@"
16+
fi
17+
18+
exec "$@"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@libredb/studio",
3-
"version": "0.9.21",
3+
"version": "0.9.22",
44
"private": false,
55
"publishConfig": {
66
"access": "public"

0 commit comments

Comments
 (0)