95 lines
3.5 KiB
Docker
95 lines
3.5 KiB
Docker
# Basado en el Dockerfile real de commerce-backend (Medusa v2 / Express).
|
|
# Multi-stage: build con devDependencies, runtime solo con lo necesario
|
|
# para correr -- sin compilador, sin devDependencies, sin npm/npx.
|
|
#
|
|
# ARGs a completar por tu app (todos tienen un default razonable):
|
|
# NODE_IMAGE -- versión exacta de Node. Fijala a una versión concreta
|
|
# (no "node:22-slim"), así un rebuild no te cambia la
|
|
# versión de Node por sorpresa un día cualquiera.
|
|
# APP_PORT -- puerto en el que tu app escucha.
|
|
# START_CMD -- cómo arrancar tu app en runtime. Por default invoca
|
|
# "node dist/index.js" -- CAMBIALO al entrypoint real de
|
|
# tu build. No uses "npm start"/"npx algo": el runtime
|
|
# de esta imagen NO tiene npm (ver más abajo, por qué).
|
|
|
|
# syntax=docker/dockerfile:1.7
|
|
|
|
ARG NODE_IMAGE=node:22.18.0-bookworm-slim
|
|
ARG APP_PORT=3000
|
|
|
|
#############################################################
|
|
# Builder
|
|
#############################################################
|
|
FROM ${NODE_IMAGE} AS builder
|
|
|
|
WORKDIR /app
|
|
|
|
ENV CI=true \
|
|
NODE_ENV=development \
|
|
NPM_CONFIG_UPDATE_NOTIFIER=false
|
|
|
|
COPY package.json package-lock.json* .npmrc* ./
|
|
|
|
# --legacy-peer-deps: sacalo si tu proyecto no lo necesita. Medusa v2 sí
|
|
# lo necesita hoy (conflictos de peer deps conocidos del ecosistema).
|
|
RUN --mount=type=cache,id=node-api-npm-cache,target=/root/.npm \
|
|
npm ci \
|
|
--legacy-peer-deps \
|
|
--prefer-offline \
|
|
--no-audit \
|
|
--no-fund
|
|
|
|
# CAMBIAR: copiá acá los archivos/carpetas fuente reales de tu app
|
|
# (tsconfig, src/, config específico). Estos son solo un ejemplo.
|
|
COPY tsconfig.json ./
|
|
COPY src ./src
|
|
|
|
RUN npm run build
|
|
|
|
RUN npm prune --omit=dev \
|
|
&& npm cache clean --force
|
|
|
|
#############################################################
|
|
# Runtime
|
|
#############################################################
|
|
FROM ${NODE_IMAGE}
|
|
|
|
ARG APP_PORT
|
|
ENV NODE_ENV=production \
|
|
PORT=${APP_PORT} \
|
|
NPM_CONFIG_UPDATE_NOTIFIER=false
|
|
|
|
# El CLI global de npm que trae la imagen base node:*-slim arrastra su
|
|
# propia copia de "tar" con historial de CVEs — no hace falta en
|
|
# runtime (nunca corrés npm/npx acá, solo "node algo.js"). Borrarlo
|
|
# reduce lo que Trivy tiene que escanear al set real que corre en
|
|
# producción.
|
|
#
|
|
# OJO si tu app usa un init container que corre "npx <algo>" contra
|
|
# esta misma imagen (ej. migraciones): eso se rompe si borrás npm acá.
|
|
# Cambiá ese comando a invocar el binario directo con "node", como el
|
|
# CMD de abajo — no vuelvas a agregar npm solo para eso.
|
|
RUN rm -rf /usr/local/lib/node_modules/npm
|
|
|
|
WORKDIR /app
|
|
|
|
# CAMBIAR: qué carpetas copiar del builder depende de tu build real
|
|
# (dist/, .output/, node_modules). Este ejemplo asume un build típico
|
|
# de tsc/esbuild a dist/ + node_modules de producción.
|
|
COPY --from=builder --chown=node:node /app/node_modules ./node_modules
|
|
COPY --from=builder --chown=node:node /app/dist ./dist
|
|
|
|
# La imagen base node:*-bookworm-slim ya trae un usuario "node" (uid
|
|
# 1000) sin privilegios -- no hace falta crear uno nuevo, a diferencia
|
|
# de nextjs.Dockerfile.
|
|
USER node
|
|
|
|
EXPOSE ${APP_PORT}
|
|
|
|
HEALTHCHECK --interval=30s --timeout=8s --start-period=20s --retries=3 \
|
|
CMD ["node", "-e", "fetch('http://127.0.0.1:' + (process.env.PORT || 3000) + '/health').then((r) => process.exit(r.ok ? 0 : 1)).catch(() => process.exit(1))"]
|
|
|
|
# CAMBIAR: el entrypoint real. Nunca "npm start"/"npx algo" -- ver nota
|
|
# de arriba sobre por qué npm no existe en esta imagen.
|
|
CMD ["node", "dist/index.js"]
|