#303 follow-up: the fonts volume must mount node-owned
All checks were successful
CI / Auth e2e pack (pull_request) Successful in 8m49s
CD / Build and push images (push) Successful in 14s
CD / Deploy to Test (push) Successful in 17s
CD / Smoke tests against Test (push) Successful in 1m21s
CD / Promote to Int (push) Successful in 12s
CI / Lint, typecheck, test (push) Successful in 6m35s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 8m30s
CI / Import/export fidelity gate (push) Successful in 57s
CI / Build container images (pull_request) Successful in 2m52s
CI / Lint, typecheck, test (pull_request) Successful in 6m28s
CI / Import/export fidelity gate (pull_request) Successful in 57s
All checks were successful
CI / Auth e2e pack (pull_request) Successful in 8m49s
CD / Build and push images (push) Successful in 14s
CD / Deploy to Test (push) Successful in 17s
CD / Smoke tests against Test (push) Successful in 1m21s
CD / Promote to Int (push) Successful in 12s
CI / Lint, typecheck, test (push) Successful in 6m35s
CI / Build container images (push) Has been skipped
CI / Auth e2e pack (push) Successful in 8m30s
CI / Import/export fidelity gate (push) Successful in 57s
CI / Build container images (pull_request) Successful in 2m52s
CI / Lint, typecheck, test (pull_request) Successful in 6m28s
CI / Import/export fidelity gate (pull_request) Successful in 57s
Found on the real deploy, not in any test: `/data/fonts` in the running api container was `root:root` and the non-root `node` user could not write to it. Every upload would have failed with EACCES at runtime while the api reported ready. The api Dockerfile already explains the mechanism for uploads and plugins — Docker copies an image directory's ownership into a fresh named volume on first mount — and pre-creates them chowned. #303 added `CUSTOM_FONTS_DIR` to the ENV but not to that mkdir/chown line. Adds a CI fence so it cannot recur: every `/data/…` path the api image defaults to must also appear in the mkdir AND the chown. Verified against the actual defect — removing `/data/fonts` from the chown makes it fail.
This commit is contained in:
parent
b96997501a
commit
485c8fa538
@ -107,6 +107,24 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# A fresh named volume inherits the ownership of the image directory it
|
||||||
|
# is mounted over. Every /data/… path the api image defaults to must
|
||||||
|
# therefore be pre-created AND chowned to `node`, or the non-root user
|
||||||
|
# cannot write to it — found on a real deploy in #303, where the env
|
||||||
|
# entry was added but the mkdir/chown line was not.
|
||||||
|
- name: api image pre-creates its data directories node-owned
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
dirs=$(grep -oE '[A-Z_]+_DIR=/data/[a-z]+' apps/api/Dockerfile | cut -d= -f2 | sort -u)
|
||||||
|
bad=0
|
||||||
|
for d in $dirs; do
|
||||||
|
grep -q "mkdir -p .*$d" apps/api/Dockerfile || {
|
||||||
|
echo "$d is not pre-created in apps/api/Dockerfile"; bad=1; }
|
||||||
|
grep -q "chown -R node:node .*$d" apps/api/Dockerfile || {
|
||||||
|
echo "$d is not chowned to node in apps/api/Dockerfile"; bad=1; }
|
||||||
|
done
|
||||||
|
exit "$bad"
|
||||||
|
|
||||||
- name: Set up pnpm
|
- name: Set up pnpm
|
||||||
uses: pnpm/action-setup@v4
|
uses: pnpm/action-setup@v4
|
||||||
|
|
||||||
|
|||||||
@ -34,13 +34,14 @@ WORKDIR /app
|
|||||||
COPY --from=build --chown=node:node /out /app
|
COPY --from=build --chown=node:node /out /app
|
||||||
# Generate the Prisma client for this image's platform.
|
# Generate the Prisma client for this image's platform.
|
||||||
RUN node node_modules/prisma/build/index.js generate
|
RUN node node_modules/prisma/build/index.js generate
|
||||||
# A fresh named volume mounted at /data/uploads or /data/plugins is created
|
# A fresh named volume mounted at /data/uploads, /data/plugins or /data/fonts
|
||||||
|
# is created
|
||||||
# root-owned; pre-creating them here (Docker copies an image directory's
|
# root-owned; pre-creating them here (Docker copies an image directory's
|
||||||
# ownership into a new volume on first mount) lets the non-root `node` user
|
# ownership into a new volume on first mount) lets the non-root `node` user
|
||||||
# write to them. /data/backups is mounted read-only here, but pre-creating it
|
# write to them. /data/backups is mounted read-only here, but pre-creating it
|
||||||
# node-owned keeps the shared `backups` volume writable for the backup
|
# node-owned keeps the shared `backups` volume writable for the backup
|
||||||
# sidecar even when the api container is the one that initializes it.
|
# sidecar even when the api container is the one that initializes it.
|
||||||
RUN mkdir -p /data/uploads /data/plugins /data/secrets /data/backups && chown -R node:node /data/uploads /data/plugins /data/secrets /data/backups
|
RUN mkdir -p /data/uploads /data/plugins /data/fonts /data/secrets /data/backups && chown -R node:node /data/uploads /data/plugins /data/fonts /data/secrets /data/backups
|
||||||
USER node
|
USER node
|
||||||
EXPOSE 3000
|
EXPOSE 3000
|
||||||
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
|
HEALTHCHECK --interval=30s --timeout=3s --retries=3 \
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user