node.js - 使用 docker-compose 在 dockerized node.js 应用程序中重新加载代码

标签 node.js docker docker-compose dockerfile

我有一个简单的 node.js docker 应用程序。

我能够成功运行它,但是尽管按照 docker-compose docs 中的描述安装了卷,但容器内的代码重新加载不起作用。 .

目录布局:

my-test-app
| docker-compose.yml
| Dockerfile
| index.js
| package.json

docker 文件:

FROM mhart/alpine-node:8
WORKDIR /app
COPY . .
EXPOSE 5000
CMD ["node", "index.js"]

docker-compose.yml:

version: '3'
services:
  node-app:
    build: .
    ports:
      - "5000:5000"
    volumes:
      - .:/app
  redis:
    image: "redis:alpine"

index.js:

const http = require('http');
const server = http.createServer((req, res) => {
  res.end("hello world");
});
server.listen(5000);

package.json:

{
  "name": "my-test-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
  },
  "author": "",
  "license": "MIT"
}

我也尝试了以下相同的结果(应用程序运行,无法实时重新加载代码)

  • 使用官方 Node 图像,而不是 alpine-node .
  • 将应用程序代码放在 ./app 下里面的文件夹my-test-app并更新 COPY里面Dockerfilevolumes里面docker-compose.yml相应地。

最佳答案

我看到短语“实时重新加载”用于两种不同类型的重新加载:

  1. 在代码更改时终止并重新启动应用程序,以及
  2. 在代码更改时自动在客户端浏览器上重新加载 HTML 和 Assets 。

根据您的问题,我认为您指的是第一种类型,因此后面的答案解决了这一问题。


这里的问题是上下文之一。

请记住,docker 容器与您的主机是隔离的 - 具体来说,在容器中运行的进程与在主机上运行的进程不同(并且通常不能与之交互)。在您的情况下,您已选择在容器中安装主机目录,但这只是文件系统,而不是进程。

当您实例化一个新容器时,想一想您的 Docker 镜像做了什么:它在 WORKDIR 中运行 node index.js。当代码更改时停止它并重新启动它的代码在哪里?大概它在主机 上的进程中运行。这意味着它无法触及在容器中运行的 Node 进程(因为它是隔离的)。

现在,您还没有提到您使用什么方法来处理实时重新加载,但这应该不会有太大的不同。它们基本上都以相同的方式工作:在更改应用程序代码时,终止现有进程并启动一个新进程。

要解决这个问题,您有两个选择:

  1. 在容器内运行“实时重新加载”代码,或者
  2. 在容器外运行您的开发代码

首先,您可以按照@MarkS 的建议使用nodemon。 .这应该和替换一样简单

CMD ["node", "index.js"]

在你的 Dockerfile 中

CMD ["nodemon", "index.js"]

当然,前提是您在镜像中正确安装了 nodemon

另一种方法,也是我所做的,是在开发期间在 Docker 环境之外的主机上运行代码,然后在部署时将其打包到镜像中。这解决了两个问题:

  1. 您在使用独立 Node 进程时遇到的问题,以及
  2. 权限问题。

请记住,在 Docker 中运行的应用程序以 root 身份运行。这意味着如果您的应用创建文件,它们将归 root 所有。我尝试在 Docker 环境中进行开发,但遇到了一些问题,例如,我想删除应用程序创建的文件并且必须 sudo(以 root 身份登录) >) 只是为了清理东西。

关于node.js - 使用 docker-compose 在 dockerized node.js 应用程序中重新加载代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46223173/

相关文章:

docker - 如何基于镜像 "python:2.7"在 docker 容器中安装 AWS CLI

javascript - 禁用 eslint 解析错误消息

node.js - 在 Github 操作中获取错误 : connect ECONNREFUSED 127. 0.0.1:5432

node.js - expressjs 和 socket.io - 客户端上的重复消息

Docker - 在构建镜像时实时查看日志

python - docker postgres 角色不存在

azure - 如何在本地和 azure 中使用相同的 compose.yml 文件?

docker - 使用 docker-compose 进行 Vue.js 本地开发

node.js - 'This' 在 typescript 中未定义,即使在 promise 中使用箭头函数

javascript - 直接在可写流中传递可读流