【问题标题】:Docker automatically rerun npm install on package.json changeDocker 在 package.json 更改时自动重新运行 npm install
【发布时间】:2019-02-25 13:46:04
【问题描述】:

我正在尝试为 node.js 项目设置 development 容器,以便与来宾共享我的本地源文件(因此我可以通过 dnsmasq 通配符请求到本地域端口 80,但我想这与问题无关)。当我在本地进行更改时,容器中的节点进程会重新启动:

Dockerfile:

FROM node:8

# Install app dependencies
RUN npm install -g nodemon
COPY package.json /tmp/package.json
RUN cd /tmp && npm install --production

NODE_PATH=/tmp/node_modules
WORKDIR /app

EXPOSE 8080
EXPOSE 9229

CMD nodemon --inspect index.js

docker-compose.json(截断):

version: '3.3'
services:
    app:
        build: .
        container_name: 'my-app'
        restart: unless-stopped
        ports:
            - 8080:8080
            - 9229:9229
        volumes:
            - .:/app

因为node_modules是安装在Dockerfile里面的,所以每次给packages.json加个包都得手动重新构建容器:

docker-compose stop
docker-compose build
docker-compose up -d

我可以使用 inotify 为此设置一个监视,但我不喜欢停止整个堆栈(包括那里定义的其他服务)。

是否可以将这个逻辑放在容器中,并在每次更改package.json 时重新运行npm install

【问题讨论】:

    标签: node.js docker docker-compose package.json


    【解决方案1】:

    解决方案

    我写了一个入口文件,它在node.js 中启动两个线程,所以Dockerfile 可以很普通。现在我们只需要docker-compose

    Dockerfile

    FROM node:8
    RUN npm install -g nodemon
    

    docker-compose.yml

    version: '3.5'
    services:
        app:
            build: .
            user: '1000'
            working_dir: /opt/app
            ports:
                - 8080:8080
                - 9229:9229
            volumes:
                - ./:/opt/app
            command: 'node docker-entry.js'
    

    docker-entry.js

    /**
     * @file docker-entry for development container
     * @author Redsandro (https://www.windowsremix.com/)
     */
    'use strict'
    const { spawn } = require('child_process')
    
    /*
     * Install dependencies every time package.json changes
     */
    spawn('nodemon -w package.json --exec "npm install"', {
        stdio: 'inherit',
        shell: true
    })
    
    /*
     * Restart node when a source file changes, plus:
     * Restart when `npm install` ran based on `package-lock.json` changing.
     */
    spawn('nodemon --inspect -e js,json -i node_modules -i package.json index.js', {
        stdio: 'inherit',
        shell: true
    })
    

    .dockerignore

    # Just ignore everything
    **
    

    这是因为 package-lock.json 在添加或更新依赖项时发生变化。所以需要 npm 5。在其他节点图像上未经测试。

    确保第一次运行时您的工作目录中没有node_modulespackage-lock.json。内部节点应用程序在第一次运行时会崩溃(显然,它找不到依赖项),但是一旦安装了依赖项,它将重新启动。

    输入docker-compose up -d && docker-compose logs -f 以查看结果。对文件进行一些更改,并添加一个包to package.json

    每次启动容器时,npm install 都会运行,除非在容器停止时更改 package.json,否则 10 次中的 9 次都没有必要。这很好,因为节点应用程序是并行启动的,您不必等待它完成。您可以立即使用容器。 (当然,除非这是您的第一次运行。)

    要做的事情:我曾希望将node_modules 移动到某个客户目录(例如/tmp),这样所有这些数据都将存储在docker 服务器上,而不是我的笔记本电脑ssd 上。更重要的是,您的主机和来宾现在共享相同的node_modules 如果您使用非 Linux 操作系统和已编译的软件包,您将度过一段糟糕的时光。因为它要么在主机中工作,要么在来宾中工作,但不能同时在两者中工作。我似乎无法为 npm 指定不同的安装目录,就像我之前所做的那样没有 npm 也写入 package-lock.json 并且该文件在本地目录中是必要的,此设置才能正常工作.我确信通过一些巧妙的链接它可以工作,但我已经用尽了分配给这个解决方案的时间。欢迎提示。随意添加附录和其他答案。

    【讨论】:

      【解决方案2】:

      是否可以在容器内有这个逻辑,并且每次更改 package.json 时重新运行 npm install ?

      我并不完全清楚,您对 package.json 的更改是在主机上还是在 /tmp/ 目录中的 docker 容器中完成的。我猜你在主机上修改了一个文件,因为那里还有其他项目文件。

      如果你在容器中修改 /tmp/ 以外的其他位置的 package.json,你需要手动将新版本的 package.json 复制到容器中的 /tmp

      docker cp "location/of/package.json" "containername":/tmp/
      

      然后你只需进入容器并安装依赖项。

      docker exec -it containername bash
      cd /tmp/
      npm install
      

      是否可以在容器内有这个逻辑,然后重新运行 npm 每次更改 package.json 时安装?

      您可以将上述逻辑传递给简单的 bash 脚本。然后您可以运行一些观察程序(例如 nodemon)来观察 package.json 并在文件更改后运行脚本。也许通过很大的延迟也是一个好主意,这样它就不会在您输入模块的全名之前尝试安装模块。但在大多数情况下,我猜你只是使用 npm 命令而不是手动输入模块的名称。

      【讨论】:

        猜你喜欢
        • 2021-08-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-02
        • 2019-07-01
        • 2019-01-23
        • 1970-01-01
        • 2015-07-16
        相关资源
        最近更新 更多