diff --git a/src/docker/functions/run-in-container.ts b/src/docker/functions/run-in-container.ts index f9ddc1c73..f13e21e0f 100644 --- a/src/docker/functions/run-in-container.ts +++ b/src/docker/functions/run-in-container.ts @@ -3,8 +3,8 @@ import { DockerImageName } from "../../docker-image-name"; import { pullImage } from "./image/pull-image"; import { startContainer } from "./container/start-container"; import { attachContainer } from "./container/attach-container"; -import { inspectContainer } from "./container/inspect-container"; import Dockerode from "dockerode"; +import { streamToString } from "../../stream-utils"; export const runInContainer = async ( dockerode: Dockerode, @@ -13,43 +13,24 @@ export const runInContainer = async ( command: string[] ): Promise => { try { - const imageName = DockerImageName.fromString(image); - - await pullImage(dockerode, indexServerAddress, { imageName, force: false }); + await pullImage(dockerode, indexServerAddress, { imageName: DockerImageName.fromString(image), force: false }); log.debug(`Creating container: ${image} with command: ${command.join(" ")}`); - const container = await dockerode.createContainer({ Image: image, Cmd: command, HostConfig: { AutoRemove: true } }); + const container = await dockerode.createContainer({ Image: image, Cmd: command }); + log.debug(`Attaching to container: ${container.id}`); const stream = await attachContainer(dockerode, container); - const promise = new Promise((resolve) => { - const interval = setInterval(async () => { - const inspect = await inspectContainer(container); - - if (inspect.state.status === "exited") { - clearInterval(interval); - stream.destroy(); - } - }, 100); - - const chunks: string[] = []; - stream.on("data", (chunk) => chunks.push(chunk)); - stream.on("end", () => { - clearInterval(interval); - resolve(chunks.join("").trim()); - }); - }); - log.debug(`Starting container: ${container.id}`); await startContainer(container); + log.debug(`Waiting for container output: ${container.id}`); - const output = await promise; + const output = await streamToString(stream, { trim: true }); + + log.debug(`Removing container: ${container.id}`); + await container.remove({ force: true, v: true }); - if (output.length === 0) { - return undefined; - } else { - return output; - } + return output.length === 0 ? undefined : output; } catch (err) { log.error(`Failed to run command in container: "${command.join(" ")}", error: "${err}"`); return undefined; diff --git a/src/stream-utils.ts b/src/stream-utils.ts new file mode 100644 index 000000000..8efccc3ac --- /dev/null +++ b/src/stream-utils.ts @@ -0,0 +1,15 @@ +import { Readable } from "stream"; + +type Options = { trim: boolean }; + +export const streamToString = async (stream: Readable, options: Options = { trim: false }): Promise => { + const chunks = []; + + for await (const chunk of stream) { + chunks.push(Buffer.from(chunk)); + } + + const str = Buffer.concat(chunks).toString("utf-8"); + + return options.trim ? str.trim() : str; +};