在本节中,将创建一个Node.js的“Hello World”应用程序,并将该应用构建成Docker镜像,并从容器启动。正常情况下,该镜像可以部署到生产服务器上,Docker Compose 将用于覆盖一些设置以创建开发和调试环境。这样可以在主机PC上进行编码开发,这样文件将在一个持续运行的容器中执行。这有几个好处:
- Docker 将管理所有依赖项—— 不需要安装和维护runtimes
- 这个过程与本地开发没什么不同——可以使用任何喜欢的编辑器和工具
- 容器是隔离的——应用程序影响到主机PC,如使删除文件
- 任何时候都可以将应用程序分发给其他开发人员或测试人员——应用程序可以在任何其他设备上以零配置相同的方式运行。
本节创建的代码文件在项目
https://github.com/QuintionTang/docker-nodejs
中
基于容器的应用开发
Docker 简化了 Web 开发:任何的 Web 应用程序都可以在单个容器中运行。
但是……如果想将类似的容器部署到实时生产服务器,应用程序通常是无状态的。这样可以启动任意数量的实例,任何实例都可以对请求做出响应。实际上,应用程序不应该将基本状态数据存储在本地文件或内存中。
例如:当用户登录时,应用程序将登录凭据存储在内存中。在开发过程中使用单个容器,都可以按预期运行没有问题。
如果将应用程序部署到生产服务器并在两个以上容器中运行,这些容器通过负载均衡接收请求。用户访问系统由
container1
处理其登录。那么下一个请求可能就由container2
提供服务,容器之间并没有共享登录状态,这个时候就会出现未登录的情况。
当然上面的问题是可以通过解决的,为隔离的容器提供一个中心存储服务,维护应用的持久化存储数据,例如数据库。
无状态 Web 应用程序是一个不错的方式。这样在生产环境中随着用户情况的增加可以快速进行扩缩容,自动添加更多的机器/容器。在解决实际需求的时候就需要考虑是否适合无状态,如果对有状态的应用程序进行转换可能是不可行的。
这些在开发过程中都无关紧要,因为通常只会在单个容器中运行应用程序。如果不实用,就不必在生产中使用容器。
什么是 Node.js
这个想必大部份掘金的小伙伴都知道,这里不展开介绍,引用一段简单的说明。
Node.js
是一种流行的、高性能 JavaScript 运行时,使用 Chrome
浏览器的 V8 JavaScript
引擎构建。它通常用于服务器端 Web 开发,但也已被前端或客户端用来构建工具、桌面应用程序、嵌入式系统等所采用。
安装 Node.js 后,可以使用以下命令执行 JavaScript 文件:
node index.js
单入口脚本文件是什么?理论上它可以命名为任何名称,通常项目都使用index.js
作为入口。
前面的内容一直在使用 Docker Hub 提供的 Docker 镜像。本节将介绍如何构建自己的 Docker 镜像,该镜像可以在开发和生产环境中安装和执行应用程序。
可能你对 Node.js
不感兴趣,但是不管使用何种语言(PHP、Python、Ruby、Go、Rust等)都适合使用 Docker 。
Hello World应用概述
该项目将使用Node.js的Express.js框架创建了一个“Hello World”应用程序。
应用运行地址为:http://localhost:3000/
,返回纯文本格式:Hello World!
。
从客户端 Ajax 请求调用相同的 URL 会返回 JSON 编码的对象:
{ "message": "Hello World!" }
当传入请求的HTTP 标头设置为时,可以识别 Ajax 调用。这是由大多数 Ajax 库添加了:X-Requested-With
、XMLHttpRequest
。
可以向 URL 路径添加字符串,例如http://localhost:3000/devpoint
将返回 Hello Devpint!
,响应内容为:
{ "message": "Hello Devpoint!" }
项目初始化
在项目目录中执行以下代码初始化项目:
npm init
输入基本的信息后,会在项目根目录下生成 package.json
。
接下来安装 express
,执行一下命令:
npm install express --save
为了开发过程中能够响应代码的变更,接下来安装 Nodemon,执行以下命令:
npm install nodemon --save-dev
nodemo
用来监听 node.js 项目中文件的更改并自动重启服务的工具,接下来为项目增加监听规则,如需要忽略的目录:
{
"script": "./index.js",
"ext": "js json",
"ignore": [
"node_modules/"
],
"legacyWatch": true,
"delay": 200,
"verbose": true
}
修改项目 package.json
,在scripts属性下添加启动命令:
"start": "node ./index.js",
"debug": "nodemon --trace-warnings --inspect=0.0.0.0:9229 ./index.js",
这样在终端可以执行一下的命令:
npm start
: 一般用于生产环境npm run debug
:用于开发调试
应用脚本 index.js
脚本在根路由下定义简单的响应请求
"use strict";
const port = process.env.NODE_PORT || 3005, // 定义HTTP默认端口或者从NODE_PORT环境变量获取
express = require("express"),
app = express();
// 根路由
app.get("/:title?", (req, res) => {
const message = `Hello ${req.params.title || "Devpoint"}!`;
if (req.xhr) {
res.set("Access-Control-Allow-Origin", "*").json({ message });
} else {
res.send(message);
}
});
// 启动HTTP服务
app.listen(port, () => console.log(`server running on port ${port}`));
接下来开始执行脚本:
npm run debug
打开浏览器输入http://localhost:3005/
,可以看到响应的响应,如下
现在可以尝试去修改脚本 index.js
的内容,当有更新的时候,终端会重启服务,刷新浏览器即可看到更新。
到目前为止,一个简单的NodeJS应用程序已经完成。接下来将介绍如何在Docker环境里面运行调试。
后续可以结合谷歌浏览器调试Node.js应用。