Skip to content

Instantly share code, notes, and snippets.

@marcj
Last active December 5, 2021 15:18
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcj/f026939066dc32568b05ed4a179c2222 to your computer and use it in GitHub Desktop.
Save marcj/f026939066dc32568b05ed4a179c2222 to your computer and use it in GitHub Desktop.
Dockerode Docker run with STDIN in Node.Js
import * as Dockerode from "dockerode";
import * as stream from "stream";
import {ContainerCreateOptions, HostConfig} from "dockerode";
export async function dockerRunWithStdIn(
docker: Dockerode,
stdin: NodeJS.ReadableStream | Buffer,
options: {name: string} & ContainerCreateOptions
): Promise<Buffer> {
return await new Promise<Buffer>(async (resolve, reject) => {
let stdOutAndStdErr: Buffer = Buffer.from('');
let currentChunk = Buffer.from('');
const attachStream = new stream.Writable({
write: function (chunk: Buffer, encoding, next) {
//header := [8]byte{STREAM_TYPE, 0, 0, 0, SIZE1, SIZE2, SIZE3, SIZE4}
currentChunk = Buffer.concat([currentChunk, chunk]);
//const isStdOut = currentChunk.readInt8() === 0x01;
//const isStdErr = currentChunk.readInt8() === 0x02;
const payloadSize: number = currentChunk.readUInt32BE(4);
while (currentChunk.byteLength >= 8 + payloadSize) {
stdOutAndStdErr = Buffer.concat([stdOutAndStdErr, currentChunk.slice(8, 8 + payloadSize)]);
currentChunk = currentChunk.slice(8 + payloadSize);
}
next();
},
});
async function removeContainer() {
try {
await docker.getContainer(options.name).remove({force: true});
} catch (error) {
}
}
docker.createContainer(Object.assign({
OpenStdin: true,
AttachStdin: true,
AttachStdout: true,
AttachStderr: true,
StdinOnce: true,
}, options), (err, container) => {
if (err || !container) {
reject(new Error(err || 'no container object'));
return;
}
container.attach({
stream: true,
stdin: true,
hijack: true,
stdout: true,
stderr: true,
}, (err, dockerStream) => {
if (err || !dockerStream) {
removeContainer();
reject(new Error(err));
return;
}
dockerStream.pipe(attachStream);
container.start((err, data) => {
if (err) {
removeContainer();
reject(new Error(err));
return;
}
if (stdin instanceof Buffer) {
dockerStream.end(stdin);
} else {
stdin.pipe(dockerStream);
}
container.wait(async (err, data) => {
if (err) {
removeContainer();
reject(err);
return;
}
resolve(stdOutAndStdErr);
});
});
});
});
});
}
import {dockerRunWithStdIn} from './docker-run.ts';
import * as Dockerode from "dockerode";
import * as fs from "fs";
(async () => {
const docker = new Dockerode;
const a = await dockerRunWithStdIn(
docker,
Buffer.from(`console.log('This is a test');console.error('Baad');console.log('done');`),
{
containerName: 'peter',
image: 'node:12-alpine',
hostConfig: {AutoRemove: true}
}
);
console.log('Answer:', a.toString());
})();
(async () => {
const docker = new Dockerode;
const file = fs.createReadStream(__dirname + '/test.ts');
const a = await dockerRunWithStdIn(docker, file, {
containerName: 'peter',
image: 'node:12-alpine',
cmd: ['wc', '-l'],
hostConfig: {AutoRemove: true}
});
console.log('Answer:', a.toString());
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment