diff --git a/Dockerfile b/Dockerfile index a1597268..91904fdb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -46,13 +46,15 @@ COPY frontend/package*.json ./frontend/ # does not warn about a missing cert path; a proxy-inspected build still gets # the cert because the file is present. # Install the frontend dependencies. vite and the rest of the build toolchain -# live under devDependencies, so include them explicitly (--include=dev) in case -# the environment defaults npm to omit=dev. Behind an inspecting proxy (Zscaler) -# npm's many parallel fetches intermittently drop, and npm can even abort with -# "Exit handler never called", leaving an incomplete node_modules with no vite. -# Raise fetch retries/timeouts to ride out flaky connections, then hard-verify -# that the toolchain actually landed so the failure is loud and immediate here -# rather than a confusing "vite: not found" three steps later. +# live under devDependencies, so include them explicitly (--include=dev). +# Behind an inspecting proxy (Zscaler) each package fetch is slow (40-50s) and +# npm's default concurrency piles up parallel sockets that the proxy resets +# mid-stream, making npm abort with "Exit handler never called" and leaving an +# incomplete node_modules with no vite. Serializing to a single socket +# (maxsockets 1) lets every fetch complete; the retry loop and raised timeouts +# ride out any remaining transient reset, and the final test hard-verifies the +# toolchain landed so a truncated install fails loudly here rather than as a +# confusing "vite: not found" three steps later. RUN if [ -f /usr/local/share/ca-certificates/corp-root-ca.crt ]; then \ export NODE_EXTRA_CA_CERTS=/usr/local/share/ca-certificates/corp-root-ca.crt; \ fi; \ @@ -62,7 +64,10 @@ RUN if [ -f /usr/local/share/ca-certificates/corp-root-ca.crt ]; then \ npm config set fetch-retry-mintimeout 20000 && \ npm config set fetch-retry-maxtimeout 120000 && \ npm config set fetch-timeout 600000 && \ - npm ci --include=dev --no-audit --no-fund && \ + npm config set maxsockets 1 && \ + ( npm ci --include=dev --no-audit --no-fund \ + || { echo "npm ci attempt 1 failed, retrying..."; sleep 5; npm ci --include=dev --no-audit --no-fund; } \ + || { echo "npm ci attempt 2 failed, retrying..."; sleep 10; npm ci --include=dev --no-audit --no-fund; } ) && \ test -x node_modules/.bin/vite || { \ echo "ERROR: node_modules/.bin/vite missing after npm ci (proxy likely truncated the install)."; \ exit 1; \