Skip to content

Commit d344dc4

Browse files
committed
chore(docker): pin Node and prep images for a read-only root filesystem
1 parent cf571cd commit d344dc4

3 files changed

Lines changed: 37 additions & 3 deletions

File tree

‎docker/app.Dockerfile‎

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,14 @@ FROM oven/bun:1.4.4-slim AS base
99
# `isolated-vm` pin in apps/sim/package.json — Node 24 (ABI 137) requires
1010
# isolated-vm 6.x.
1111
#
12+
# NODE_VERSION pins the exact NodeSource build: this layer is cached, so an
13+
# unpinned `nodejs` changed only when an unrelated edit forced a rebuild. The
14+
# `-1nodesource1` suffix selects the `nodejs` package, never `nsolid`, which
15+
# Provides `nodejs` at the same version numbers. build-base and deps inherit
16+
# this stage, so isolated-vm's node-gyp build targets the same Node (and ABI)
17+
# the runner executes it with.
18+
ARG NODE_VERSION=24.22.1
19+
#
1220
# Only what the running container needs belongs here. ffmpeg backs the media
1321
# subprocess adapter; python3 is the node-gyp interpreter and is kept because
1422
# build-base inherits from this stage. The compiler toolchain lives in build-base
@@ -24,7 +32,8 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
2432
apt-get update && apt-get install -y --no-install-recommends \
2533
python3 curl ca-certificates bash ffmpeg \
2634
&& curl -fsSL https://deb.nodesource.com/setup_24.x | bash - \
27-
&& apt-get install -y nodejs \
35+
&& apt-get install -y --no-install-recommends "nodejs=${NODE_VERSION}-1nodesource1" \
36+
&& [ "$(node --version)" = "v${NODE_VERSION}" ] \
2837
&& sed -i -E 's#^mozilla/(emSign_ECC_Root_CA_-_G3|Comodo_AAA_Services_root)\.crt$#!&#' /etc/ca-certificates.conf \
2938
&& update-ca-certificates \
3039
&& ! grep -qF -e 'l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3' -e 'CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD' /etc/ssl/certs/ca-certificates.crt
@@ -234,9 +243,20 @@ COPY --from=builder --chown=nextjs:nodejs /app/apps/sim/lib/execution/sandbox/bu
234243
# anonymizer, docker/pii.Dockerfile), reached over the network via PII_URL —
235244
# no Python/Presidio in this image.
236245

237-
# Create .next/cache directory with correct ownership
246+
# Writable paths for a read-only root filesystem. Declaring them as volumes
247+
# keeps writes working when the root is mounted read-only: ECS copies the
248+
# image's contents and ownership into a bind volume mounted at a VOLUME path.
249+
# - /tmp (mode 1777): os.tmpdir() scratch for ffmpeg and audio processing,
250+
# knowledge base imports, the Pi agent, and libvips (sharp) spill files.
251+
# - apps/sim/.next/cache: the Next image optimizer's disk cache
252+
# (.next/cache/images) and the data cache for `fetch` calls with
253+
# `next.revalidate`.
254+
# Keep the VOLUME line after every step that writes to these paths: the
255+
# classic builder discards later build-time changes to a declared volume.
238256
RUN mkdir -p apps/sim/.next/cache && \
239-
chown -R nextjs:nodejs apps/sim/.next/cache
257+
chown -R nextjs:nodejs apps/sim/.next/cache && \
258+
chmod 1777 /tmp
259+
VOLUME ["/tmp", "/app/apps/sim/.next/cache"]
240260

241261
# Switch to non-root user
242262
USER nextjs

‎docker/pii.Dockerfile‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,15 @@ RUN groupadd -g 1001 pii && \
4141
COPY --chown=pii:pii apps/pii/server.py ./
4242
COPY --chown=pii:pii --chmod=755 docker/pii-entrypoint.sh ./
4343

44+
# Read-only root filesystem prep. Python skips writing __pycache__ next to
45+
# server.py (site-packages is already byte-compiled by pip at install time),
46+
# and /tmp (mode 1777), Python's tempfile scratch, stays writable because ECS
47+
# copies the image's /tmp into a bind volume mounted at a VOLUME path. The
48+
# VOLUME line stays below the model download, which stages wheels in /tmp.
49+
ENV PYTHONDONTWRITEBYTECODE=1
50+
RUN chmod 1777 /tmp
51+
VOLUME ["/tmp"]
52+
4453
USER pii
4554

4655
# Listen on 5001. Runs as its own ECS service (separate task), reached via PII_URL;

‎docker/realtime.Dockerfile‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ RUN addgroup -g 1001 -S nodejs && \
4444
COPY --from=deps --chown=nextjs:nodejs /app ./
4545
COPY --from=pruner --chown=nextjs:nodejs /app/out/full/ ./
4646

47+
# /tmp stays writable under a read-only root filesystem: ECS copies the image's
48+
# /tmp (mode 1777) into a bind volume mounted at a VOLUME path.
49+
RUN chmod 1777 /tmp
50+
VOLUME ["/tmp"]
51+
4752
USER nextjs
4853

4954
EXPOSE 3002

0 commit comments

Comments
 (0)