基于 Docker 开发 NodeJS 应用

作者:终端旅客

时间:2026-10-28

浏览:598

本文介绍如何在 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 中的数据在容器重启时不会保持持久化,例如,如果你重启了容器,所有会话数据都将丢失。同样的情况也发生在你销毁容器并开启新容器时,这显然不是我们想要的。我将在第二部分的产品化内容中讨论这个问题。

实用工具推荐

电子包浆

绿化、压缩、噪点和虚拟水印,自由调节做旧程度。

使用 ›
图片压缩

选择画质和输出格式,预览压缩前后的大小。

使用 ›
相关文章