brackt/Dockerfile
chrisp 08474631c1
Some checks failed
🚀 Deploy / 🧪 Test (push) Failing after 1m34s
🚀 Deploy / ʦ TypeScript (push) Successful in 1m23s
🚀 Deploy / 🔍 Lint (push) Successful in 49s
🚀 Deploy / 🐳 Build (push) Has been skipped
🚀 Deploy / 🚀 Deploy (push) Has been skipped
Optimize CI build pipeline (~15 min → ~3-5 min) (#59)
## Summary

- **Dockerfile layer caching**: `development-dependencies-env` now copies only `package.json`/`package-lock.json` before `npm ci` (was `COPY . /app`), so the npm install layer is cached on every code-only commit instead of rebuilt from scratch
- **Skip QEMU**: `platforms: linux/amd64` added to `build-push-action`, cutting `setup-buildx-action` from ~5 min to ~30 sec
- **npm cache in CI jobs**: Manual `actions/cache@v3` blocks (copy-pasted 3×) replaced with `actions/setup-node@v4` + `cache: 'npm'`, which handles path/key/restore automatically and pins Node 20 explicitly
- **Harden `.npmrc`**: Switched from `COPY .npmrc` to `--mount=type=secret,id=npmrc` in both `npm ci` stages — the file is available during install but never written into a Docker layer, so it cannot leak through the registry build cache regardless of future contents

## Expected timing

| Step | Before | After (code change) |
|---|---|---|
| Setup buildx | ~5 min | ~30 sec |
| Build + push | ~5 min | ~1-2 min |
| Deploy (docker pull) | ~5 min | ~1-2 min |
| **Total** | **~15 min** | **~3-5 min** |

## Test plan

- [ ] Push a code-only commit to main — confirm `setup-buildx-action` logs ~30s (no QEMU), Docker build shows `CACHED` for npm install layers, build+push completes in ~1-2 min
- [ ] Check deploy job — `docker compose pull` should show most layers as `Already exists`
- [ ] Push a commit that changes `package.json` — confirm npm layer correctly re-runs (not cached)
- [ ] Confirm deployed app is functional

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Chris Parsons <chrisparsons1127@gmail.com>
Reviewed-on: #59
2026-05-31 04:35:05 +00:00

26 lines
No EOL
879 B
Docker

FROM node:20-alpine AS development-dependencies-env
COPY package.json package-lock.json /app/
WORKDIR /app
RUN --mount=type=secret,id=npmrc,target=/app/.npmrc npm ci
FROM node:20-alpine AS production-dependencies-env
COPY ./package.json package-lock.json /app/
WORKDIR /app
RUN --mount=type=secret,id=npmrc,target=/app/.npmrc npm ci --omit=dev
FROM node:20-alpine AS build-env
COPY . /app/
COPY --from=development-dependencies-env /app/node_modules /app/node_modules
WORKDIR /app
RUN npm run build
FROM node:20-alpine
COPY ./package.json package-lock.json /app/
COPY --from=production-dependencies-env /app/node_modules /app/node_modules
COPY --from=build-env /app/build /app/build
COPY --from=build-env /app/dist /app/dist
COPY ./drizzle /app/drizzle
COPY ./scripts /app/scripts
COPY ./instrument.server.mjs /app/instrument.server.mjs
WORKDIR /app
CMD ["npm", "run", "start"]