-
|
I've used your example on running container exec. in the log, i can see the result of the execution, but i want to be able to use the result. But right now, it looks like it's just a log. my code: result is: the last json containing ID, Publickey, etc. is what i need, but that is not part of the returned value from runExec function. |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 3 replies
-
|
Hi, we have a few examples of this in dockerode tests :) |
Beta Was this translation helpful? Give feedback.
-
|
Replicating import stream from "stream";
import streamPromises from "stream/promises";
import Docker from "dockerode";
const docker = new Docker();
/**
* Interface for the output of a Docker exec command.
*/
interface DockerExecOutput {
/**
* Exit code of the process.
*/
exitCode: number | null;
/**
* Stdout of the process as a string.
*/
stderr: string;
/**
* Stderr of the process as a string.
*/
stdout: string;
}
/**
* Execute a command in a running Docker container.
*
* @param container container to execute the command in
* @param cmd command to execute
* @param opts options passed to the Docker Engine API
*/
export async function exec(
container: Docker.Container,
cmd: string[],
opts?: Docker.ExecCreateOptions,
): Promise<DockerExecOutput> {
const dockerExec = await container.exec({
...opts,
AttachStderr: true,
AttachStdout: true,
Cmd: cmd,
});
const dockerExecStream = await dockerExec.start({});
const stdoutStream = new stream.PassThrough();
const stderrStream = new stream.PassThrough();
docker.modem.demuxStream(dockerExecStream, stdoutStream, stderrStream);
dockerExecStream.resume();
await streamPromises.finished(dockerExecStream);
const stderr = stderrStream.read() as Buffer | undefined;
const stdout = stdoutStream.read() as Buffer | undefined;
const dockerExecInfo = await dockerExec.inspect();
return {
exitCode: dockerExecInfo.ExitCode,
stderr: stderr?.toString(),
stdout: stdout?.toString(),
};
} |
Beta Was this translation helpful? Give feedback.
-
import { PassThrough } from "node:stream";
import { finished } from "node:stream/promises";
export async function executeCommandInContainerBuffer(
command: string,
container: Container,
execCreateOptions: ExecCreateOptions = {},
execStartOptions: ExecStartOptions = {},
): Promise<CommandResult> {
const stdoutChunks: Buffer[] = [];
const stderrChunks: Buffer[] = [];
const outStream = new PassThrough();
const errStream = new PassThrough();
outStream.on("data", (chunk) => stdoutChunks.push(chunk));
errStream.on("data", (chunk) => stderrChunks.push(chunk));
try {
const exec = await container.exec({
Cmd: ["/bin/bash", "-c", command],
AttachStdout: true,
AttachStderr: true,
Tty: false,
...execCreateOptions,
});
const stream = await exec.start(execStartOptions);
container.modem.demuxStream(stream, outStream, errStream);
await finished(stream);
const stdOut = Buffer.concat(stdoutChunks).toString("utf8");
const stdErr = Buffer.concat(stderrChunks).toString("utf8");
const execInspectInfo = await exec.inspect();
const exitCode = execInspectInfo.ExitCode ?? 0;
// When Tty: true, stdout contains the error message from bad commands
// When Tty: false, stderr contains the error message from bad commands
return { exitCode, stdOut, stdErr };
} catch (error) {
logger.error(
error,
"Error executing command:%s in container:id %s",
command,
container.id,
);
return {
exitCode: -1,
stdErr: error instanceof Error ? error.message : String(error),
stdOut: "",
};
}
}
export async function executeCommandInContainerString(
command: string,
container: Container,
execCreateOptions: ExecCreateOptions = {},
execStartOptions: ExecStartOptions = {},
): Promise<CommandResult> {
const stdoutChunks: string[] = [];
const stderrChunks: string[] = [];
const outStream = new PassThrough();
const errStream = new PassThrough();
outStream.setEncoding("utf-8");
errStream.setEncoding("utf-8");
outStream.on("data", (chunk) => stdoutChunks.push(chunk));
errStream.on("data", (chunk) => stderrChunks.push(chunk));
try {
const exec = await container.exec({
Cmd: ["/bin/bash", "-c", command],
AttachStdout: true,
AttachStderr: true,
Tty: false,
...execCreateOptions,
});
const stream = await exec.start(execStartOptions);
container.modem.demuxStream(stream, outStream, errStream);
await finished(stream);
const stdOut = stdoutChunks.join("");
const stdErr = stderrChunks.join("");
const execInspectInfo = await exec.inspect();
const exitCode = execInspectInfo.ExitCode ?? 0;
// When Tty: true, stdout contains the error message from bad commands
// When Tty: false, stderr contains the error message from bad commands
return { exitCode, stdOut, stdErr };
} catch (error) {
logger.error(
error,
"Error executing command:%s in container:id %s",
command,
container.id,
);
return {
exitCode: -1,
stdErr: error instanceof Error ? error.message : String(error),
stdOut: "",
};
}
}
|
Beta Was this translation helpful? Give feedback.
Hi, we have a few examples of this in dockerode tests :)
I believe this is similar to what you want: https://github.com/apocas/dockerode/blob/v3.3.5/test/container.js#L635