And*_*y E 5 pipe child-process node.js docker
我正在使用 Node.js 进程运行命令行应用程序spawn()。该进程是通过 stdio 选项中的额外管道启动的。这是一个简化的代码示例:
const stdio = ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'];
const process = spawn('/path/to/command', [], { stdio });
// Later...
const { 3: pipeWrite, 4: pipeRead } = process.stdio;
pipeRead.on('data', (data) => {
if (String(data) === "PING?") {
pipeWrite.write("PONG!");
}
});
Run Code Online (Sandbox Code Playgroud)
现在,这工作正常,但我想在 docker 容器内运行命令,用作docker run生成的可执行文件:
const stdio = ['ignore', 'pipe', 'pipe', 'pipe', 'pipe'];
const process = spawn(
'/usr/bin/env', [
'docker',
'run',
'--rm',
'my-image',
'/path/to/command'
], { stdio }
);
Run Code Online (Sandbox Code Playgroud)
这失败了,docker 容器内的命令行应用程序说它无法写入管道。有可能实现这一点吗docker run?
我已经建立了一个Github 存储库来演示该问题,但我应该明确表示这只是一个演示,我没有办法改变真正的子进程(即 Chromium,以防有人感兴趣)的行为!)。
你所尝试的方法是无法实现的。子进程可以与父进程共享文件描述符,但是当在 docker 内运行进程时,它首先被容器化。您可以使用命名管道而不是管道来实现此目的。命名管道类似于管道,但具有文件的接口。
据此,使用命名管道是可行的:
这是您发布的 Github 存储库的修改后的代码:
测试.js
import { spawn } from "child_process";
import path from 'path';
import { fileURLToPath } from 'url';
import {describe, jest} from '@jest/globals'
import fs from "fs";
const __dirname = path.dirname(fileURLToPath(import.meta.url));
describe("on docker container", () => {
let child;
jest.setTimeout(60000);
afterEach(() => child?.kill('SIGINT'));
it("responds with PONG! when PING? is sent", async () => {
child = spawn(
"/usr/bin/env",
[
"docker",
"run",
"--rm",
"--init",
`-v=${ __dirname }:/usr/app`,
"node:latest",
"node",
"/usr/app/ponger.js"
],
{
stdio: ['inherit', 'inherit', 'inherit']
}
);
await new Promise((resolve, reject) => {
const fifoWritePath = path.resolve(`${ __dirname }/named_pipe_in`);
const fifoReadPath = path.resolve(`${ __dirname }/named_pipe_out`);
const pipeWrite = fs.createWriteStream(fifoWritePath);
const pipeRead = fs.createReadStream(fifoReadPath);
pipeRead.on('data', (message) => {
console.log(message)
if (String(message) === "PONG!\n") {
resolve();
}
else {
reject();
}
});
pipeWrite.write("PING?\n");
});
});
});
Run Code Online (Sandbox Code Playgroud)
ponger.js
import fs from "fs";
import path from 'path';
const fifoReadPath = path.resolve('/usr/app/named_pipe_in');
const fifoWritePath = path.resolve('/usr/app/named_pipe_out');
const pipeRead = fs.createReadStream(fifoReadPath);
const pipeWrite = fs.createWriteStream(fifoWritePath);
pipeRead.on("data", (message) => {
if (String(message) === "PING?\n") {
pipeWrite.write("PONG!\n");
}
});
Run Code Online (Sandbox Code Playgroud)
npm test在项目目录中运行之前,执行以下命令:
mkfifo --mode=777 named_pipe_out
mkfifo --mode=777 named_pipe_out
Run Code Online (Sandbox Code Playgroud)
这些权限仅用于测试目的,请记住,这样的设置可能会破坏应用程序的安全性。
附言。我可以进一步详细说明为什么您的方法在这种情况下不起作用。
| 归档时间: |
|
| 查看次数: |
1090 次 |
| 最近记录: |