使

使用 Docker 设置 Node 的分步指南 了解如何在 Docker 容器内设置 Node JS

2025-06-11

使用 Docker 设置 Node 的分步指南

了解如何在 Docker 容器内设置 Node JS

了解如何在 Docker 容器内设置 Node JS

本文的目标

  • 拥有一个可以运行的 NodeJS 应用程序
  • 确保进程不会因错误而退出,从而使 Node 应用具有弹性
  • 代码更改时自动重启服务器,使 Node 应用更易于使用
  • 利用 Docker 可以:
    • 快速建立与生产相同的开发环境。
    • 能够轻松地在本地和服务器上切换 Node 版本
    • Docker 的所有其他优势

先决条件

  • Docker 已安装
  • 至少具备 Node 和 NPM 的入门级知识

如果你是那种只想看到最终结果的人,那么 GitHub repo 也许更适合你


1. 准备一个简单的 Node 应用

我们将使用 Express,因为它设置起来非常简单,而且这个框架很受欢迎。

在一个干净的目录中,让我们首先初始化 NPM,继续运行此命令并按照提示进行操作(提示中输入的内容对于本指南来说并不重要)

npm init
Enter fullscreen mode Exit fullscreen mode

安装 Express

npm install --save-prod express
Enter fullscreen mode Exit fullscreen mode

设置基本的 Express 服务器。下面的文件只是简单地启动一个 Node 进程,监听 3000 端口,并向/ 路由返回Hello World!消息。

src/index.js

const express = require('express')
const app = express()
const port = 3000

app.get('/', (req, res) => res.send('Hello World!'))

app.listen(port, () => {console.log(`Example app listening on port ${port}!`))
Enter fullscreen mode Exit fullscreen mode

2. 设置 Docker 来运行我们的 Node 应用

我们将使用 docker-compose.yml 文件来启动和停止 Docker 容器,而无需输入冗长的 Docker 命令。你可以将此文件视为多个 Docker 容器的配置文件。

docker-compose.yml

version: "3"
services:
  app:
    container_name: app # How the container will appear when listing containers from the CLI
    image: node:10 # The <container-name>:<tag-version> of the container, in this case the tag version aligns with the version of node
    user: node # The user to run as in the container
    working_dir: "/app" # Where to container will assume it should run commands and where you will start out if you go inside the container
    networks:
    - app # Networking can get complex, but for all intents and purposes just know that containers on the same network can speak to each other
    ports:
    - "3000:3000" # <host-port>:<container-port> to listen to, so anything running on port 3000 of the container will map to port 3000 on our localhost
    volumes:
    - ./:/app # <host-directory>:<container-directory> this says map the current directory from your system to the /app directory in the docker container
    command: "node src/index.js" # The command docker will execute when starting the container, this command is not allowed to exit, if it does your container will stop

networks:
  app:

Enter fullscreen mode Exit fullscreen mode

现在我们已经配置好了,让我们用这个命令启动docker容器。这意味着启动配置文件中定义的容器,并在后台运行它们(-d)。

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

现在你应该能够在浏览器中访问localhost:3000并查看 你还应该能够通过运行来验证你的容器是否正在运行Hello World!
浏览器中显示的 hello world 示例

docker ps
Enter fullscreen mode Exit fullscreen mode

它应该输出正在运行的 docker 容器列表,类似于
使用 docker ps 命令查看正在运行的容器列表

用于管理此容器的有用 docker 命令

列出所有正在运行的容器

docker ps
Enter fullscreen mode Exit fullscreen mode

列出所有容器,无论它们是否正在运行

docker ps -a
Enter fullscreen mode Exit fullscreen mode

从同一目录中的 docker-compose.yml 文件启动容器

docker-compose up -d
Enter fullscreen mode Exit fullscreen mode

从同一目录中的 docker-compose.yml 文件停止容器

docker-compose stop
Enter fullscreen mode Exit fullscreen mode

从同一目录中的 docker-compose.yml 文件重新启动容器

docker-compose restart
Enter fullscreen mode Exit fullscreen mode

查看 Docker 容器中的日志文件

docker-compose logs -f
Enter fullscreen mode Exit fullscreen mode

3. 增强应用程序的弹性

如果您之前使用过 Node,那么您可能知道,如果应用程序中出现错误(例如未捕获的异常),它会关闭相应的 Node 进程。这对我们来说真是个坏消息,因为我们的代码中难免会有 bug,而且我们无法保证代码 100% 无错误。解决这个问题的方法通常是创建一个新的进程来监视我们的 Node 应用,并在应用退出时重新启动它。市面上有很多解决方案,例如 Linux 的 supervisord、NPM 的 forever 包和 PM2 等等……我们只需在本指南中挑选一个即可。

我将重点介绍PM2,因为我对它最熟悉,并且除了进程管理之外,它还具有一些其他功能,例如文件监视,这在我们的下一部分中会很有用。

安装 PM2

npm install --save-prod pm2
Enter fullscreen mode Exit fullscreen mode

PM2 可以通过命令行使用,但我们将设置一个简单的配置文件,就像我们对 docker-compose.yml 文件所做的那样,以防止我们重复输入长命令

生态系统.config.js

const path = require('path')

module.exports = {
  apps: [{
    name: 'app',
    script: 'src/index.js', // Your entry point
    instances: 1,
    autorestart: true, // THIS is the important part, this will tell PM2 to restart your app if it falls over
    max_memory_restart: '1G'
  }]
}
Enter fullscreen mode Exit fullscreen mode

现在我们应该更改我们的 docker-compose.yml 文件以使用 PM2 来启动我们的应用程序,而不是直接从 index.js 启动它。

docker-compose.yml(仅更改了命令选项)

version: "3"
services:
  app:
    container_name: app # How the container will appear when listing containers from the CLI
    image: node:10 # The <container-name>:<tag-version> of the container, in this case the tag version aligns with the version of node
    user: node # The user to run as in the container
    working_dir: "/app" # Where to container will assume it should run commands and where you will start out if you go inside the container
    networks:
    - app # Networking can get complex, but for all intents and purposes just know that containers on the same network can speak to each other
    ports:
    - "3000:3000" # <host-port>:<container-port> to listen to, so anything running on port 3000 of the container will map to port 3000 on our localhost
    volumes:
    - ./:/app # <host-directory>:<container-directory> this says map the current directory from your system to the /app directory in the docker container
    command: "npx pm2 start ecosystem.config.js --no-daemon" # The command docker will execute when starting the container, this command is not allowed to exit, if it does your container will stop

networks:
  app:
Enter fullscreen mode Exit fullscreen mode

需要注意的是,修改 docker-compose.yml 文件不会影响正在运行的容器。为了使更改生效,您需要重启容器。

docker-compose restart
Enter fullscreen mode Exit fullscreen mode

太好了,我们现在应该回到locahost:3000 的正常运行应用程序,但现在我们的应用程序在出现错误时不会崩溃。

4. 使我们的应用程序易于开发

您可能已经注意到,一旦 Node 进程启动,更改代码实际上不会有任何效果,直到您重新启动该 Node 进程,而对于我们来说,这意味着每次进行更改时都要重新启动 Docker 容器。这听起来太糟糕了。如果我们可以在更改代码时自动重新启动 Node 进程,那就太理想了。过去,我曾尝试过引入文件监视实用程序,并使用该文件监视实用程序在文件更改时重新启动 Docker,或者我会使用 Nodemon,但在使用 Docker 时这样做会有一些注意事项。最近,我一直使用 PM2 在文件更改时重新启动我的 Node 进程,由于我们已经从上一步将其引入,因此无需安装其他依赖项。

ecosystem.config.js(仅添加了监视选项)**

const path = require('path')

module.exports = {
    apps: [{
        name: 'app',
        script: 'src/index.js',
        instances: 1,
        autorestart: true,
        watch: process.env.NODE_ENV !== 'production' ? path.resolve(__dirname, 'src') : false,
        max_memory_restart: '1G'
    }]
}
Enter fullscreen mode Exit fullscreen mode

如果我们没有将 NODE_ENV 环境变量设置为production,上面的配置文件现在将监视src目录。您可以通过更改 index.js 文件来测试它,使其除了Hello World!之外还向浏览器打印其他内容。同样,在此功能生效之前,您需要重新启动 Docker 容器,因为您更改了 PM2 运行容器的方式。

docker-compose restart
Enter fullscreen mode Exit fullscreen mode

需要注意的是,重新启动 Node 进程可能需要一秒钟才能完成,如果您想观察它何时完成,您可以查看 Docker 日志以了解 PM2 何时完成重新启动 Node 进程。

docker-compose logs -f
Enter fullscreen mode Exit fullscreen mode

当你的进程重新启动时,你会看到类似这样的内容
PM2重启节点流程示例

总结

  • 我们的目标之一是能够轻松更改 Node 版本,您可以通过更改docker-compose.yml文件中的图像选项来实现这一点。

  • 本地安装依赖项需要使用本地 NPM 和 Node 版本,如果本地版本与 Docker 版本不同,有时可能会导致冲突。使用同一个 Docker 容器安装依赖项更安全。您可以使用以下命令,它将使用该容器安装依赖项,然后将其删除

docker run --rm -i -v <absolute-path-to-your-project-locally>:/app -w /app node:10 npm install 
Enter fullscreen mode Exit fullscreen mode
  • 如上所述,如果本地 Node 版本与 Docker 运行的版本不同,可能会出现问题。为了保持一致性,最好在容器内运行命令。您可以使用以下命令进入容器内部:
docker exec -it app bash
Enter fullscreen mode Exit fullscreen mode

上述命令将把你放入容器中,以便你可以继续从那里运行命令,即npm run startnpm run test

如果你不想进入容器,你可以运行如下命令

docker exec -t app bash -c "npm run start"
Enter fullscreen mode Exit fullscreen mode
鏂囩珷鏉ユ簮锛�https://dev.to/itmayziii/step-by-step-guide-to-setup-node-with-docker-2mc9
PREV
如何构建和发布你自己的扩展到 VS Code Marketplace
NEXT
Svelte 反应性陷阱 + 解决方案(如果您在生产中使用 Svelte,则应该阅读此内容)