NPM 启动脚本从本地 shell 运行但在 Docker 容器命令中失败
NPM start script runs from local shell but fails inside Docker container command
我有一个 Node 应用程序,它由三个独立的 Node 服务器组成,每个服务器 运行 pm2 start
。我用concurrently到运行这三台服务器,作为start-all的脚本在package.json:
"scripts": {
...
"start-all": "concurrently \" pm2 start ./dist/foo.js \" \"pm2 start ./dist/bar.js \" \"pm2 start ./dist/baz.js\"",
"stop-all": "pm2 stop all",
"reload-all": "pm2 reload all",
...
}
当从本地主机上的命令行 运行ning 时,这一切 运行 都很好,但是当我 运行 它作为 docker-compose 命令时 - 或者作为我的 Docker 文件中的 RUN
命令 - 只有一个服务器脚本(我每次尝试时随机一个!)将启动,但随后立即退出。在我的 --verbose
docker-compose 输出中,我可以看到 pm2 面板(列表名称、版本、模式、pid 等),但随后显示此错误消息:
pm2 start ./dist/foo.js exited with code 0
.
N.B:这都是在 Docker 运行 本地进行的(在具有 16GB RAM 的 Mac Mini 上), 不在远程服务器上。
如果我 docker exec -it <container_name> /bin/bash
进入容器和 运行 npm run start-all
手动从 src 目录的顶层(我 COPY
在我的 Docker文件)一切正常。这是我的 Docker 文件:
FROM node:latest
# Create the workdir
RUN mkdir /myapp
WORKDIR /myapp
# Install packages
COPY package*.json ./
RUN npm install
# Install pm2 and concurrently globally.
RUN npm install -g pm2
RUN npm install -g concurrently
# Copy source code to the container
COPY . ./
在我的 docker-compose 文件中,我只是将 npm 运行 start-all 列为节点服务的命令。但是如果我像这样将它添加到 Docker 文件中没有什么区别:
RUN npm run start-all
可能发生了什么? pm2 日志只显示应用已启动。
第一个原因是 pm2 start app.js
在后台启动应用程序,这就是为什么您的容器在 运行s pm2 start
.
后立即停止的原因
您需要使用pm2_runtime
启动一个应用程序,它会在前台启动一个应用程序。你也不需要 concurrently
,pm2 process.yml 将完成这项工作。
Docker 整合
Using Containers? We got your back. Start today using pm2-runtime, a
perfect companion to get the most out of Node.js in production
environment.
The goal of pm2-runtime is to wrap your applications into a proper
Node.js production environment. It solves major issues when running
Node.js applications inside a container like:
Second Process Fallback for High Application Reliability Process Flow
Control Automatic Application Monitoring to keep it always sane and
high performing Automatic Source Map Discovery and Resolving Support
第二个重要的事情,你应该把你所有的应用程序都放在pm2配置文件中,因为docker只能运行来自[=16的进程=].
生态系统文件
PM2 empowers your process management workflow. It allows you to
fine-tune the behavior, options, environment variables, logs files of
each application via a process file. It’s particularly useful for
micro-service based applications.
pm2 config application-declaration
创建文件 process.yml
apps:
- script : ./dist/bar.js
name : 'bar'
- script : ./dist/foo.js
name : 'worker'
env :
NODE_ENV: development
然后在Docker文件
中添加CMD
CMD ["pm2-runtime", "process.yml"]
从 docker-compose 中删除 command
。
Docker 和 pm2 提供重叠的功能:例如,两者都具有重启进程和管理日志的能力。在 Docker 中,通常认为容器中只有 运行 一个进程是最佳实践,如果这样做,则不一定需要 pm2。 同时使用 pm2 和 docker 有什么意义?
对此进行了更详细的讨论。
当您 运行 您的映像时,您可以指定 运行 命令,并且您可以从同一个映像启动多个容器。根据您最初显示的 Docker 文件,您可以将它们作为
启动
docker run --name foo myimage node ./dist/foo.js
docker run --name bar myimage node ./dist/bar.js
docker run --name baz myimage node ./dist/baz.js
这样您就可以执行一些操作,例如在代码更改时仅重启其中一个容器,同时保持其余容器不变。
您暗示 Docker 撰写;它的 command:
指令设置相同的 属性.
version: '3'
services:
foo:
build: .
command: node ./dist/foo.js
bar:
build: .
command: node ./dist/bar.js
baz:
build: .
command: node ./dist/baz.js
我有一个 Node 应用程序,它由三个独立的 Node 服务器组成,每个服务器 运行 pm2 start
。我用concurrently到运行这三台服务器,作为start-all的脚本在package.json:
"scripts": {
...
"start-all": "concurrently \" pm2 start ./dist/foo.js \" \"pm2 start ./dist/bar.js \" \"pm2 start ./dist/baz.js\"",
"stop-all": "pm2 stop all",
"reload-all": "pm2 reload all",
...
}
当从本地主机上的命令行 运行ning 时,这一切 运行 都很好,但是当我 运行 它作为 docker-compose 命令时 - 或者作为我的 Docker 文件中的 RUN
命令 - 只有一个服务器脚本(我每次尝试时随机一个!)将启动,但随后立即退出。在我的 --verbose
docker-compose 输出中,我可以看到 pm2 面板(列表名称、版本、模式、pid 等),但随后显示此错误消息:
pm2 start ./dist/foo.js exited with code 0
.
N.B:这都是在 Docker 运行 本地进行的(在具有 16GB RAM 的 Mac Mini 上), 不在远程服务器上。
如果我 docker exec -it <container_name> /bin/bash
进入容器和 运行 npm run start-all
手动从 src 目录的顶层(我 COPY
在我的 Docker文件)一切正常。这是我的 Docker 文件:
FROM node:latest
# Create the workdir
RUN mkdir /myapp
WORKDIR /myapp
# Install packages
COPY package*.json ./
RUN npm install
# Install pm2 and concurrently globally.
RUN npm install -g pm2
RUN npm install -g concurrently
# Copy source code to the container
COPY . ./
在我的 docker-compose 文件中,我只是将 npm 运行 start-all 列为节点服务的命令。但是如果我像这样将它添加到 Docker 文件中没有什么区别:
RUN npm run start-all
可能发生了什么? pm2 日志只显示应用已启动。
第一个原因是 pm2 start app.js
在后台启动应用程序,这就是为什么您的容器在 运行s pm2 start
.
您需要使用pm2_runtime
启动一个应用程序,它会在前台启动一个应用程序。你也不需要 concurrently
,pm2 process.yml 将完成这项工作。
Docker 整合
Using Containers? We got your back. Start today using pm2-runtime, a perfect companion to get the most out of Node.js in production environment.
The goal of pm2-runtime is to wrap your applications into a proper Node.js production environment. It solves major issues when running Node.js applications inside a container like:
Second Process Fallback for High Application Reliability Process Flow Control Automatic Application Monitoring to keep it always sane and high performing Automatic Source Map Discovery and Resolving Support
第二个重要的事情,你应该把你所有的应用程序都放在pm2配置文件中,因为docker只能运行来自[=16的进程=].
生态系统文件
PM2 empowers your process management workflow. It allows you to fine-tune the behavior, options, environment variables, logs files of each application via a process file. It’s particularly useful for micro-service based applications.
pm2 config application-declaration
创建文件 process.yml
apps:
- script : ./dist/bar.js
name : 'bar'
- script : ./dist/foo.js
name : 'worker'
env :
NODE_ENV: development
然后在Docker文件
中添加CMD
CMD ["pm2-runtime", "process.yml"]
从 docker-compose 中删除 command
。
Docker 和 pm2 提供重叠的功能:例如,两者都具有重启进程和管理日志的能力。在 Docker 中,通常认为容器中只有 运行 一个进程是最佳实践,如果这样做,则不一定需要 pm2。 同时使用 pm2 和 docker 有什么意义? 对此进行了更详细的讨论。
当您 运行 您的映像时,您可以指定 运行 命令,并且您可以从同一个映像启动多个容器。根据您最初显示的 Docker 文件,您可以将它们作为
启动docker run --name foo myimage node ./dist/foo.js
docker run --name bar myimage node ./dist/bar.js
docker run --name baz myimage node ./dist/baz.js
这样您就可以执行一些操作,例如在代码更改时仅重启其中一个容器,同时保持其余容器不变。
您暗示 Docker 撰写;它的 command:
指令设置相同的 属性.
version: '3'
services:
foo:
build: .
command: node ./dist/foo.js
bar:
build: .
command: node ./dist/bar.js
baz:
build: .
command: node ./dist/baz.js