Databases, Testing, and DeploymentLesson 6.5
Deploying Node.js to production: Docker and cloud platforms
Dockerfile for Node.js, .dockerignore, multi-stage builds, non-root user, docker-compose, environment variables in Docker, graceful shutdown, Render deployment
A Production Dockerfile
Always use multi-stage Docker builds for Node.js โ the final image contains only production dependencies and the app code, not devDependencies or build tools.
FROM node:20-alpine AS base
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
FROM node:20-alpine AS production
WORKDIR /app
COPY --from=base /app/node_modules ./node_modules
COPY . .
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
EXPOSE 3000
CMD ["node", "src/index.js"]Graceful Shutdown
const server = app.listen(config.PORT);
async function shutdown() {
logger.info('Shutting down gracefully...');
server.close(async () => {
await prisma.$disconnect();
logger.info('Shutdown complete');
process.exit(0);
});
}
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);Deploy to Render
Push your Dockerfile to GitHub. On Render: New โ Web Service โ Connect repo โ Runtime: Docker. Set environment variables in the dashboard. Render pulls the image, runs your container, and provides HTTPS automatically. For Railway the process is nearly identical โ connect the repo, set env vars, deploy.
