Skip to content

Commit 8055730

Browse files
committed
feat: optimize Dockerfile — cache mounts, consolidate USER, provenance labels, remove github MCP
- Add # syntax=docker/dockerfile:1 for modern build features - Add --mount=type=cache for npm cache and node_modules (faster rebuilds) - Consolidate USER root/lpb switches (9 → 5, same behavior) - Add OCI provenance labels (IMAGE_REVISION, IMAGE_BUILT) - Update .dockerignore: exclude support/node_modules, *.tgz - Remove github MCP server (unattended auth issues)
1 parent 87d1809 commit 8055730

3 files changed

Lines changed: 42 additions & 29 deletions

File tree

.dockerignore

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ Thumbs.db
3131
# Biome
3232
biome.base.json
3333

34-
# Keep these:
35-
# Dockerfile
36-
# support/
37-
# lpb.stack.env
34+
# Local build artifacts
35+
support/node_modules
36+
*.tgz

.pi/mcp.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
{
2-
"mcpServers": {}
2+
"mcpServers": {
3+
"github": {
4+
"disabled": true
5+
}
6+
}
37
}

Dockerfile

Lines changed: 34 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
# syntax=docker/dockerfile:1
12
# ═══════════════════════════════════════════════════════════════════════════
23
# LOCALPIBOX DEVSTACK — MULTI-STAGE DOCKERFILE
34
# ═══════════════════════════════════════════════════════════════════════════
@@ -29,6 +30,10 @@ ARG PI_FORK=https://github.com/localpibox/pi.git
2930
ARG PI_REF=lpb
3031
ARG PI_HEAD_SHA=unknown
3132

33+
# Provenance — set via --build-arg in CI, defaults to "unknown" for local builds
34+
ARG IMAGE_REVISION=unknown
35+
ARG IMAGE_BUILT=unknown
36+
3237
# ═══════════════════════════════════════════════════════════════════════════
3338
# BASE STAGE — Common setup for both cli and web images
3439
# ═══════════════════════════════════════════════════════════════════════════
@@ -39,6 +44,8 @@ ARG VSCODIUM_VERSION
3944
ARG PI_FORK
4045
ARG PI_REF
4146
ARG PI_HEAD_SHA
47+
ARG IMAGE_REVISION
48+
ARG IMAGE_BUILT
4249

4350
ENV DEBIAN_FRONTEND=noninteractive
4451

@@ -48,6 +55,7 @@ ENV DEBIAN_FRONTEND=noninteractive
4855
ENV LPB_MAX_TOKENS_CONTEXT_RATIO=0.06
4956
ENV LPB_VERSION=
5057

58+
# ── System packages ─────────────────────────────────────────────────────────
5159
RUN apt-get update && apt-get install -y --no-install-recommends \
5260
build-essential pkg-config \
5361
curl ca-certificates gnupg \
@@ -57,11 +65,13 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
5765
gh ripgrep fzf fd-find tmux \
5866
&& rm -rf /var/lib/apt/lists/*
5967

68+
# ── Node.js ─────────────────────────────────────────────────────────────────
6069
RUN curl -fsSL https://deb.nodesource.com/setup_${NODE_VERSION}.x | bash - \
6170
&& apt-get install -y nodejs \
6271
&& npm install -g npm@latest \
6372
&& corepack enable
6473

74+
# ── User lpb (UID 1000) ────────────────────────────────────────────────────
6575
RUN set -eux; \
6676
if getent passwd 1000 >/dev/null; then \
6777
oldname="$(getent passwd 1000 | cut -d: -f1)"; \
@@ -79,7 +89,10 @@ RUN set -eux; \
7989

8090
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' > /etc/sudoers.d/nopasswd && chmod 440 /etc/sudoers.d/nopasswd
8191

82-
RUN set -eux; \
92+
# ── Global npm packages ─────────────────────────────────────────────────────
93+
# Cache mounted — persists downloaded tarballs across builds.
94+
RUN --mount=type=cache,target=/home/lpb/.npm \
95+
set -eux; \
8396
npm config set prefix '/home/lpb/.npm-global'; \
8497
npm config set fetch-retries 5; \
8598
npm config set fetch-retry-mintimeout 20000; \
@@ -88,12 +101,12 @@ RUN set -eux; \
88101
npm config set registry https://registry.npmjs.org/; \
89102
printf 'allow-scripts=better-sqlite3\nallow-scripts=agent-browser\nallow-scripts=esbuild\nallow-scripts=protobufjs\nallow-scripts=@google/genai\n' > /home/lpb/.npmrc; \
90103
npm install -g zod@3 agent-browser exa-mcp-server; \
91-
npm cache clean --force; \
92104
chown -R 1000:1000 /home/lpb/.npm-global
93105

94106
# ── Pi monorepo build ───────────────────────────────────────────────────────
95-
USER root
96-
RUN set -eux; \
107+
# Cache mounted — persists node_modules across builds when Pi source is unchanged.
108+
RUN --mount=type=cache,target=/opt/pi-src/node_modules \
109+
set -eux; \
97110
export PATH="/home/lpb/.npm-global/bin:${PATH}"; \
98111
mkdir -p /opt/pi-src && cd /opt/pi-src; \
99112
git clone --depth=1 --single-branch --branch ${PI_REF} ${PI_FORK} .; \
@@ -120,9 +133,11 @@ RUN set -eux; \
120133
ls -la /home/lpb/.npm-global/bin/; \
121134
rm -rf /opt/pi-src/.git /opt/pi-src/src /opt/pi-src/test /opt/pi-src/tests
122135

136+
# ── Switch to non-root user ─────────────────────────────────────────────────
137+
USER lpb
138+
123139
# ── Extensions + Config ─────────────────────────────────────────────────────
124140
# Config repo is cloned at container start by start.sh — the image stays lean.
125-
USER lpb
126141

127142
# ═══════════════════════════════════════════════════════════════════════════
128143
# CLI IMAGE
@@ -147,37 +162,29 @@ COPY --chmod=755 support/start.sh /opt/devstack/start.sh
147162
COPY lpb.conf.env /opt/devstack/lpb.conf.env
148163
COPY --chmod=755 support/entrypoint-cli.sh /opt/devstack/entrypoint-cli.sh
149164

150-
# Copy lpb-config to PATH (user-owned dir — no chmod issues)
165+
# ── Shell PATH helper ───────────────────────────────────────────────────────
151166
RUN mkdir -p /home/lpb/.local/bin
152167
COPY --chmod=755 support/lpb-config /home/lpb/.local/bin/lpb-config
153168

154-
# ─── Ownership (must run as root — COPY creates files as root) ───────────
169+
# ── Root operations: ownership + gitconfig + shell PATH ─────────────────────
155170
USER root
156171
RUN mkdir -p /home/lpb/.agent-browser/sessions \
157-
&& chown -R 1000:1000 /home/lpb /opt/devstack /opt/pi-support
158-
USER lpb
172+
&& chown -R 1000:1000 /home/lpb /opt/devstack /opt/pi-support \
173+
&& printf '[credential "https://github.com"]\n helper = !gh auth git-credential\n[credential "https://gist.github.com"]\n helper = !gh auth git-credential\n' > /home/lpb/.gitconfig \
174+
&& chown 1000:1000 /home/lpb/.gitconfig \
175+
&& printf '\n# LocalPibox: npm-global and local bin on PATH\nexport PATH="/home/lpb/.npm-global/bin:/home/lpb/.local/bin:${PATH}"\n' >> /home/lpb/.bashrc
159176

160-
# ─── Git credential helper ────────────────────────────────────────────
161-
# Points git to gh auth for GitHub HTTPS operations. No sensitive data
162-
# baked in — the actual token is resolved at runtime from
163-
# /home/lpb/.config/gh/hosts.yml (volume-mounted from host).
164-
USER root
165-
RUN printf '[credential "https://github.com"]\n helper = !gh auth git-credential\n[credential "https://gist.github.com"]\n helper = !gh auth git-credential\n' > /home/lpb/.gitconfig && chown 1000:1000 /home/lpb/.gitconfig
166177
USER lpb
167178

168-
# ─── Shell PATH (npm global bin, local bin) ──────────────────────────
169-
# Ensures agent-browser, pi, and other npm-global tools are on PATH
170-
# for all interactive and non-interactive shells.
171-
RUN printf '\n# LocalPibox: npm-global and local bin on PATH\nexport PATH="/home/lpb/.npm-global/bin:/home/lpb/.local/bin:${PATH}"\n' >> /home/lpb/.bashrc
172-
173-
USER lpb
174179
WORKDIR /home/lpb/workspace
175180

176181
LABEL org.opencontainers.image.title="LocalPibox Devstack — CLI" \
177182
org.opencontainers.image.description="AI-powered dev environment with Pi CLI (interactive terminal)" \
178183
org.opencontainers.image.source="https://github.com/localpibox/devstack" \
179184
org.opencontainers.image.vendor="LocalPibox" \
180-
org.opencontainers.image.licenses="MIT"
185+
org.opencontainers.image.licenses="MIT" \
186+
org.opencontainers.image.revision="${IMAGE_REVISION}" \
187+
org.opencontainers.image.created="${IMAGE_BUILT}"
181188

182189
ENTRYPOINT ["/opt/devstack/entrypoint-cli.sh"]
183190

@@ -195,7 +202,7 @@ RUN curl -fsSL \
195202
&& tar -xzf /tmp/vscodium.tar.gz -C /opt/vscodium --strip-components=1 \
196203
&& rm /tmp/vscodium.tar.gz
197204

198-
USER root
205+
# ── VSCodium extensions ─────────────────────────────────────────────────────
199206
RUN set -eux; \
200207
export PATH="/home/lpb/.npm-global/bin:${PATH}"; \
201208
EXT_DIR="/home/lpb/.vscodium-server/extensions"; \
@@ -224,6 +231,7 @@ COPY --chmod=755 support/entrypoint-web.sh /opt/devstack/entrypoint-web.sh
224231
RUN chown -R 1000:1000 /home/lpb
225232

226233
USER lpb
234+
227235
WORKDIR /home/lpb/workspace
228236

229237
ENV ED_PORT=3000
@@ -240,6 +248,8 @@ LABEL org.opencontainers.image.title="LocalPibox Devstack — Web" \
240248
org.opencontainers.image.description="AI-powered dev environment with VSCodium web editor" \
241249
org.opencontainers.image.source="https://github.com/localpibox/devstack" \
242250
org.opencontainers.image.vendor="LocalPibox" \
243-
org.opencontainers.image.licenses="MIT"
251+
org.opencontainers.image.licenses="MIT" \
252+
org.opencontainers.image.revision="${IMAGE_REVISION}" \
253+
org.opencontainers.image.created="${IMAGE_BUILT}"
244254

245255
ENTRYPOINT ["/opt/devstack/entrypoint-web.sh"]

0 commit comments

Comments
 (0)