基于 Docker 开发 NodeJS 应用
本文介绍如何在 Docker 容器中搭建 Node.js 开发环境。通过配置 Dockerfile 整合 Node 与 Redis,利用命令行参数实现端口映射与代码热更新,演示从镜像构建到本地调试的完整流程,并指出当前配置在数据持久化方面的局限性。
应用基础结构
关于这个 Node 应用
该应用由三个基础文件组成:package.json、server.js 以及 .gitignore,结构简洁明了。
.gitignore
node_modules/*
package.json
{
"name": "docker-dev",
"version": "0.1.0",
"description": "Docker Dev",
"dependencies": {
"connect-redis": "~1.4.5",
"express": "~3.3.3",
"hiredis": "~0.1.15",
"redis": "~0.8.4"
}
}
server.js
var express = require('express'),
app = express(),
redis = require('redis'),
RedisStore = require('connect-redis')(express),
server = require('http').createServer(app);
app.configure(function() {
app.use(express.cookieParser('keyboard-cat'));
app.use(express.session({
store: new RedisStore({
host: process.env.REDIS_HOST || 'localhost',
port: process.env.REDIS_PORT || 6379,
db: process.env.REDIS_DB || 0
}),
cookie: {
expires: false,
maxAge: 30 * 24 * 60 * 60 * 1000
}
}));
});
app.get('/', function(req, res) {
res.json({
status: "ok"
});
});
var port = process.env.HTTP_PORT || 3000;
server.listen(port);
console.log('Listening on port ' + port);
server.js 负责加载所有依赖项并启动应用。该应用将会话信息存储至 Redis,并提供一个返回 JSON 状态消息的请求端点。这是非常标准的实现方式。
需要注意的是,Redis 的连接信息可以通过环境变量进行覆盖——这将在后续从开发环境 dev 迁移到生产环境 prod 时发挥关键作用。
Dockerfile 配置解析
Docker file
为了满足开发需求,我们将 Redis 和 Node 运行在同一个容器中。为此,我们使用 Dockerfile 来配置该容器。
Dockerfile
FROM dockerfile/ubuntu
MAINTAINER Abhinav Ajgaonkar <abhinav316@gmail.com>
# Install Redis
RUN \
apt-get -y -qq install python redis-server
# Install Node
RUN \
cd /opt && \
wget http://nodejs.org/dist/v0.10.28/node-v0.10.28-linux-x64.tar.gz && \
tar -xzf node-v0.10.28-linux-x64.tar.gz && \
mv node-v0.10.28-linux-x64 node && \
cd /usr/local/bin && \
ln -s /opt/node/bin/* . && \
rm -f /opt/node-v0.10.28-linux-x64.tar.gz
# Set the working directory
WORKDIR /src
CMD ["/bin/bash"]
我们将逐行解析其内容。
FROM dockerfile/ubuntu 这指示 Docker 使用 Docker Inc. 提供的 dockerfile/ubuntu 镜像作为构建基准。
RUN \ apt-get -y -qq install python redis-server 基准镜像未包含任何内容,因此我们需要使用 apt-get 获取应用运行所需的所有组件。此命令将安装 python 和 redis-server。Redis 服务器是必需的,因为我们将会话信息存储在其中;而安装 python 则是为了通过 npm 构建 Redis node 模块所需的 C 扩展。
RUN \
cd /opt && \
wget http://nodejs.org/dist/v0.10.28/node-v0.10.28-linux-x64.tar.gz && \
tar -xzf node-v0.10.28-linux-x64.tar.gz && \
mv node-v0.10.28-linux-x64 node && \
cd /usr/local/bin && \
ln -s /opt/node/bin/* . && \
rm -f /opt/node-v0.10.28-linux-x64.tar.gz
此步骤下载并解压 64 位 NodeJS 二进制文件。
WORKDIR /src
此命令指示 Docker 在容器启动并执行 CMD 属性指定的内容之前,先执行 cd /src。
CMD ["/bin/bash"]
最后一步是运行 /bin/bash。
构建与运行容器
构建并运行容器
现在 Dockerfile 已编写完毕,让我们构建一个 Docker 镜像。
docker build -t sqldump/docker-dev:0.1 .
镜像构建完成后,我们可以使用以下命令运行容器:
docker run -i -t --rm \
-p 3000:3000 \
-v `pwd`:/src \
sqldump/docker-dev:0.1
让我们分析 docker 运行命令中的各个参数。
-i 以交互模式启动容器(与 -d 分离模式相对)。这意味着一旦交互会话结束,容器将退出。
-t 分配一个伪终端(pseudo-tty)。
--rm 在容器退出时移除容器及其文件系统。
-p 3000:3000 将主机上的端口 3000 转发到容器内的端口 3000。
-v `pwd`:/src 此命令将当前工作目录(即我们的项目文件)挂载到容器内的 /src 中。我们将当前目录作为卷挂载,而不是使用 Dockerfile 中的 ADD 命令,这样我们在文本编辑器中进行的任何修改都可以立即在容器中生效。
sqldump/docker-dev:0.1 是要运行的 Docker 镜像的名称和版本——这与我们构建 Docker 镜像时使用的名称和版本相同。
由于 Dockerfile 指定了 CMD ["/bin/bash"],容器启动后我们将登录到 bash shell 环境。如果 docker 运行命令执行成功,输出将如下所示:

开发环境调试流程
开始开发
现在容器正在运行,在开始编写代码之前,我们需要整理一些标准的、非 Docker 相关的内容。首先,使用以下命令启动容器内的 Redis 服务器:
service redis-server start
然后,安装项目依赖和 nodemon。Nodemon 会监控项目文件中的更改,并在适当时重启服务器。
npm install
npm install -g nodemon
最后,使用如下命令启动服务器:
nodemon server.js
现在,如果你在浏览器中导航到 http://localhost:3000,你应该会看到如下内容:

让我们向 Server.js 中添加另一个端点,以模拟开发流程:
app.get('/hello/:name', function(req, res) {
res.json({
hello: req.params.name
});
});
你会看到 nodemon 已检测到你所做的修改,并重启了服务器:

现在,如果你将浏览器导航到 http://localhost:3000/hello/world,你将看到如下响应:

生产环境注意事项
生产环境
当前状态下的容器还远不能作为产品发布。Redis 中的数据在容器重启时不会保持持久化,例如,如果你重启了容器,所有会话数据都将丢失。同样的情况也发生在你销毁容器并开启新容器时,这显然不是我们想要的。我将在第二部分的产品化内容中讨论这个问题。
Java和JavaScript的应用场景分工:后端企业级开发与Web前端交互
2026-11-05 15:57:34
除了浏览器和Node.js,还有哪些轻量级Js脚本运行工具?
2026-11-04 17:38:24
无需后端:用JavaScript实现简单网站的本地数据存储
2026-11-03 23:03:30
Node.js 下载慢或官网打不开怎么办
2026-11-03 18:19:37
JS解析大体积Excel文件内存溢出怎么办
2026-11-03 18:19:37
