diff --git a/docs/features/compose.md b/docs/features/compose.md index 669a1899b..85aedbebd 100644 --- a/docs/features/compose.md +++ b/docs/features/compose.md @@ -142,6 +142,17 @@ const environment = await new DockerComposeEnvironment(composeFilePath, composeF .up(); ``` +### With custom client options + +See [docker-compose](https://github.com/PDMLab/docker-compose/) library. + +```javascript +const environment = await new DockerComposeEnvironment(composeFilePath, composeFile) + .withClientOptions({ executable: { standalone: true, executablePath: "/path/to/docker-compose" } }) + .up(); +``` + + ## Downing a Docker compose environment Testcontainers by default will not wait until the environment has downed. It will simply issue the down command and return immediately. This is to save time when running tests. diff --git a/packages/testcontainers/src/container-runtime/clients/compose/default-compose-options.ts b/packages/testcontainers/src/container-runtime/clients/compose/default-compose-options.ts index fafa25cb4..4c3240991 100644 --- a/packages/testcontainers/src/container-runtime/clients/compose/default-compose-options.ts +++ b/packages/testcontainers/src/container-runtime/clients/compose/default-compose-options.ts @@ -29,5 +29,6 @@ export function defaultComposeOptions( COMPOSE_PROJECT_NAME: options.projectName, ...{ ...environment, ...options.environment }, }, + executable: options.executable, }; } diff --git a/packages/testcontainers/src/container-runtime/clients/compose/types.ts b/packages/testcontainers/src/container-runtime/clients/compose/types.ts index 747fe0a43..9e50f5fec 100644 --- a/packages/testcontainers/src/container-runtime/clients/compose/types.ts +++ b/packages/testcontainers/src/container-runtime/clients/compose/types.ts @@ -8,8 +8,21 @@ export type ComposeOptions = { composeOptions?: string[]; environment?: NodeJS.ProcessEnv; logger?: Logger; + executable?: ComposeExecutableOptions; }; +export type ComposeExecutableOptions = + | { + executablePath: string; + options?: string[] | (string | string[])[]; + standalone?: never; + } + | { + executablePath?: string; + options?: never; + standalone: true; + }; + export type ComposeDownOptions = { timeout: number; removeVolumes: boolean; diff --git a/packages/testcontainers/src/container-runtime/index.ts b/packages/testcontainers/src/container-runtime/index.ts index 6717aaec5..d0332c0b5 100644 --- a/packages/testcontainers/src/container-runtime/index.ts +++ b/packages/testcontainers/src/container-runtime/index.ts @@ -1,6 +1,6 @@ export { getAuthConfig } from "./auth/get-auth-config"; export { ContainerRuntimeClient, getContainerRuntimeClient } from "./clients/client"; export { parseComposeContainerName } from "./clients/compose/parse-compose-container-name"; -export { ComposeDownOptions, ComposeOptions } from "./clients/compose/types"; +export { ComposeDownOptions, ComposeExecutableOptions, ComposeOptions } from "./clients/compose/types"; export { HostIp } from "./clients/types"; export { ImageName } from "./image-name"; diff --git a/packages/testcontainers/src/docker-compose-environment/docker-compose-environment.ts b/packages/testcontainers/src/docker-compose-environment/docker-compose-environment.ts index 252998ed2..40273b48b 100644 --- a/packages/testcontainers/src/docker-compose-environment/docker-compose-environment.ts +++ b/packages/testcontainers/src/docker-compose-environment/docker-compose-environment.ts @@ -1,6 +1,6 @@ import { ContainerInfo } from "dockerode"; import { containerLog, log, RandomUuid, Uuid } from "../common"; -import { getContainerRuntimeClient, parseComposeContainerName } from "../container-runtime"; +import { ComposeOptions, getContainerRuntimeClient, parseComposeContainerName } from "../container-runtime"; import { StartedGenericContainer } from "../generic-container/started-generic-container"; import { getReaper } from "../reaper/reaper"; import { Environment } from "../types"; @@ -26,6 +26,7 @@ export class DockerComposeEnvironment { private defaultWaitStrategy: WaitStrategy = Wait.forListeningPorts(); private waitStrategy: { [containerName: string]: WaitStrategy } = {}; private startupTimeoutMs?: number; + private clientOptions: Partial = {}; constructor(composeFilePath: string, composeFiles: string | string[], uuid: Uuid = new RandomUuid()) { this.composeFilePath = composeFilePath; @@ -84,19 +85,33 @@ export class DockerComposeEnvironment { return this; } + public withClientOptions( + options: Partial> + ): this { + this.clientOptions = { ...this.clientOptions, ...options }; + return this; + } + public async up(services?: Array): Promise { log.info(`Starting DockerCompose environment "${this.projectName}"...`); const client = await getContainerRuntimeClient(); const reaper = await getReaper(client); reaper.addComposeProject(this.projectName); + const { + composeOptions: clientComposeOptions = [], + commandOptions: clientCommandOptions = [], + ...remainingClientOptions + } = this.clientOptions; + const options = { + ...remainingClientOptions, filePath: this.composeFilePath, files: this.composeFiles, projectName: this.projectName, }; - const commandOptions = []; + const commandOptions = [...clientCommandOptions]; if (this.build) { commandOptions.push("--build"); } @@ -104,7 +119,7 @@ export class DockerComposeEnvironment { commandOptions.push("--no-recreate"); } - const composeOptions: string[] = []; + const composeOptions = [...clientComposeOptions]; if (this.environmentFile) { composeOptions.push("--env-file", this.environmentFile); }