todos-contra-el-fuego-web/Dockerfile
vjrj 197a59f641 fase 3: stack docker-compose local del sistema modernizado
Compose con los 5 servicios: mongo:7 (replica set rs0 + mongo-init one-shot),
redis (AOF), web Meteor 3.1 (Dockerfile multi-stage: builder debian con
meteor-tool 3.1 -> server-deps alpine -> runtime node:22-alpine), notifications
(dry-run) y node-red 4. Healthchecks (127.0.0.1, no localhost: busybox wget
prefiere IPv6 y Meteor escucha IPv4), restart unless-stopped, logging rotado
3x10MB, secretos montados desde ./secrets (gitignored, solo .example versionado).
.npmrc legacy-peer-deps para el ERESOLVE de las libs react viejas.

Validado: los 5 servicios healthy y smoke REST byte-identico (12/12) contra la
web dockerizada en :3200. RUNBOOK.md documenta arranque, smoke, backups y
rollback. No toca infra de Comunes.
2026-07-15 01:01:07 +02:00

47 lines
1.9 KiB
Docker

# Web Meteor 3.1 — imagen de producción (fase 3, Docker Compose).
#
# Multi-stage:
# 1. meteor-builder (debian/glibc): instala el meteor-tool y construye el bundle.
# 2. server-deps (alpine/musl): npm install de programs/server con toolchain
# nativa, sobre la MISMA libc que el runtime.
# 3. runtime (node:22-alpine): solo el bundle listo.
#
# Secretos: NUNCA en la imagen. El entrypoint carga METEOR_SETTINGS desde el
# fichero apuntado por METEOR_SETTINGS_FILE (montado por compose).
FROM node:22-bookworm AS meteor-builder
ENV METEOR_ALLOW_SUPERUSER=1
# Node 22 + Happy Eyeballs elige IPv6 sin ruta contra warehouse.meteor.com
# (mismo workaround que en dev, ver UPGRADE.md).
ENV NODE_OPTIONS="--dns-result-order=ipv4first --no-network-family-autoselection"
# python-is-python3: node-gyp 3.x (pulled by some Atmosphere npm deps) invokes
# `python`, absent on bookworm by default.
RUN apt-get update \
&& apt-get install -y --no-install-recommends curl ca-certificates python3 python-is-python3 make g++ git \
&& rm -rf /var/lib/apt/lists/*
RUN curl -fsSL "https://install.meteor.com/?release=3.1" | sh
WORKDIR /app
COPY . .
RUN meteor npm install
RUN meteor build /build --directory --server-only
FROM node:22-alpine AS server-deps
RUN apk add --no-cache python3 make g++
WORKDIR /bundle
COPY --from=meteor-builder /build/bundle .
RUN cd programs/server && npm install --omit=dev
FROM node:22-alpine
ENV NODE_ENV=production PORT=3000
WORKDIR /app
COPY --from=server-deps --chown=node:node /bundle .
COPY --chown=node:node docker/web-entrypoint.sh /web-entrypoint.sh
RUN chmod +x /web-entrypoint.sh
USER node
EXPOSE 3000
# 127.0.0.1 (not localhost): busybox wget resolves localhost to ::1 first, but
# the Meteor server listens on IPv4 only -> the check would false-negative.
HEALTHCHECK --interval=30s --timeout=5s --start-period=90s --retries=5 \
CMD wget -qO /dev/null "http://127.0.0.1:${PORT}/" || exit 1
ENTRYPOINT ["/web-entrypoint.sh"]
CMD ["node", "main.js"]