Repository navigation
Expand file tree
/
Copy pathDockerfile
More file actions
34 lines (33 loc) · 1.69 KB
/
Copy pathDockerfile
File metadata and controls
34 lines (33 loc) · 1.69 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# node:22-alpine as of 2026-08-15 — node v22.23.2 on Alpine 3.24.1.
# Pinned by digest so two builds of the same git tag produce the same runtime,
# and so a `22-alpine` refresh cannot change musl/OpenSSL under a release that
# nothing re-tests. To move it deliberately:
# docker buildx imagetools inspect node:22-alpine | head -3
# and replace the digest in BOTH stages with the `Digest:` line it prints.
FROM node:22-alpine@sha256:c610fcdfb1d5b4740dd70c284ed3cb16bb857e0f7166196e36a5501df7a3aa32 AS build
WORKDIR /app
COPY package.json package-lock.json ./
# --ignore-scripts: no production dependency declares an install hook, so this
# costs nothing and keeps a compromised transitive from executing during the
# build that produces the shipped image. `npm run build` below is explicit.
RUN npm ci --ignore-scripts
COPY tsconfig.json ./
COPY src ./src
RUN npm run build
FROM node:22-alpine@sha256:c610fcdfb1d5b4740dd70c284ed3cb16bb857e0f7166196e36a5501df7a3aa32 AS runtime
WORKDIR /app
ENV NODE_ENV=production
ENV PORT=8080
COPY package.json package-lock.json ./
RUN npm ci --omit=dev --ignore-scripts && npm cache clean --force
RUN apk add --no-cache tini
COPY --from=build /app/dist ./dist
USER node
EXPOSE 8080
# Honoured by plain Docker, compose, and anything reading OCI healthcheck
# metadata. Azure App Service ignores it — configure its own "Health check"
# feature with path `/` there; see the self-hosting section of the README.
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD node -e "fetch('http://127.0.0.1:' + (process.env.PORT || 8080) + '/').then(r => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["node", "dist/main.js"]