Node.js 是一个开源的、异步事件驱动的 JavaScript 运行时,用于运行 JavaScript 应用程序。它广泛用于传统网站和 API 服务器。同时,Docker 容器是一个独立的、可部署的单元,它将应用程序及其依赖项打包在一起,使其具有高度的可扩展性和可维护性。在本文中,我们将为 Node.js 创建一个 Docker 容器,并在该容器上运行一个简单的 express.js 应用程序。
什么是 Docker 容器?
Docker 是一个提供 Docker 运行时的开放平台。它使应用程序的开发、运行和部署变得简单易行。Docker 容器因其轻量级且高效利用底层系统资源而广受欢迎。它与虚拟机共享主机操作系统的内核,这使得 Docker 速度更快,能够同时处理多个请求。点击此处了解更多关于Docker的信息。
什么是 Node.js?
Node.js 是一个开源且免费的服务器环境。它提供 JavaScript 运行时,以便 JavaScript 应用程序可以在服务器上运行。它还允许JavaScript代码在浏览器之外运行。它还有很多其他功能,例如生成动态页面内容,在服务器上创建、保存和关闭文件,以及在后端处理数据库。
为什么要对 Node.js 使用 Docker 容器?
开发人员面临的问题之一是,应用程序的开发和部署环境可能截然不同。开发人员可能会开发自己的本地系统,而这很可能与应用程序最终部署到的云实例完全不同。
Docker 容器解决了这个问题,它使用了镜像的概念,镜像存储了 Docker 容器在特定时间的记录,就像所有库一样。运行应用程序时需要镜像及其版本。然后,开发人员可以与其他人共享此镜像,以获得与开发人员相同的环境并运行应用程序。
Docker 容器是微服务学习Docker 架构适配的最佳工具。许多公司正在转向 Docker,因为在 Docker 上运行的应用程序更易于维护、易于修改且高度可扩展。
分步 Docker 化 NodeJS 应用程序
步骤 1:Docker 化 Node.js Web 应用
让我们从一个轻松的快速应用程序开始,它在访问根端点时 打印“ Hello World!这是来自 docker 容器的 Nodejs ”。
- 创建一个名为express_app的文件夹并使用以下命令移动到该文件夹内。
mkdir express_app
cd express_app
现在,创建一个名为app.js的文件,如下所示。
-
`express_app`是您正在创建的目录的名称。
-
express_app是您想要更改到的目录。
第 2 步:创建 Node.js 应用
创建一个包含描述您的应用程序所需的所有文件和依赖项的文件,并将其命名为package.Jason。
{
"name": "docker-example",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"start": "nodemon app.js",
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.17.1",
"nodemon": "^2.0.12"
}
}
- 现在,使用以下命令初始化node项目。
npm init
这将添加 package.json 文件,其中包含有关我们项目的信息,例如脚本、依赖项和版本。它会询问包的名称、版本以及许多其他信息(您可以按 ENTER 选择默认值)。
-
npm:Node 包管理器 (Node Package Manager) 的缩写。它是 Node.js 捆绑的工具,用于管理 Node.js 的包(可在您自己的项目中使用的代码片段)。npm 可以帮助您安装、卸载、更新和管理这些包。
-
init:这是“initialize”的缩写。运行
npm init
,就是请求 npm 帮你设置项目的初始配置。本质上,你是在说:“我想启动一个新项目。请指导我完成设置过程。”
安装 Express 库并将其作为依赖项添加到 package.json 文件中。
npm install --save express
-
npm:Node 包管理器的缩写。它是一个帮助开发人员管理和安装 Node.js 应用程序包(类似于插件或库)的工具。
-
install:这是你给 npm 的命令。你告诉它你想安装一些东西。
-
–save:这部分表示您要将要安装的包作为依赖项保存在项目
package.json
文件中。该package.json
文件会跟踪项目运行时所需的所有依赖项。将包保存为依赖项意味着,如果其他人想要运行您的项目,他们只需查看该package.json
文件,了解所需的包,然后轻松安装它们。 -
express:这是您要安装的软件包的名称。在本例中,它是一个用于使用 Node.js 创建 Web 服务器和 Web 应用程序的常用软件包。安装时,npm 会获取所有必需的文件,并将它们放在
node_modules
项目目录中名为 express 的文件夹中。此文件夹包含您已安装软件包的所有代码。
安装一个名为 nodemon 的工具,当它检测到任何更改时会自动重新启动node应用程序。
npm install --save nodemon
我们明确地将这些依赖项添加到我们的 package.json 文件中,以便在 docker 容器内运行此应用程序时下载它们。
- 在package.json文件的 scripts 部分添加一个脚本,以便使用 nodemon 运行应用程序。文件内容如下:
步骤3:Express.js
Express 是一个 Node.js 框架,可帮助开发人员在服务器端将其 Web 应用程序组织成MVC 架构。与仅使用 Node.js 开发应用程序相比,它使 Web 应用程序的开发更加快速和简单。
例如,node.js 应用程序可能需要后端的MongoDB,而 Express 是帮助管理路由、请求和视图等一切的框架。
然后,创建一个 server.js 文件,使用 Express.js 框架定义一个 Web 应用程序:
// import and create an express app
const express = require('express');
const app = express()
// message as response
msg = "Hello world! this is nodejs in a docker container.."
// create an end point of the api
app.get('/', (req, res) => res.send(msg));
// now run the application and start listening
// on port 3000
app.listen(3000, () => {
console.log("app running on port 3000...");
})
在此阶段,我们可以使用以下命令在本地系统上运行我们的应用程序:
npm run start
但实际上,我们想要将这个应用程序docker化。为此,我们需要创建一个镜像,并提供一些信息,例如我们需要的运行时、应用程序将使用的端口以及本地系统上可用的所需文件。
-
npm:npm 是 Node.js 捆绑的命令行工具。它用于管理 Node.js 包和依赖项,以及运行文件中定义的脚本
package.json
。 -
run:这告诉 npm 您想要执行一个脚本。
-
start:这是要运行的脚本的名称。它是 npm 识别的特殊名称。您可以自定义它,但它
"start"
是运行应用程序主入口点的约定。 -
创建一个 Dockerfile,其中包含将运行应用程序的镜像的所有信息。docker 软件可以识别这个特殊文件,并使用它构建镜像。
步骤 4: 在 Node.js 应用项目中创建 Dockerfile
首先,创建一个名为Dockerfile的文件。
FROM node:latest
WORKDIR /app
COPY package.json /app
RUN npm install
COPY . /app
CMD ["npm", "start"]
Dockerfile 的解释
-
FROM 采用基础镜像的名称,并可选择与其版本一起使用。
-
WORKDIR 表示容器中保存应用程序文件的目录。
-
COPY 命令将 package.json 文件复制到应用程序目录。
-
RUN 命令运行提供的命令来安装 package.json 文件中提到的所有依赖项。
-
然后使用COPY将其余文件复制到容器中的app目录。
-
最后,我们提供运行应用程序的脚本。
- 创建所有需要的文件后的文件夹结构如下:
- 最后,使用此命令构建我们将在 docker 容器中运行的映像。
步骤5:构建您的镜像
创建 Dockerfile 后,使用以下命令通过帮助 Dockerfile 构建映像。
docker build -t docker-container-nodejs .
-
docker build:这是用于构建 Docker 镜像的命令。它告诉 Docker 根据 Dockerfile 中提供的指令构建镜像。
-
-t docker-container-nodejs:该
-t
标志是“tag”的缩写,用于为正在构建的镜像指定名称以及可选的标签。在本例中,我们将镜像命名为“docker-container-nodejs”。名称通常采用以下格式<repository>/<image_name>
: ,其中docker-container-nodejs
是镜像名称。 -
.:命令末尾的点表示构建上下文。它指示 Docker 在当前目录中查找 Dockerfile 以及其他必要的文件。Docker 会在构建上下文中查找 Dockerfile 中引用的文件,例如源代码、依赖项和配置文件。
.
该命令使用 -t 参数指定镜像名称,然后我们需要指定镜像的地址。接下来,我们需要将 Dockerfile 放置到该目录中;由于我们在运行命令时处于该目录中,因此可以使用句点,它代表当前目录。
- 确认镜像已创建。
docker images
输出将是系统中的镜像列表。它应该包含我们最近创建的镜像,其名称是我们通过 -t 标志指定的。
- 要使用此映像运行 docker 容器,请使用以下命令。
步骤 6:运行镜像
将镜像作为容器运行,并以容器的形式部署应用程序。
docker run -d -p 8000:3000 -v address_to_app_locally:/app docker-container-nodejs
上述命令运行一个 docker 容器。-p 参数用于将本地端口 8000 映射到容器的 3000 端口(应用程序正在该端口上运行)。-v 参数用于将应用程序文件挂载到容器的 app 目录中。此外,还需要指定要在容器中运行的镜像名称,在本例中为 docker-container-nodejs。
-
`docker run`:此命令用于从镜像创建并启动新的 Docker 容器。
-
`-d`:此标志代表“分离模式”。它在后台运行容器,因此您的终端可以自由地执行其他命令。
-
`-p 8000:3000`:此选项将主机上的端口映射到 Docker 容器内的端口。
-
`8000`:主机(即您的计算机)上的端口。
-
`3000`:Node.js 应用程序运行的 Docker 容器内的端口。
-
这意味着当您
http://localhost:8000
在主机上访问时,它将被转发到http://localhost:3000
容器内部。
-
-
`-v address_to_app_locally:/app`:此标志安装一个卷,将主机上的目录链接到容器内的目录。
-
`address_to_app_locally`:主机上应用程序目录的路径。
-
`/app`:Docker 容器内应用程序可用的目录。
-
这使您可以在本地开发应用程序并查看容器内部的变化,而无需重建它。
-
-
`docker-container-nodejs`:这是创建容器的 Docker 镜像的名称。请确保在运行该命令之前已构建或拉取此镜像。
步骤 7:测试应用程序
访问此地址localhost :8000,我们的 express 应用程序将返回以下响应。
使用 Docker Compose 运行 node
version: '3.8'
services:
app:
build: .
ports:
- "8000:3000"
volumes:
- .:/app
command: npm start
-
`version: ‘3.8’`:指定 Docker Compose 文件格式的版本。3.8 版本是常用的版本,支持最新功能。
-
`services`:定义组成应用程序的服务。这里我们有一个名为 的服务
app
。 -
`app`:服务名称。此服务代表您的 Node.js 应用程序。
-
`build: .`:指示Docker Compose从位于当前目录 ( ) 中的 Dockerfile 构建映像
.
。 -
`ports`:映射主机和 Docker 容器之间的端口。
- `“8000:3000”`:将主机上的 8000 端口映射到 Docker 容器内的 3000 端口。当您
http://localhost:8000
在主机上访问时,它会将请求转发到运行 Node.js 应用的容器中的 3000 端口。
- `“8000:3000”`:将主机上的 8000 端口映射到 Docker 容器内的 3000 端口。当您
-
`volumes`:将主机中的目录挂载到 Docker 容器中。
- `. : /app`:将主机上的当前目录 (
.
) 挂载到/app
容器内的目录。这样您就可以在主机上编辑代码,并且更改将反映在容器内。
- `. : /app`:将主机上的当前目录 (
-
`command`:指定在容器内运行的命令。
- `npm start`:运行
npm start
,通常会启动您的 Node.js 应用程序。
- `npm start`:运行
Docker node最佳实践
-
使用官方node镜像:从轻量级基础镜像开始,例如较小的镜像尺寸。
node:alpine
-
利用多阶段构建:使用多阶段构建,通过仅包含必要的文件来减少最终镜像大小。
-
缓存依赖项:在复制其他文件之前首先复制
package.json
并package-lock.json
运行,npm install
以利用Docker 的层缓存。 -
设置工作目录:用于
WORKDIR
设置容器内的工作目录。 -
用途:创建一个文件以从构建上下文中排除不必要的文件和目录。`.dockerignore`
.dockerignore
-
以非 root 用户身份运行:在 Dockerfile 中添加非 root 用户并切换到该用户以获得更好的安全性。
-
优化CMD:用于
CMD ["node", "your-app.js"]
定义容器的默认命令。
结论
在本文中,我们了解了 Docker 容器、镜像及其优势。然后,我们学习了如何创建可在 Docker 容器上运行的镜像。最后,我们创建了一个小型 Express 应用程序,演示了如何使用在 Docker 容器中运行的 Node.js 应用程序。