From 554a4e5aa765cfaee2ebe927273b0a60d02f96da Mon Sep 17 00:00:00 2001 From: MouT Date: Sat, 30 May 2026 19:27:44 +0800 Subject: [PATCH 1/3] fix(deploy): move stage-2 asset copies into build stage Stage 2 COPY commands for skills, design-systems, craft, prompt-templates, assets, and plugins/_official previously read from the build context, which couples the Dockerfile to the repo root. Platforms like Railway that require the Dockerfile directory to equal the build context could not find these paths. Move the asset directories into the build stage and let Stage 2 pull them via --from=build, so the Dockerfile is fully self-contained and works from any context directory. --- deploy/Dockerfile | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 14e9f07f2..ffced3af9 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -66,6 +66,18 @@ RUN pnpm --filter @open-design/daemon build && \ -name "binding.gyp" \ \) -delete +# Stage-2 assets — copied into the build stage so the runtime stage +# can pull them via --from=build instead of reaching back into the +# build context. This lets the Dockerfile work when the build context +# differs from the repo root (Railway, CI runners with a subdirectory +# context, etc.). +COPY skills ./skills +COPY design-systems ./design-systems +COPY craft ./craft +COPY prompt-templates ./prompt-templates +COPY assets ./assets +COPY plugins/_official ./plugins/_official + FROM ${RUNTIME_IMAGE} RUN apk add --no-cache tini poppler-utils && \ @@ -75,18 +87,18 @@ RUN apk add --no-cache tini poppler-utils && \ WORKDIR /app COPY --from=build --chown=open-design:open-design /app/deploy/daemon ./apps/daemon COPY --from=build --chown=open-design:open-design /app/apps/web/out ./apps/web/out -COPY --chown=open-design:open-design skills ./skills -COPY --chown=open-design:open-design design-systems ./design-systems -COPY --chown=open-design:open-design craft ./craft -COPY --chown=open-design:open-design prompt-templates ./prompt-templates -COPY --chown=open-design:open-design assets/frames ./assets/frames -COPY --chown=open-design:open-design assets/community-pets ./assets/community-pets +COPY --from=build --chown=open-design:open-design /app/skills ./skills +COPY --from=build --chown=open-design:open-design /app/design-systems ./design-systems +COPY --from=build --chown=open-design:open-design /app/craft ./craft +COPY --from=build --chown=open-design:open-design /app/prompt-templates ./prompt-templates +COPY --from=build --chown=open-design:open-design /app/assets/frames ./assets/frames +COPY --from=build --chown=open-design:open-design /app/assets/community-pets ./assets/community-pets # Plan §3.J4 / spec §23.3.5 — bundled atom plugins registered on # daemon boot. The directory contains `plugins/_official/atoms//` # pairs (SKILL.md + open-design.json); registerBundledPlugins() walks # it on startup so the container ships with first-party atoms reachable # via the same registry path third-party plugins use. -COPY --chown=open-design:open-design plugins/_official ./plugins/_official +COPY --from=build --chown=open-design:open-design /app/plugins/_official ./plugins/_official RUN mkdir -p /app/.od && \ chown -R open-design:open-design /app From f32655d9c2e9ae6a1695ef248c3db450b0b4af7c Mon Sep 17 00:00:00 2001 From: MouT Date: Sat, 30 May 2026 21:32:36 +0800 Subject: [PATCH 2/3] fix(deploy): chown volume at runtime so containers work with root-owned mounts Platforms like Railway mount volumes as root, which overrides the build-time chown on /app/.od. Run the container as root with tini, chown the volume directory on start, then drop privileges to the open-design user via su-exec before launching the daemon. --- deploy/Dockerfile | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index ffced3af9..63ff97f0f 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -80,7 +80,7 @@ COPY plugins/_official ./plugins/_official FROM ${RUNTIME_IMAGE} -RUN apk add --no-cache tini poppler-utils && \ +RUN apk add --no-cache tini su-exec poppler-utils && \ addgroup -S -g 1001 open-design && \ adduser -S -D -H -u 1001 -G open-design open-design @@ -110,6 +110,8 @@ ENV OD_PORT=7456 EXPOSE 7456 -USER open-design +# Stay as root so the entrypoint can fix volume permissions (Railway +# and similar platforms mount volumes as root). Privileges are dropped +# to open-design right before the daemon starts. ENTRYPOINT ["/sbin/tini", "--"] -CMD ["node", "apps/daemon/dist/cli.js", "--no-open"] +CMD ["sh", "-c", "chown -R open-design:open-design /app/.od 2>/dev/null || true && exec su-exec open-design node apps/daemon/dist/cli.js --no-open"] From dfd883dcb34858403f8f286d71bef4131bb9bc84 Mon Sep 17 00:00:00 2001 From: MouT Date: Sat, 30 May 2026 21:43:27 +0800 Subject: [PATCH 3/3] Revert "fix(deploy): chown volume at runtime so containers work with root-owned mounts" This reverts commit f32655d9c2e9ae6a1695ef248c3db450b0b4af7c. --- deploy/Dockerfile | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/deploy/Dockerfile b/deploy/Dockerfile index 63ff97f0f..ffced3af9 100644 --- a/deploy/Dockerfile +++ b/deploy/Dockerfile @@ -80,7 +80,7 @@ COPY plugins/_official ./plugins/_official FROM ${RUNTIME_IMAGE} -RUN apk add --no-cache tini su-exec poppler-utils && \ +RUN apk add --no-cache tini poppler-utils && \ addgroup -S -g 1001 open-design && \ adduser -S -D -H -u 1001 -G open-design open-design @@ -110,8 +110,6 @@ ENV OD_PORT=7456 EXPOSE 7456 -# Stay as root so the entrypoint can fix volume permissions (Railway -# and similar platforms mount volumes as root). Privileges are dropped -# to open-design right before the daemon starts. +USER open-design ENTRYPOINT ["/sbin/tini", "--"] -CMD ["sh", "-c", "chown -R open-design:open-design /app/.od 2>/dev/null || true && exec su-exec open-design node apps/daemon/dist/cli.js --no-open"] +CMD ["node", "apps/daemon/dist/cli.js", "--no-open"]