Skip to content

Conversation

@rugk
Copy link
Contributor

@rugk rugk commented Oct 6, 2025

Fixes #207

Supersedes #214
Thanks @CommanderTvis

With some Copilot help I adjusted it again and executed both your test script and docker-compose up --build (note: the test script is not really needed, you can run docker compose like that) and it works for me:

$ docker-compose up --build
[+] Building 0.8s (16/16) FINISHED                                                                                                                                                                       
 => [internal] load local bake definitions                                                                                                                                                          0.0s
 => => reading from stdin 347B                                                                                                                                                                      0.0s
 => [internal] load build definition from Dockerfile                                                                                                                                                0.0s
 => => transferring dockerfile: 1.15kB                                                                                                                                                              0.0s
 => [internal] load metadata for docker.io/library/node:22-slim                                                                                                                                     0.7s
 => [auth] library/node:pull token for registry-1.docker.io                                                                                                                                         0.0s
 => [internal] load .dockerignore                                                                                                                                                                   0.0s
 => => transferring context: 99B                                                                                                                                                                    0.0s
 => [1/8] FROM docker.io/library/node:22-slim@sha256:d943bf20249f8b92eff6f605362df2ee9cf2d6ce2ea771a8886e126ec8714f08                                                                               0.0s
 => [internal] load build context                                                                                                                                                                   0.0s
 => => transferring context: 15.26kB                                                                                                                                                                0.0s
 => CACHED [2/8] WORKDIR /fredy                                                                                                                                                                     0.0s
 => CACHED [3/8] RUN apt-get update   && apt-get install -y --no-install-recommends chromium curl   && rm -rf /var/lib/apt/lists/*                                                                  0.0s
 => CACHED [4/8] COPY --chown=node:node package.json yarn.lock ./                                                                                                                                   0.0s
 => CACHED [5/8] RUN yarn config set network-timeout 600000   && yarn --frozen-lockfile   && yarn global add pm2                                                                                    0.0s
 => CACHED [6/8] COPY --chown=node:node . .                                                                                                                                                         0.0s
 => CACHED [7/8] RUN yarn build:frontend                                                                                                                                                            0.0s
 => CACHED [8/8] RUN mkdir -p /db /conf   && chown -R node:node /fredy /db /conf   && chmod 770 /db /conf   && ln -s /db /fredy/db   && ln -s /conf /fredy/conf                                     0.0s
 => exporting to image                                                                                                                                                                              0.0s
 => => exporting layers                                                                                                                                                                             0.0s
 => => writing image sha256:ed383019fb4706479b0b20d23396b495f48febcd1a70a0d435b331ecfb0b2e95                                                                                                        0.0s
 => => naming to ghcr.io/orangecoding/fredy                                                                                                                                                         0.0s
 => resolving provenance for metadata file                                                                                                                                                          0.0s
[+] Running 2/2
 ✔ fredy            Built                                                                                                                                                                           0.0s 
 ✔ Container fredy  Created                                                                                                                                                                         0.0s 
Attaching to fredy
fredy  | 2025-10-06T16:25:57: PM2 log: Launching in no daemon mode
fredy  | 2025-10-06T16:25:57: PM2 log: App [index:0] starting in -fork mode-
fredy  | 2025-10-06T16:25:57: PM2 log: App [index:0] online
fredy  | [2025-10-06 16:25:58] INFO: Applying migration: 0.init.js
fredy  | [2025-10-06 16:25:58] INFO: Migration applied: 0.init.js (0 ms)
fredy  | [2025-10-06 16:25:58] INFO: Applying migration: 1.create-fredy-base-structure.js
fredy  | [2025-10-06 16:25:58] INFO: Migration applied: 1.create-fredy-base-structure.js (1 ms)
fredy  | [2025-10-06 16:25:58] INFO: Applying migration: 2.active-flag-for-listings.js
fredy  | [2025-10-06 16:25:58] INFO: Migration applied: 2.active-flag-for-listings.js (0 ms)
fredy  | [2025-10-06 16:25:58] INFO: Applying migration: 2.new-indexes-for-listings.js
fredy  | [2025-10-06 16:25:58] INFO: Migration applied: 2.new-indexes-for-listings.js (1 ms)
fredy  | [2025-10-06 16:25:58] INFO: Applying migration: 3.changeset-for-listings.js
fredy  | [2025-10-06 16:25:58] INFO: Migration applied: 3.changeset-for-listings.js (1 ms)
fredy  | [2025-10-06 16:25:58] INFO: Applying migration: 4.watch-list.js
fredy  | [2025-10-06 16:25:58] INFO: Migration applied: 4.watch-list.js (0 ms)
fredy  | [2025-10-06 16:25:58] INFO: All migrations completed successfully.
fredy  | [2025-10-06 16:25:58] INFO: Started Fredy successfully. Ui can be accessed via http://localhost:9998
fredy  | [2025-10-06 16:25:58] DEBUG: No listings to check.
fredy  | [2025-10-06 16:25:58] DEBUG: Started API service on port 9998

Also finally found the official doc: https://github.com/nodejs/docker-node/blob/main/docs/BestPractices.md#non-root-user
A funny side-note: The UID/GID 1000 you came up before/had used already corresponds already to the node user so your Dockerfile kinda already was inconsistent here?

I am still not quite sure though why #214 did not work as I see no big differences in how I do it here.

Important note: From my experience when user have deployed this image somewhere and mounted some data in, the users of your app also may sometimes need to adjust the UID/GID/user e.g. if /db is mounted somewhere. However, I'd argue better to do that change now rather than later and settle on the good and apparently well-known UI/GID 1000 (= user node)

@orangecoding
Copy link
Owner

tbh, I'm not sure what / how you tested it, but if I taker your dockerfile and run it with my test script, I get the same error.

SqliteError: attempt to write a readonly database
    at SqliteConnection.execute (file:///fredy/lib/services/storage/SqliteConnection.js:77:28)
    at ensureDemoUserExists (file:///fredy/lib/services/storage/userStorage.js:135:22)
    at file:///fredy/index.js:54:1 {
  code: 'SQLITE_READONLY'
}

@orangecoding
Copy link
Owner

I was able to get it to work like this.
f0f1244

Anyway, thanks for looking into this!

@orangecoding
Copy link
Owner

mhm.. no even this change did not resolve it,

Container is unhealthy!
fredy  | 2025-10-06T18:09:01: PM2 log: Launching in no daemon mode
fredy  | 2025-10-06T18:09:01: PM2 log: App [index:0] starting in -fork mode-
fredy  | 2025-10-06T18:09:01: PM2 log: App [index:0] online
fredy  | SqliteError: unable to open database file
fredy  |     at new Database (/fredy/node_modules/better-sqlite3/lib/database.js:69:26)
fredy  |     at SqliteConnection.getConnection (file:///fredy/lib/services/storage/SqliteConnection.js:47:16)
fredy  |     at runMigrations (file:///fredy/lib/services/storage/migrations/migrate.js:119:20)
fredy  |     at file:///fredy/index.js:35:7 {
fredy  |   code: 'SQLITE_CANTOPEN'
fredy  | }

@orangecoding
Copy link
Owner

I'll revert it

@rugk
Copy link
Contributor Author

rugk commented Oct 8, 2025

I was able to get it to work like this.
f0f1244

So no cache for the script yeah okay?

I don't get why it's different. I run it in a GitHub Codespace here (you can create your own above with the "Code" button next to the PR title) and I posted by exact command how it's run.

Do you maybe have an existing /db directory locally? In such a case maybe it also needs to be chowned chown -R 1000:1000 db?
Though the previous error was in a CI was not it?

@rugk
Copy link
Contributor Author

rugk commented Oct 8, 2025

Pushed a commit to https://github.com/rugk/fredy/tree/container/nonroot (rugk@14c22e3) to use an anonymous volume, though I see your test script also did that and thus should have no problem too. Anyway, maybe it helps.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature]: Make app run as non-root in container

2 participants