Ctrl K
ComunidadGuías…

Dockerfile

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# ===========================================
# MynetworK - Node 22 Alpine (OPTIMIZED MULTI-STAGE)
# ===========================================
# Multi-arch: Buildx sets TARGETPLATFORM (amd64/arm64/arm/v7) per build.
# Builder uses TARGETPLATFORM so native modules (e.g. better-sqlite3) are compiled for the target arch.
ARG TARGETPLATFORM
ARG BUILDPLATFORM

# ---------- Stage 1: Build (with build tools) ----------
# Official node image via Google's Docker Hub mirror: Docker Hub rate-limits
# anonymous pulls per IP, which regularly fails CI on shared GitHub runners.
FROM mirror.gcr.io/library/node:22-alpine AS builder

WORKDIR /app

# Required build tools to compile better-sqlite3 and other native modules.
# These tools are not present in the final image.
RUN apk add --no-cache python3 make g++

# Install all dependencies (including devDependencies) only to compile native modules.
# devDependencies are removed in the final image (see npm prune --production below).
# Layer caching: package*.json rarely changes, so npm ci is cached across builds.
# Cache is keyed per TARGETPLATFORM to avoid ETXTBSY race between amd64/arm64 esbuild binaries.
COPY package*.json ./
ARG TARGETPLATFORM
RUN --mount=type=cache,target=/root/.npm,id=npm-${TARGETPLATFORM} npm ci

# Copy config files first (rarely change = better cache hits)
COPY tsconfig.json vite.config.ts index.html postcss.config.js tailwind.config.js ./

# Copy source and build
# Separate COPY for server and src to maximize layer reuse
COPY server ./server
COPY src ./src
COPY public ./public
COPY scripts ./scripts
RUN npm run build

# Prepare production node_modules (no devDependencies but with compiled binaries).
# Keep compiled better-sqlite3 binaries and remove only devDependencies.
# npm prune --production removes devDependencies but keeps compiled binaries.
RUN npm prune --production && npm cache clean --force


# ---------- Stage 2: Runtime (slim final image) ----------
# Re-declare so this stage gets Buildx TARGETPLATFORM (global ARG is not available after first FROM)
ARG TARGETPLATFORM
# Use TARGETPLATFORM so the runtime base matches the built arch (required for HA / Raspberry)
FROM mirror.gcr.io/library/node:22-alpine

WORKDIR /app

# Runtime tools only (no build tools).
# su-exec: required for entrypoint script (switch root → node).
# iputils-ping: required for network scan (ping command).
# iproute2: required for network scan (ip neigh for MAC detection).
# samba-common: provides nmblookup for NetBIOS/SMB hostname resolution.
# curl: required to download IEEE OUI vendor database from standards-oui.ieee.org (with plugin fallback on failure).
# Note: getent is not available on Alpine (musl libc); we use direct /etc/hosts reading.
# Note: libpcap/libpcap-dev removed as arp-scan is optional (fallback after ip neigh).
#       If arp-scan is needed, it must be compiled in the build stage.
# nmap: for port scanning (option "Scan ports after each full scan").
# arping: for direct ARP-based MAC address resolution (reliable in native and host network mode).
# Upgrade base packages first to fix known CVEs (e.g. zlib CVE-2026-27171)
RUN apk upgrade --no-cache && \
    apk add --no-cache su-exec iputils-ping iproute2 samba-common curl nmap arping

# Create data directory with correct permissions
RUN mkdir -p /app/data && chown -R node:node /app

# Copy entrypoint script (requires su-exec)
COPY docker-entrypoint.sh /app/docker-entrypoint.sh
RUN chmod +x /app/docker-entrypoint.sh

# Entrypoint to fix permissions on startup
ENTRYPOINT ["/app/docker-entrypoint.sh"]

# Copy compiled node_modules from build stage (native binaries already compiled).
# Avoids recompiling better-sqlite3 in the final image.
# Binaries are compiled for the target architecture in the build stage.
COPY --chown=node:node --from=builder /app/node_modules ./node_modules

# Copy package.json for reference (required by some dependencies)
COPY --chown=node:node package*.json ./

# Built frontend
COPY --chown=node:node --from=builder /app/dist ./dist

# Backend TypeScript (run by tsx)
COPY --chown=node:node --from=builder /app/server ./server
COPY --chown=node:node --from=builder /app/tsconfig.json ./

# CLI scripts (e.g. mcp-token.ts), run inside the container via
# `docker compose exec mynetwork node_modules/.bin/tsx scripts/mcp-token.ts`
# (npm is removed from the runtime image below, so tsx is invoked directly)
COPY --chown=node:node --from=builder /app/scripts ./scripts

ENV NODE_ENV=production
ENV PORT=3000
# FREEBOX_TOKEN_FILE and FREEBOX_HOST should be set at runtime via docker-compose or environment variables
# This avoids security warnings about sensitive data in Dockerfile

# Healthcheck with wget (already available in base Alpine)
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
 CMD wget -q --spider http://127.0.0.1:${PORT}/api/health || exit 1

EXPOSE 3000

# Remove npm/npx/corepack: unused at runtime (CMD invokes tsx directly, see below,
# and CLI scripts like mcp-token are run via tsx too, see README). Node's base image
# bundles npm with its own vendored deps (tar, brace-expansion, sigstore) that lag
# behind upstream fixes; dropping npm entirely removes that unused attack surface
# instead of waiting on a patched node:22-alpine.
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/lib/node_modules/corepack \
    /usr/local/bin/npm /usr/local/bin/npx /usr/local/bin/corepack

# TS runtime (tsx runs TypeScript files directly)
CMD ["node_modules/.bin/tsx", "server/index.ts"]