merge v1.10.2-booterm-glibc
This commit is contained in:
@@ -15,28 +15,45 @@ COPY apps/booterm ./apps/booterm
|
|||||||
RUN pnpm --filter=@boocode/booterm build
|
RUN pnpm --filter=@boocode/booterm build
|
||||||
|
|
||||||
# ---- Prod-deps stage: hoisted, native built via npm rebuild ----
|
# ---- Prod-deps stage: hoisted, native built via npm rebuild ----
|
||||||
FROM node:20-alpine AS proddeps
|
# v1.10.2: switched to bookworm-slim (glibc) so node-pty's native .node is
|
||||||
|
# compiled against the same libc as the runtime stage. A musl-built .node
|
||||||
|
# won't dlopen in a glibc node binary, so both stages must match.
|
||||||
|
FROM node:20-bookworm-slim AS proddeps
|
||||||
ENV COREPACK_DEFAULT_TO_LATEST=0
|
ENV COREPACK_DEFAULT_TO_LATEST=0
|
||||||
RUN corepack enable && corepack prepare pnpm@10.15.1 --activate
|
RUN corepack enable && corepack prepare pnpm@10.15.1 --activate
|
||||||
RUN apk add --no-cache python3 make g++
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
python3 make g++ ca-certificates \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
WORKDIR /prod
|
WORKDIR /prod
|
||||||
COPY apps/booterm/package.json ./package.json
|
COPY apps/booterm/package.json ./package.json
|
||||||
RUN pnpm install --prod --config.node-linker=hoisted --config.strict-peer-dependencies=false
|
RUN pnpm install --prod --config.node-linker=hoisted --config.strict-peer-dependencies=false
|
||||||
# pnpm 10 ignores build scripts; force compile with npm directly.
|
# pnpm 10 ignores build scripts; force compile with npm directly.
|
||||||
# node-gyp is bundled with npm in the node:20-alpine image.
|
# node-gyp is bundled with npm in the node:20-bookworm-slim image.
|
||||||
RUN cd node_modules/node-pty && npm run install
|
RUN cd node_modules/node-pty && npm run install
|
||||||
# Sanity check — fail the build if the artifact still isn't there
|
# Sanity check — fail the build if the artifact still isn't there
|
||||||
RUN test -f node_modules/node-pty/build/Release/pty.node && echo "pty.node OK" || (echo "pty.node MISSING" && exit 1)
|
RUN test -f node_modules/node-pty/build/Release/pty.node && echo "pty.node OK" || (echo "pty.node MISSING" && exit 1)
|
||||||
|
|
||||||
# ---- Runtime ----
|
# ---- Runtime ----
|
||||||
FROM node:20-alpine AS runtime
|
# v1.10.2: switched from node:20-alpine (musl) to node:20-bookworm-slim (glibc)
|
||||||
RUN apk add --no-cache tmux libstdc++ bash su-exec shadow
|
# so glibc-linked binaries from /home/samkintop (Claude Code, opencode, the
|
||||||
# v1.10.1: terminal shells inside tmux drop privs to samkintop via su-exec.
|
# host's nvm node) run inside the container when invoked from the terminal
|
||||||
|
# pane. Side-effect: su-exec is alpine-only — Debian replacement is gosu.
|
||||||
|
FROM node:20-bookworm-slim AS runtime
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
tmux bash gosu ca-certificates procps \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
# Mirror uid/gid 1000:1000 from the host so the bind-mounted /home/samkintop
|
# Mirror uid/gid 1000:1000 from the host so the bind-mounted /home/samkintop
|
||||||
# (added in docker-compose) is owned by the user from the container's view.
|
# (added in docker-compose) is owned by the user from the container's view.
|
||||||
RUN deluser --remove-home node 2>/dev/null; delgroup node 2>/dev/null; \
|
# bookworm-slim ships a `node` user at 1000 — wipe whatever sits on uid/gid
|
||||||
addgroup -g 1000 samkintop && \
|
# 1000 first, then create samkintop fresh.
|
||||||
adduser -D -u 1000 -G samkintop -s /bin/bash samkintop
|
RUN if id -u 1000 >/dev/null 2>&1; then \
|
||||||
|
userdel -r "$(id -un 1000)" 2>/dev/null || true; \
|
||||||
|
fi; \
|
||||||
|
if getent group 1000 >/dev/null 2>&1; then \
|
||||||
|
groupdel "$(getent group 1000 | cut -d: -f1)" 2>/dev/null || true; \
|
||||||
|
fi; \
|
||||||
|
groupadd -g 1000 samkintop && \
|
||||||
|
useradd -m -u 1000 -g 1000 -s /bin/bash samkintop
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY --from=builder /build/apps/booterm/dist ./dist
|
COPY --from=builder /build/apps/booterm/dist ./dist
|
||||||
COPY --from=proddeps /prod/package.json ./package.json
|
COPY --from=proddeps /prod/package.json ./package.json
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ set -g destroy-unattached off
|
|||||||
|
|
||||||
# v1.10.1: shells drop privs to samkintop (uid 1000) so the terminal runs in
|
# v1.10.1: shells drop privs to samkintop (uid 1000) so the terminal runs in
|
||||||
# the user's environment, not root. `env HOME=… USER=…` is required because
|
# the user's environment, not root. `env HOME=… USER=…` is required because
|
||||||
# su-exec only changes uid/gid — it leaves env intact, and tmux server runs
|
# gosu (and su-exec before it) only changes uid/gid — it leaves env intact,
|
||||||
# as root so HOME would otherwise be /root. bash -l then sources samkintop's
|
# and the tmux server runs as root so HOME would otherwise be /root. bash -l
|
||||||
# ~/.profile / ~/.bashrc to pick up PATH (nvm, ~/.local/bin, ~/.opencode/bin).
|
# then sources samkintop's ~/.profile / ~/.bashrc to pick up PATH (nvm,
|
||||||
set -g default-command "su-exec samkintop:samkintop env HOME=/home/samkintop USER=samkintop SHELL=/bin/bash bash -l"
|
# ~/.local/bin, ~/.opencode/bin).
|
||||||
|
# v1.10.2: su-exec → gosu (alpine → debian; functionally identical).
|
||||||
|
set -g default-command "gosu samkintop:samkintop env HOME=/home/samkintop USER=samkintop SHELL=/bin/bash bash -l"
|
||||||
|
|||||||
Reference in New Issue
Block a user