Node.js Hello World:npm 与 Docker 打包
验证:未记录
- 适用版本
- 未记录
- 验证范围
- 尚未登记验证记录。
本文缩写(英文全称与中文含义)
| 缩写 | 英文全称/名称 | 中文含义 |
|---|---|---|
| CPU | Central Processing Unit | 中央处理器 |
| HTTP | Hypertext Transfer Protocol | 超文本传输协议 |
| npm | npm package manager | Node.js 常用包管理器的名称,并非需强行展开的正式缩写 |
目标:使用 npm 安装 Express,打包 HTTP 服务并验证。需要 Docker、Node.js 24/npm 和 curl;命令在 Bash 中执行。完整进阶配置见 Dockerfile 专题。
1. 创建项目与依赖#
mkdir node-hello
cd node-hello
npm init -y
npm pkg set private=true --json
npm pkg set scripts.start='node server.js'
npm install --save-exact express@5生成 package.json、package-lock.json 和 node_modules/。前两个文件提交 Git;node_modules/ 不提交。--save-exact 固定本次安装的 Express 版本,完整依赖树由 lockfile 锁定。
保存 server.js:
const express = require('express');
const app = express();
app.disable('x-powered-by');
app.get('/', (_req, res) => res.type('text').send('Hello World from Node.js!\n'));
app.get('/healthz', (_req, res) => res.type('text').send('ok\n'));
const server = app.listen(3000, '0.0.0.0', () => {
console.log('listening on :3000');
});
let stopping = false;
function shutdown() {
if (stopping) return;
stopping = true;
const timer = setTimeout(() => process.exit(1), 5000);
timer.unref();
server.close((err) => {
clearTimeout(timer);
process.exit(err ? 1 : 0);
});
}
process.on('SIGTERM', shutdown);
process.on('SIGINT', shutdown);本机可先执行 npm start,另一个终端 curl 验证,随后 Ctrl+C 停止。
2. Dockerfile 与忽略文件#
保存 Dockerfile:
# syntax=docker/dockerfile:1
FROM node:24-bookworm-slim AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci --omit=dev && npm cache clean --force
FROM node:24-bookworm-slim AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY --from=deps --chown=node:node /app/node_modules ./node_modules
COPY --chown=node:node package.json package-lock.json server.js ./
USER node
EXPOSE 3000
CMD ["node", "server.js"]npm install 用于添加/更新依赖;镜像中 npm ci 严格按 lockfile 安装,不匹配就失败。先复制依赖文件可复用缓存;使用 node 直接作为主进程接收停止信号。纯 JavaScript 本例无需 npm run build;TypeScript 需要额外编译阶段,见 TypeScript Dockerfile。
保存 .dockerignore:
node_modules
.git
.env
.env.*
.npmrc
coverage
npm-debug.log不复制宿主机的 node_modules,避免 macOS/Linux 或 CPU 架构不一致。私有 npm token 使用 BuildKit secret,不能写进 Dockerfile。
3. 构建、运行与验证#
docker build -t node-hello:local .
docker run -d --name node-hello --read-only --cap-drop=ALL --security-opt=no-new-privileges:true -p 127.0.0.1:3000:3000 node-hello:local
curl --fail --retry 10 --retry-connrefused --retry-delay 1 http://127.0.0.1:3000/
curl --fail http://127.0.0.1:3000/healthz
docker logs node-hello预期分别返回 Hello World from Node.js! 和 ok。如宿主机端口冲突,将 -p 改成 127.0.0.1:3001:3000,curl 同步改为 3001。
4. 停止与清理#
docker stop --timeout 10 node-hello
docker inspect node-hello --format '{{.State.ExitCode}}'
docker rm node-hello
docker image rm node-hello:local正常退出码为 0。本例以 Hello World 演示完整打包链路;正式交付还需测试、镜像扫描、资源限制及基础镜像 digest 固定。