|
1 | 1 | # syntax=docker/dockerfile:1.7 |
2 | 2 |
|
3 | | -# ---------- Base dependencies ---------- |
4 | | -FROM node:22-bookworm-slim AS base |
| 3 | +ARG NODE_IMAGE=node:22-bookworm-slim |
| 4 | + |
| 5 | +# ---------- Base image with tooling ---------- |
| 6 | +FROM ${NODE_IMAGE} AS base |
5 | 7 |
|
6 | | -# set workdir and install common deps |
7 | 8 | WORKDIR /app |
| 9 | + |
8 | 10 | RUN --mount=type=cache,target=/var/cache/apt \ |
9 | 11 | apt-get update \ |
10 | | - && apt-get install -y --no-install-recommends ca-certificates curl git tini openssl \ |
| 12 | + && apt-get install -y --no-install-recommends ca-certificates curl git openssh-client tini \ |
11 | 13 | && rm -rf /var/lib/apt/lists/* |
12 | 14 |
|
13 | 15 | # Use Corepack to pin Yarn deterministically |
14 | 16 | ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 |
15 | 17 | RUN corepack enable && corepack prepare [email protected] --activate |
16 | 18 |
|
17 | | -# ---------- Dependencies layer ---------- |
18 | | -FROM base AS deps |
19 | | - |
20 | | -# Copy package manager files |
21 | | -COPY package.json yarn.lock ./ |
22 | | - |
23 | | -# IMPORTANT: skip lifecycle scripts here (prevents running prepare/build before sources exist) |
24 | | -# RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \ |
25 | | -# yarn install --frozen-lockfile --ignore-scripts |
| 19 | +# ---------- Builder ---------- |
| 20 | +FROM base AS build |
26 | 21 |
|
27 | | -# Disable optional deps (argon2 has native build, still install) |
28 | | -RUN yarn install --frozen-lockfile |
| 22 | +ARG BUILD_SHA=dev |
| 23 | +ARG BUILD_TAG=local |
29 | 24 |
|
30 | | -# ---------- Build layer ---------- |
31 | | -FROM deps AS build |
32 | | - |
33 | | -# Reuse node_modules from deps |
34 | | -COPY --from=deps /app/node_modules ./node_modules |
35 | | -# Bring in source (exclude by .dockerignore later) |
| 25 | +# Install dependencies (cached). Force dev deps to be present even though we later build for production. |
| 26 | +COPY package.json yarn.lock ./ |
36 | 27 | COPY . . |
| 28 | +RUN --mount=type=cache,target=/usr/local/share/.cache/yarn \ |
| 29 | + NODE_ENV=development yarn install --frozen-lockfile |
37 | 30 |
|
38 | | -# Generate prisma client & build sources |
39 | | -RUN yarn prisma generate \ |
40 | | - && yarn build |
| 31 | +# Prepare Prisma schema, migrations, seeds (writes sqlite DB under /app/data) |
| 32 | +ENV NODE_ENV=production |
| 33 | +ENV DATABASE_URL=file:/app/data/sovereign.db |
| 34 | +RUN mkdir -p /app/data \ |
| 35 | + && yarn prepare:all |
41 | 36 |
|
42 | | -# ---------- Production runtime ---------- |
43 | | -FROM node:22-bookworm-slim AS runtime |
| 37 | +# Build workspaces and manifest/openapi (prebuild hook regenerates manifest) |
| 38 | +RUN NODE_ENV=production yarn build |
44 | 39 |
|
| 40 | +# ---------- Runtime ---------- |
| 41 | +FROM ${NODE_IMAGE} AS runtime |
| 42 | +ARG BUILD_SHA=dev |
| 43 | +ARG BUILD_TAG=local |
45 | 44 | WORKDIR /app |
| 45 | + |
46 | 46 | ENV NODE_ENV=production |
47 | | -ENV PORT=5000 |
| 47 | +ENV PORT=4000 |
48 | 48 | ENV DATABASE_URL="file:/app/data/sovereign.db" |
49 | 49 |
|
50 | | -# Corepack for Yarn in runtime too (optional if you don't use yarn here) |
| 50 | +# Corepack for runtime (keeps Yarn available for scripts) |
51 | 51 | ENV COREPACK_ENABLE_DOWNLOAD_PROMPT=0 |
52 | | -RUN corepack enable && corepack prepare [email protected] --activate |
53 | | - |
54 | | -# Bring built app and prisma **artifacts** (client + engine) from build |
55 | | -# Copy the platform app since the runtime entry is /platform/index.cjs |
56 | | -COPY --from=build /app/platform ./platform |
57 | | -COPY --from=build /app/prisma ./prisma |
58 | | - |
59 | | -# Copy Prisma client output generated during build (so we don't need prisma CLI now) |
60 | | -COPY --from=build /app/node_modules/@prisma ./node_modules/@prisma |
61 | | -COPY --from=build /app/node_modules/.prisma ./node_modules/.prisma |
| 52 | +RUN --mount=type=cache,target=/var/cache/apt \ |
| 53 | + apt-get update \ |
| 54 | + && apt-get install -y --no-install-recommends ca-certificates tini \ |
| 55 | + && rm -rf /var/lib/apt/lists/* \ |
| 56 | + && corepack enable && corepack prepare [email protected] --activate |
62 | 57 |
|
63 | | -# Copy node_modules from build (matches built artifacts and avoids registry lookups) |
64 | | -COPY --from=build /app/node_modules ./node_modules |
| 58 | +LABEL org.opencontainers.image.revision="${BUILD_SHA}" \ |
| 59 | + org.opencontainers.image.version="${BUILD_TAG}" |
65 | 60 |
|
66 | | -# Copy build artifacts and required folders |
| 61 | +# Copy built artifacts and runtime assets |
67 | 62 | COPY --from=build /app/package.json ./package.json |
| 63 | +COPY --from=build /app/yarn.lock ./yarn.lock |
| 64 | +COPY --from=build /app/node_modules ./node_modules |
| 65 | +COPY --from=build /app/platform ./platform |
| 66 | +COPY --from=build /app/plugins ./plugins |
| 67 | +COPY --from=build /app/tools ./tools |
| 68 | +COPY --from=build /app/data ./data |
| 69 | +COPY --from=build /app/platform/prisma ./prisma |
| 70 | +COPY --from=build /app/manifest.json ./manifest.json |
| 71 | +COPY --from=build /app/openapi.json ./openapi.json |
68 | 72 |
|
69 | | -# Prepare persistent data directory for sqlite |
70 | | -RUN mkdir -p /app/data \ |
71 | | - && chown node:node /app/data |
| 73 | +VOLUME ["/app/data"] |
72 | 74 |
|
73 | | -# Copy entrypoint script |
| 75 | +# Entry + runtime prep |
74 | 76 | COPY docker/entrypoint.sh /entrypoint.sh |
75 | | -RUN chmod +x /entrypoint.sh |
| 77 | +RUN chmod +x /entrypoint.sh \ |
| 78 | + && mkdir -p /app/data \ |
| 79 | + && chown -R node:node /app/data |
76 | 80 |
|
77 | 81 | USER node |
78 | 82 |
|
79 | | -EXPOSE 5000 |
| 83 | +EXPOSE 4000 |
80 | 84 |
|
81 | 85 | ENTRYPOINT ["/usr/bin/tini", "--", "/entrypoint.sh"] |
82 | 86 | CMD ["node", "platform/index.cjs"] |
0 commit comments