Conceptos básicos de Docker
10 ejemplos para contenerizar una API de Node.js con TypeScript en Node 24 LTS - 7 básicos y 3 intermedios.
Busca en todas las páginas de la documentación
10 ejemplos para contenerizar una API de Node.js con TypeScript en Node 24 LTS - 7 básicos y 3 intermedios.
mkdir node-api && cd node-api
npm init -y
npm pkg set type=module
npm install express@5
npm install -D typescript@5.6 tsx @types/express @types/nodePara patrones multi-etapa y endurecimiento de imágenes, consulta Construcciones multi-etapa y Contenedores sin root.
FROM node:24-bookworm-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY dist ./dist
ENV NODE_ENV=production
USER node
EXPOSE 3000
CMD ["node", "dist/main.js"]npm ci usa el archivo de bloqueo para instalaciones reproduciblespackage*.json antes del código fuente para que las capas de dependencias se almacenen bien en cachéUSER node ejecuta el proceso sin privilegios de root.dockerignorenode_modules
dist
.git
.env
.env.*
*.md
coverage
.vscode
Dockerfile*
docker-compose*.yml
docker build más rápido.env en una capa de imagenFROM node:24-bookworm-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY tsconfig.json ./
COPY src ./src
RUN npm run build
FROM node:24-bookworm-slim
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=build /app/dist ./dist
USER node
CMD ["node", "dist/main.js"]docker builddist/ y node_modules de producciónPORT desde el entornoimport express from "express";
const app = express();
const port = Number(process.env.PORT ?? 3000);
app.get("/health", (_req, res) => {
res.json({ status: "ok" });
});
app.listen(port, "0.0.0.0", () => {
console.log(`listening on ${port}`);
});0.0.0.0 dentro de los contenedores, no a 127.0.0.1PORTdocker build y docker rundocker build -t my-api:local .
docker run --rm -p 3000:3000 -e PORT=3000 my-api:local
curl http://localhost:3000/health-p 3000:3000 mapea el puerto del host al puerto del contenedor--rm elimina el contenedor después de salir (bueno para pruebas de humo locales)-e localmente; usa un gestor de secretos en producciónpackage.json para Docker{
"scripts": {
"build": "tsc",
"start": "node dist/main.js",
"docker:build": "docker build -t my-api:local .",
"docker:run": "docker run --rm -p 3000:3000 -e PORT=3000 my-api:local"
}
}npm run docker:build después de que pasen las pruebasstart como node simple, no tsx, en imágenes de producciónHEALTHCHECK en DockerfileHEALTHCHECK --interval=30s --timeout=3s --start-period=10s --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))"HEALTHCHECK/health rápido: sin llamadas a la base de datos (usa /ready para eso)FROM node:24-bookworm-slim AS base
WORKDIR /app
COPY package*.json ./
FROM base AS dev
RUN npm ci
COPY . .
CMD ["npx", "tsx", "watch", "src/main.ts"]
FROM base AS prod
RUN npm ci --omit=dev
COPY dist ./dist
USER node
CMD ["node", "dist/main.js"]docker build --target dev -t my-api:dev .
docker build --target prod -t my-api:prod .tsx watch) y producción--target selecciona la etapa finaldocker compose para la pila local# compose.yml
services:
api:
build: .
ports:
- "3000:3000"
environment:
NODE_ENV: development
PORT: 3000
DATABASE_URL: postgres://postgres:postgres@db:5432/app
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_PASSWORD: postgres
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
timeout: 3s
retries: 5depends_on con condition: service_healthy evita la condición de carrera al inicioFROM node:24-bookworm-slim@sha256:abc123def456...Por defecto, node:24-bookworm-slim (glibc). Alpine (musl) rompe algunos módulos npm nativos. Consulta Compensaciones de Distroless y Alpine.
Sí, para depurar problemas de imagen. CI construye imágenes; los desarrolladores aún se benefician de docker build y compose para pruebas de integración.
Ya sea en una etapa de construcción de Docker o en CI antes de docker build. No envíes tsx o typescript en imágenes de producción a menos que tengas una razón sólida.
Una API Express ligera suele ser de 150-250 MB. Si la tuya es de 800 MB o más, audita las capas con Reducción de tamaño de imagen.
Un proceso por contenedor. Ejecuta la API y los trabajadores en segundo plano como implementaciones separadas para que puedas escalarlos e implementarlos de forma independiente.
Variables de entorno de secretos del orquestador (Secretos de K8s, secretos de tareas de ECS, SSM). Nunca incorpores secretos en las capas de la imagen. Consulta ConfigMaps y Secretos.
USER node/health vs /readyVersiones de la pila: Esta página fue escrita para Node.js 24.18.0 (LTS activa), npm 10+, TypeScript 5.6+, Express 5, Fastify 5 y NestJS 11.
Revisado por Chris St. John·Última actualización: 19 jul 2026