1+ # syntax=docker/dockerfile:1
12ARG BASE_CONTAINER=node:22-alpine
23
4+ # ============================================================================
5+ # Builder Stage: Install dependencies and build package
6+ # ============================================================================
37FROM $BASE_CONTAINER AS builder
48
9+ # Enable corepack for pnpm support
10+ RUN corepack enable
11+
12+ ENV PNPM_HOME="/pnpm" \
13+ PATH="$PNPM_HOME:$PATH"
14+
15+ WORKDIR /build
16+
17+ # Copy dependency manifests first for better layer caching
18+ COPY package.json pnpm-lock.yaml ./
19+
20+ # Use BuildKit cache mount for pnpm store (faster rebuilds)
21+ # Fetch dependencies into cache
22+ RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
23+ pnpm fetch --frozen-lockfile
24+
25+ # Install production dependencies offline from cache
26+ RUN --mount=type=cache,id=pnpm,target=/pnpm/store \
27+ pnpm install --frozen-lockfile --prod --offline --ignore-scripts
28+
29+ # Copy source code (sensitive files excluded via .dockerignore: .git, .env, coverage, node_modules, etc.)
30+ COPY . .
31+
32+ # Build and pack
33+ RUN pnpm run prepack && \
34+ pnpm pack && \
35+ mv mitre-saf-*.tgz saf.tgz
36+
37+ # ============================================================================
38+ # Runtime Stage: Minimal production image
39+ # ============================================================================
40+ FROM $BASE_CONTAINER AS app
41+
42+ # Metadata labels in final stage
543LABEL name="SAF" \
644 vendor="The MITRE Corporation" \
745 version="${SAF_VERSION}" \
@@ -11,24 +49,19 @@ LABEL name="SAF" \
1149 docs="https://github.com/mitre/saf" \
1250 run="docker run -d --name ${NAME} ${IMAGE} <args>"
1351
14- RUN mkdir -p /share
15-
16- COPY . /build
17- WORKDIR /build
18- RUN rm -rf test
19- RUN npm ci --omit=dev --fetch-timeout=600000
20- RUN mv "$(npm pack | tail -1)" saf.tgz
21-
22- FROM $BASE_CONTAINER AS app
23-
24- COPY --from=builder /build/saf.tgz /build/
25- RUN npm install -g /build/saf.tgz && npm cache clean --force;
26-
27- # Useful for CI pipelines
52+ # Install runtime utilities (--no-cache prevents cache creation)
2853RUN apk add --no-cache bash jq curl ca-certificates yq
2954
55+ # Copy and install packaged CLI
56+ COPY --from=builder /build/saf.tgz /tmp/
57+ RUN npm install -g /tmp/saf.tgz --ignore-scripts && \
58+ npm cache clean --force && \
59+ rm /tmp/saf.tgz
60+
61+ # Run as non-root user
3062USER node
3163
32- ENTRYPOINT ["saf" ]
33- VOLUME ["/share" ]
3464WORKDIR /share
65+ VOLUME ["/share" ]
66+
67+ ENTRYPOINT ["saf" ]
0 commit comments