testcontainers 7.24.0 → 8.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. package/README.md +22 -14
  2. package/dist/bound-ports.d.ts +3 -0
  3. package/dist/bound-ports.js +14 -0
  4. package/dist/docker/dockerode.js +2 -2
  5. package/dist/docker/functions/container/create-container.d.ts +2 -2
  6. package/dist/docker/functions/container/create-container.js +8 -8
  7. package/dist/docker/functions/container/inspect-container.d.ts +3 -4
  8. package/dist/docker/functions/container/inspect-container.js +10 -8
  9. package/dist/docker/get-docker-host.js +9 -5
  10. package/dist/docker/types.d.ts +3 -0
  11. package/dist/docker-compose/default-docker-compose-options.d.ts +1 -1
  12. package/dist/docker-compose/docker-compose.d.ts +2 -0
  13. package/dist/docker-compose/docker-compose.js +11 -0
  14. package/dist/docker-compose/functions/docker-compose-down.js +1 -1
  15. package/dist/docker-compose/functions/docker-compose-stop.js +1 -1
  16. package/dist/docker-compose/functions/docker-compose-up.js +1 -1
  17. package/dist/docker-compose-environment/docker-compose-environment.d.ts +0 -1
  18. package/dist/docker-compose-environment/docker-compose-environment.js +2 -10
  19. package/dist/generic-container/generic-container.d.ts +4 -1
  20. package/dist/generic-container/generic-container.js +14 -6
  21. package/dist/log-system-diagnostics.js +2 -21
  22. package/dist/modules/kafka/kafka-container.d.ts +6 -17
  23. package/dist/modules/kafka/kafka-container.js +56 -68
  24. package/dist/reaper.d.ts +1 -0
  25. package/dist/reaper.js +18 -12
  26. package/dist/testcontainers-properties-file.d.ts +1 -0
  27. package/dist/testcontainers-properties-file.js +35 -0
  28. package/package.json +3 -1
package/README.md CHANGED
@@ -18,12 +18,18 @@ npm i -D testcontainers
18
18
 
19
19
  The following environment variables are supported:
20
20
 
21
- - `DEBUG=testcontainers` See output
22
- - `DEBUG=testcontainers:containers` See container output
23
- - `DEBUG=testcontainers*` See all output
24
- - `DOCKER_HOST=tcp://docker:2375` Daemon socket to connect to
21
+ - `DEBUG=testcontainers` See testcontainers logs
22
+ - `DEBUG=testcontainers:containers` See container logs
23
+ - `DEBUG=testcontainers*` See all logs
24
+ - `DOCKER_HOST=tcp://docker:2375` Sets the URL of the docker daemon
25
+ - `DOCKER_TLS_VERIFY=1` When set to anything other than an empty string, enables TLS communication with the docker
26
+ daemon
27
+ - `DOCKER_CERT_PATH=/some/path` Configures the path to the ca.pem, cert.pem, and key.pem files used for TLS
28
+ verification. Defaults to ~/.docker
25
29
  - `TESTCONTAINERS_HOST_OVERRIDE=docker.svc.local` Docker's host on which ports are exposed
26
- - `TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE=/var/run/docker.sock` Path to Docker's socket. Used by [ryuk](#ryuk) and other [auxiliary containers](#auxiliary-containers) that need to perform Docker actions
30
+ - `TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE=/var/run/docker.sock` Path to Docker's socket. Used by [ryuk](#ryuk) and
31
+ other [auxiliary containers](#auxiliary-containers) that need to perform Docker actions
32
+ - `TESTCONTAINERS_RYUK_PRIVILEGED=true` Run [ryuk](#ryuk) as a privileged container
27
33
  - `TESTCONTAINERS_RYUK_DISABLED=true` Disable [ryuk](#ryuk)
28
34
  - `RYUK_CONTAINER_IMAGE=registry.mycompany.com/mirror/ryuk:0.3.0` Custom image for [ryuk](#ryuk)
29
35
  - `SSHD_CONTAINER_IMAGE=registry.mycompany.com/mirror/sshd:1.0.0` Custom image for [SSHd](#SSHd)
@@ -138,7 +144,7 @@ Creating a container with a command:
138
144
  const { GenericContainer } = require("testcontainers");
139
145
 
140
146
  const container = await new GenericContainer("alpine")
141
- .withCmd(["top"])
147
+ .withCmd(["sleep", "infinity"])
142
148
  .start();
143
149
  ```
144
150
 
@@ -148,7 +154,7 @@ Execute commands inside a running container:
148
154
  const { GenericContainer } = require("testcontainers");
149
155
 
150
156
  const container = await new GenericContainer("alpine")
151
- .withCmd(["top"])
157
+ .withCmd(["sleep", "infinity"])
152
158
  .start();
153
159
 
154
160
  const { output, exitCode } = await container.exec(["echo", "hello", "world"]);
@@ -265,12 +271,12 @@ const network = await new Network()
265
271
  .start();
266
272
 
267
273
  const container = await new GenericContainer("alpine")
268
- .withCmd(["top"])
274
+ .withCmd(["sleep", "infinity"])
269
275
  .withNetworkMode(network.getName())
270
276
  .start();
271
277
 
272
278
  const fooContainer = await new GenericContainer("alpine")
273
- .withCmd(["top"])
279
+ .withCmd(["sleep", "infinity"])
274
280
  .withNetworkMode(network.getName())
275
281
  .withNetworkAliases("foo", "bar")
276
282
  .start();
@@ -284,10 +290,10 @@ Add hostname mappings:
284
290
  const { GenericContainer } = require("testcontainers");
285
291
 
286
292
  const container = await new GenericContainer("alpine")
287
- .withExtraHosts([
293
+ .withExtraHosts(
288
294
  { host: "foo", ipAddress: "10.11.12.13" },
289
295
  { host: "bar", ipAddress: "11.12.13.14" }
290
- ])
296
+ )
291
297
  .start();
292
298
 
293
299
  expect((await container.exec(["nslookup", "foo"])).exitCode).toBe(0);
@@ -419,7 +425,7 @@ server.listen(8000);
419
425
  await TestContainers.exposeHostPorts(8000);
420
426
 
421
427
  const container = await new GenericContainer("alpine")
422
- .withCmd(["top"])
428
+ .withCmd(["sleep", "infinity"])
423
429
  .start();
424
430
 
425
431
  const { output } = await container.exec(["curl", `http://host.testcontainers.internal:8000`]);
@@ -652,8 +658,9 @@ Once started, this container keeps track of containers/images/networks/volumes c
652
658
  automatically clean them up 10s after connectivity with testcontainers is lost. This is useful for example if a test
653
659
  starts a container and then terminates unexpectedly, as it will be automatically removed.
654
660
 
655
- ryuk must be run with privileged mode; in CI environments such as Bit Bucket where this isn't supported, ryuk can be
656
- disabled by setting the environment variable `TESTCONTAINERS_RYUK_DISABLED` to `true`.
661
+ ryuk by default does not run privileged, if necessary this can be overridden by setting the environment variable
662
+ `TESTCONTAINERS_RYUK_PRIVILEGED` to `true`. If necessary, ryuk can be disabled enirely by setting the environment
663
+ variable `TESTCONTAINERS_RYUK_DISABLED` to `true`.
657
664
 
658
665
  ### SSHd
659
666
 
@@ -683,3 +690,4 @@ depending on file sizes and network constraints. It's unlikely that the default
683
690
  timeouts set by test frameworks are sufficient.
684
691
 
685
692
  - Increase the test timeout via the methods provided by the testing framework.
693
+
@@ -1,7 +1,10 @@
1
1
  import { Port } from "./port";
2
+ import { InspectResult } from "./docker/functions/container/inspect-container";
2
3
  export declare class BoundPorts {
3
4
  private readonly ports;
4
5
  getBinding(port: Port): Port;
5
6
  setBinding(key: Port, value: Port): void;
6
7
  iterator(): Iterable<[Port, Port]>;
8
+ filter(ports: Port[]): BoundPorts;
9
+ static fromInspectResult(inspectResult: InspectResult): BoundPorts;
7
10
  }
@@ -18,5 +18,19 @@ class BoundPorts {
18
18
  iterator() {
19
19
  return this.ports;
20
20
  }
21
+ filter(ports) {
22
+ const boundPorts = new BoundPorts();
23
+ for (const [internalPort, hostPort] of this.iterator()) {
24
+ if (ports.includes(internalPort)) {
25
+ boundPorts.setBinding(internalPort, hostPort);
26
+ }
27
+ }
28
+ return boundPorts;
29
+ }
30
+ static fromInspectResult(inspectResult) {
31
+ const boundPorts = new BoundPorts();
32
+ Object.entries(inspectResult.ports).forEach(([internalPort, hostPort]) => boundPorts.setBinding(parseInt(internalPort), hostPort));
33
+ return boundPorts;
34
+ }
21
35
  }
22
36
  exports.BoundPorts = BoundPorts;
@@ -5,6 +5,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.dockerode = void 0;
7
7
  const dockerode_1 = __importDefault(require("dockerode"));
8
- const logger_1 = require("../logger");
9
- logger_1.log.debug("Creating new Docker instance");
8
+ const testcontainers_properties_file_1 = require("../testcontainers-properties-file");
9
+ testcontainers_properties_file_1.loadTestcontainersPropertiesFile();
10
10
  exports.dockerode = new dockerode_1.default();
@@ -1,6 +1,6 @@
1
1
  import { DockerImageName } from "../../../docker-image-name";
2
- import { BoundPorts } from "../../../bound-ports";
3
2
  import Dockerode from "dockerode";
3
+ import { Port } from "../../../port";
4
4
  import { BindMount, Command, ContainerName, Env, ExtraHost, HealthCheck, NetworkMode, TmpFs } from "../../types";
5
5
  export declare type CreateContainerOptions = {
6
6
  imageName: DockerImageName;
@@ -8,7 +8,7 @@ export declare type CreateContainerOptions = {
8
8
  cmd: Command[];
9
9
  bindMounts: BindMount[];
10
10
  tmpFs: TmpFs;
11
- boundPorts: BoundPorts;
11
+ exposedPorts: Port[];
12
12
  name?: ContainerName;
13
13
  networkMode?: NetworkMode;
14
14
  healthCheck?: HealthCheck;
@@ -21,7 +21,7 @@ const createContainer = (options) => __awaiter(void 0, void 0, void 0, function*
21
21
  User: options.user,
22
22
  Image: options.imageName.toString(),
23
23
  Env: getEnv(options.env),
24
- ExposedPorts: getExposedPorts(options.boundPorts),
24
+ ExposedPorts: getExposedPorts(options.exposedPorts),
25
25
  Cmd: options.cmd,
26
26
  Labels: create_labels_1.createLabels(options.imageName),
27
27
  // @ts-ignore
@@ -31,7 +31,7 @@ const createContainer = (options) => __awaiter(void 0, void 0, void 0, function*
31
31
  ExtraHosts: getExtraHosts(options.extraHosts),
32
32
  AutoRemove: options.autoRemove,
33
33
  NetworkMode: options.networkMode,
34
- PortBindings: getPortBindings(options.boundPorts),
34
+ PortBindings: getPortBindings(options.exposedPorts),
35
35
  Binds: getBindMounts(options.bindMounts),
36
36
  Tmpfs: options.tmpFs,
37
37
  LogConfig: getLogConfig(options.useDefaultLogDriver),
@@ -46,20 +46,20 @@ const createContainer = (options) => __awaiter(void 0, void 0, void 0, function*
46
46
  });
47
47
  exports.createContainer = createContainer;
48
48
  const getEnv = (env) => Object.entries(env).reduce((dockerodeEnvironment, [key, value]) => [...dockerodeEnvironment, `${key}=${value}`], []);
49
- const getExposedPorts = (boundPorts) => {
49
+ const getExposedPorts = (exposedPorts) => {
50
50
  const dockerodeExposedPorts = {};
51
- for (const [internalPort] of boundPorts.iterator()) {
52
- dockerodeExposedPorts[internalPort.toString()] = {};
51
+ for (const exposedPort of exposedPorts) {
52
+ dockerodeExposedPorts[exposedPort.toString()] = {};
53
53
  }
54
54
  return dockerodeExposedPorts;
55
55
  };
56
56
  const getExtraHosts = (extraHosts) => {
57
57
  return extraHosts.map((extraHost) => `${extraHost.host}:${extraHost.ipAddress}`);
58
58
  };
59
- const getPortBindings = (boundPorts) => {
59
+ const getPortBindings = (exposedPorts) => {
60
60
  const dockerodePortBindings = {};
61
- for (const [internalPort, hostPort] of boundPorts.iterator()) {
62
- dockerodePortBindings[internalPort.toString()] = [{ HostPort: hostPort.toString() }];
61
+ for (const exposedPort of exposedPorts) {
62
+ dockerodePortBindings[exposedPort] = [{ HostPort: "0" }];
63
63
  }
64
64
  return dockerodePortBindings;
65
65
  };
@@ -1,10 +1,9 @@
1
- import { ContainerName, HealthCheckStatus, NetworkSettings } from "../../types";
2
- import { Port } from "../../../port";
1
+ import { ContainerName, HealthCheckStatus, NetworkSettings, Ports } from "../../types";
3
2
  import Dockerode from "dockerode";
4
3
  export declare type InspectResult = {
5
4
  name: ContainerName;
6
- internalPorts: Port[];
7
- hostPorts: Port[];
5
+ hostname: string;
6
+ ports: Ports;
8
7
  healthCheckStatus: HealthCheckStatus;
9
8
  networkSettings: {
10
9
  [networkName: string]: NetworkSettings;
@@ -15,9 +15,9 @@ const inspectContainer = (container) => __awaiter(void 0, void 0, void 0, functi
15
15
  try {
16
16
  const inspectResult = yield container.inspect();
17
17
  return {
18
- hostPorts: getHostPorts(inspectResult),
19
- internalPorts: getInternalPorts(inspectResult),
20
- name: getName(inspectResult),
18
+ name: inspectResult.Name,
19
+ hostname: inspectResult.Config.Hostname,
20
+ ports: getPorts(inspectResult),
21
21
  healthCheckStatus: getHealthCheckStatus(inspectResult),
22
22
  networkSettings: getNetworkSettings(inspectResult),
23
23
  state: { status: inspectResult.State.Status, running: inspectResult.State.Running },
@@ -29,11 +29,13 @@ const inspectContainer = (container) => __awaiter(void 0, void 0, void 0, functi
29
29
  }
30
30
  });
31
31
  exports.inspectContainer = inspectContainer;
32
- const getHostPorts = (inspectInfo) => Object.values(inspectInfo.NetworkSettings.Ports)
33
- .filter((portsArray) => portsArray !== null)
34
- .map((portsArray) => Number(portsArray[0].HostPort));
35
- const getInternalPorts = (inspectInfo) => Object.keys(inspectInfo.NetworkSettings.Ports).map((port) => Number(port.split("/")[0]));
36
- const getName = (inspectInfo) => inspectInfo.Name;
32
+ const getPorts = (inspectInfo) => Object.entries(inspectInfo.NetworkSettings.Ports)
33
+ .filter(([, hostPorts]) => hostPorts !== null)
34
+ .map(([internalPort, hostPorts]) => {
35
+ const hostPort = hostPorts[0].HostPort;
36
+ return { [parseInt(internalPort.split("/")[0])]: parseInt(hostPort) };
37
+ })
38
+ .reduce((acc, curr) => (Object.assign(Object.assign({}, acc), curr)), {});
37
39
  const getHealthCheckStatus = (inspectResult) => {
38
40
  const health = inspectResult.State.Health;
39
41
  if (health === undefined) {
@@ -16,16 +16,15 @@ exports.getDockerHost = void 0;
16
16
  const logger_1 = require("../logger");
17
17
  const run_in_container_1 = require("./functions/run-in-container");
18
18
  const fs_1 = __importDefault(require("fs"));
19
+ const url_1 = require("url");
19
20
  const DEFAULT_HOST = "localhost";
20
21
  const getDockerHost = (dockerode) => __awaiter(void 0, void 0, void 0, function* () {
21
- if (process.env.DOCKER_HOST) {
22
- logger_1.log.info(`Detected DOCKER_HOST environment variable: ${process.env.DOCKER_HOST}`);
23
- }
24
22
  for (const [hostStrategyName, hostStrategy] of Object.entries(hostStrategies(dockerode))) {
25
23
  const result = yield hostStrategy();
26
24
  if (result) {
27
- logger_1.log.info(`Docker host strategy ${hostStrategyName}: ${result}`);
28
- return result;
25
+ const hostname = result === DEFAULT_HOST ? DEFAULT_HOST : new url_1.URL(result).hostname;
26
+ logger_1.log.info(`Docker host strategy ${hostStrategyName}: ${hostname}`);
27
+ return hostname;
29
28
  }
30
29
  }
31
30
  logger_1.log.info(`Docker host strategy FALLBACK: ${DEFAULT_HOST}`);
@@ -33,6 +32,11 @@ const getDockerHost = (dockerode) => __awaiter(void 0, void 0, void 0, function*
33
32
  });
34
33
  exports.getDockerHost = getDockerHost;
35
34
  const hostStrategies = (dockerode) => ({
35
+ DOCKER_HOST: () => __awaiter(void 0, void 0, void 0, function* () {
36
+ if (process.env.DOCKER_HOST) {
37
+ return process.env.DOCKER_HOST;
38
+ }
39
+ }),
36
40
  MODEM: () => __awaiter(void 0, void 0, void 0, function* () { return dockerode.modem.host; }),
37
41
  TESTCONTAINERS_HOST_OVERRIDE: () => __awaiter(void 0, void 0, void 0, function* () { return process.env["TESTCONTAINERS_HOST_OVERRIDE"]; }),
38
42
  OUTSIDE_CONTAINER: () => __awaiter(void 0, void 0, void 0, function* () {
@@ -28,6 +28,9 @@ export declare type ExtraHost = {
28
28
  };
29
29
  export declare type NetworkMode = string;
30
30
  export declare type ContainerName = string;
31
+ export declare type Ports = {
32
+ [internalPort: number]: number;
33
+ };
31
34
  export declare type AuthConfig = {
32
35
  username: string;
33
36
  password: string;
@@ -1,3 +1,3 @@
1
- import { IDockerComposeOptions } from "docker-compose";
1
+ import { IDockerComposeOptions } from "./docker-compose";
2
2
  import { DockerComposeOptions } from "./docker-compose-options";
3
3
  export declare const defaultDockerComposeOptions: ({ env, ...options }: DockerComposeOptions) => Partial<IDockerComposeOptions>;
@@ -0,0 +1,2 @@
1
+ export { upMany, upAll, down, stop, version } from "docker-compose";
2
+ export type { IDockerComposeOptions } from "docker-compose";
@@ -0,0 +1,11 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.version = exports.stop = exports.down = exports.upAll = exports.upMany = void 0;
4
+ const testcontainers_properties_file_1 = require("../testcontainers-properties-file");
5
+ testcontainers_properties_file_1.loadTestcontainersPropertiesFile();
6
+ var docker_compose_1 = require("docker-compose");
7
+ Object.defineProperty(exports, "upMany", { enumerable: true, get: function () { return docker_compose_1.upMany; } });
8
+ Object.defineProperty(exports, "upAll", { enumerable: true, get: function () { return docker_compose_1.upAll; } });
9
+ Object.defineProperty(exports, "down", { enumerable: true, get: function () { return docker_compose_1.down; } });
10
+ Object.defineProperty(exports, "stop", { enumerable: true, get: function () { return docker_compose_1.stop; } });
11
+ Object.defineProperty(exports, "version", { enumerable: true, get: function () { return docker_compose_1.version; } });
@@ -10,9 +10,9 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.dockerComposeDown = void 0;
13
- const docker_compose_1 = require("docker-compose");
14
13
  const logger_1 = require("../../logger");
15
14
  const default_docker_compose_options_1 = require("../default-docker-compose-options");
15
+ const docker_compose_1 = require("../docker-compose");
16
16
  const dockerComposeDown = (options) => __awaiter(void 0, void 0, void 0, function* () {
17
17
  logger_1.log.info(`Downing DockerCompose environment`);
18
18
  try {
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.dockerComposeStop = void 0;
13
13
  const logger_1 = require("../../logger");
14
- const docker_compose_1 = require("docker-compose");
14
+ const docker_compose_1 = require("../docker-compose");
15
15
  const default_docker_compose_options_1 = require("../default-docker-compose-options");
16
16
  const dockerComposeStop = (options) => __awaiter(void 0, void 0, void 0, function* () {
17
17
  logger_1.log.info(`Stopping DockerCompose environment`);
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.dockerComposeUp = void 0;
13
13
  const logger_1 = require("../../logger");
14
- const docker_compose_1 = require("docker-compose");
14
+ const docker_compose_1 = require("../docker-compose");
15
15
  const default_docker_compose_options_1 = require("../default-docker-compose-options");
16
16
  const docker_compose_down_1 = require("./docker-compose-down");
17
17
  const dockerComposeUp = (options, services) => __awaiter(void 0, void 0, void 0, function* () {
@@ -20,7 +20,6 @@ export declare class DockerComposeEnvironment {
20
20
  withWaitStrategy(containerName: string, waitStrategy: WaitStrategy): this;
21
21
  withStartupTimeout(startupTimeout: number): this;
22
22
  up(services?: Array<string>): Promise<StartedDockerComposeEnvironment>;
23
- private getBoundPorts;
24
23
  private waitForContainer;
25
24
  private getWaitStrategy;
26
25
  }
@@ -80,10 +80,7 @@ class DockerComposeEnvironment {
80
80
  commandOptions.push("--no-recreate");
81
81
  }
82
82
  const composeOptions = [];
83
- this.profiles.forEach((profile) => {
84
- composeOptions.push("--profile");
85
- composeOptions.push(profile);
86
- });
83
+ this.profiles.forEach((profile) => composeOptions.push("--profile", profile));
87
84
  yield docker_compose_up_1.dockerComposeUp(Object.assign(Object.assign({}, options), { commandOptions, composeOptions, env: this.env }), services);
88
85
  const startedContainers = (yield list_containers_1.listContainers()).filter((container) => container.Labels["com.docker.compose.project"] === this.projectName);
89
86
  const startedContainerNames = startedContainers.reduce((containerNames, startedContainer) => [
@@ -98,7 +95,7 @@ class DockerComposeEnvironment {
98
95
  .on("data", (data) => logger_1.containerLog.trace(`${containerName}: ${data}`))
99
96
  .on("err", (data) => logger_1.containerLog.error(`${containerName}: ${data}`));
100
97
  const inspectResult = yield inspect_container_1.inspectContainer(container);
101
- const boundPorts = this.getBoundPorts(startedContainer);
98
+ const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(inspectResult);
102
99
  try {
103
100
  logger_1.log.info(`Waiting for container ${containerName} to be ready`);
104
101
  yield this.waitForContainer(container, containerName, boundPorts);
@@ -123,11 +120,6 @@ class DockerComposeEnvironment {
123
120
  return new started_docker_compose_environment_1.StartedDockerComposeEnvironment(startedGenericContainers, Object.assign(Object.assign({}, options), { composeOptions, env: this.env }));
124
121
  });
125
122
  }
126
- getBoundPorts(containerInfo) {
127
- const boundPorts = new bound_ports_1.BoundPorts();
128
- containerInfo.Ports.filter((port) => port.PublicPort !== undefined).forEach((port) => boundPorts.setBinding(port.PrivatePort, port.PublicPort));
129
- return boundPorts;
130
- }
131
123
  waitForContainer(container, containerName, boundPorts) {
132
124
  return __awaiter(this, void 0, void 0, function* () {
133
125
  const waitStrategy = this.getWaitStrategy(yield docker_host_1.dockerHost, container, containerName);
@@ -7,6 +7,7 @@ import { StartedTestContainer, TestContainer } from "../test-container";
7
7
  import { WaitStrategy } from "../wait-strategy";
8
8
  import { Readable } from "stream";
9
9
  import { BindMode, BindMount, BuildContext, Command, ContainerName, Dir, Env, EnvKey, EnvValue, ExtraHost, HealthCheck, NetworkMode, TmpFs } from "../docker/types";
10
+ import { InspectResult } from "../docker/functions/container/inspect-container";
10
11
  import { GenericContainerBuilder } from "./generic-container-builder";
11
12
  export declare class GenericContainer implements TestContainer {
12
13
  readonly image: string;
@@ -31,7 +32,9 @@ export declare class GenericContainer implements TestContainer {
31
32
  protected tarToCopy?: archiver.Archiver;
32
33
  private extraHosts;
33
34
  constructor(image: string);
35
+ protected preStart?(): Promise<void>;
34
36
  start(): Promise<StartedTestContainer>;
37
+ protected postStart?(container: StartedTestContainer, inspectResult: InspectResult, boundPorts: BoundPorts): Promise<void>;
35
38
  withCmd(cmd: Command[]): this;
36
39
  withName(name: ContainerName): this;
37
40
  withEnv(key: EnvKey, value: EnvValue): this;
@@ -40,6 +43,7 @@ export declare class GenericContainer implements TestContainer {
40
43
  withNetworkAliases(...networkAliases: string[]): this;
41
44
  withExtraHosts(...extraHosts: ExtraHost[]): this;
42
45
  withExposedPorts(...ports: Port[]): this;
46
+ protected addExposedPorts(...ports: Port[]): this;
43
47
  withBindMount(source: Dir, target: Dir, bindMode?: BindMode): this;
44
48
  withHealthCheck(healthCheck: HealthCheck): this;
45
49
  withStartupTimeout(startupTimeout: number): this;
@@ -52,7 +56,6 @@ export declare class GenericContainer implements TestContainer {
52
56
  withCopyFileToContainer(sourcePath: string, containerPath: string): this;
53
57
  withCopyContentToContainer(content: string | Buffer | Readable, containerPath: string): this;
54
58
  protected getTarToCopy(): archiver.Archiver;
55
- protected preCreate?(boundPorts: BoundPorts): Promise<void>;
56
59
  private waitForContainer;
57
60
  private getWaitStrategy;
58
61
  }
@@ -14,8 +14,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.GenericContainer = void 0;
16
16
  const archiver_1 = __importDefault(require("archiver"));
17
+ const bound_ports_1 = require("../bound-ports");
17
18
  const logger_1 = require("../logger");
18
- const port_binder_1 = require("../port-binder");
19
19
  const port_check_1 = require("../port-check");
20
20
  const pull_policy_1 = require("../pull-policy");
21
21
  const reaper_1 = require("../reaper");
@@ -61,12 +61,11 @@ class GenericContainer {
61
61
  force: this.pullPolicy.shouldPull(),
62
62
  authConfig: yield registry_auth_locator_1.getAuthConfig(this.imageName.registry),
63
63
  });
64
- const boundPorts = yield new port_binder_1.PortBinder().bind(this.ports);
65
64
  if (!this.imageName.isReaper()) {
66
65
  yield reaper_1.ReaperInstance.getInstance();
67
66
  }
68
- if (this.preCreate) {
69
- yield this.preCreate(boundPorts);
67
+ if (this.preStart) {
68
+ yield this.preStart();
70
69
  }
71
70
  if (!this.imageName.isHelperContainer() && port_forwarder_1.PortForwarderInstance.isRunning()) {
72
71
  const portForwarder = yield port_forwarder_1.PortForwarderInstance.getInstance();
@@ -78,7 +77,7 @@ class GenericContainer {
78
77
  cmd: this.cmd,
79
78
  bindMounts: this.bindMounts,
80
79
  tmpFs: this.tmpFs,
81
- boundPorts,
80
+ exposedPorts: this.ports,
82
81
  name: this.name,
83
82
  networkMode: this.networkAliases.length > 0 ? undefined : this.networkMode,
84
83
  healthCheck: this.healthCheck,
@@ -118,8 +117,13 @@ class GenericContainer {
118
117
  .on("data", (data) => logger_1.containerLog.trace(`${container.id}: ${data.trim()}`))
119
118
  .on("err", (data) => logger_1.containerLog.error(`${container.id}: ${data.trim()}`));
120
119
  const inspectResult = yield inspect_container_1.inspectContainer(container);
120
+ const boundPorts = bound_ports_1.BoundPorts.fromInspectResult(inspectResult).filter(this.ports);
121
121
  yield this.waitForContainer(container, boundPorts);
122
- return new started_generic_container_1.StartedGenericContainer(container, yield docker_host_1.dockerHost, inspectResult, boundPorts, inspectResult.name);
122
+ const startedContainer = new started_generic_container_1.StartedGenericContainer(container, yield docker_host_1.dockerHost, inspectResult, boundPorts, inspectResult.name);
123
+ if (this.postStart) {
124
+ yield this.postStart(startedContainer, inspectResult, boundPorts);
125
+ }
126
+ return startedContainer;
123
127
  });
124
128
  }
125
129
  withCmd(cmd) {
@@ -154,6 +158,10 @@ class GenericContainer {
154
158
  this.ports = ports;
155
159
  return this;
156
160
  }
161
+ addExposedPorts(...ports) {
162
+ this.ports.push(...ports);
163
+ return this;
164
+ }
157
165
  withBindMount(source, target, bindMode = "rw") {
158
166
  this.bindMounts.push({ source, target, bindMode });
159
167
  return this;
@@ -1,23 +1,4 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
- }) : (function(o, m, k, k2) {
6
- if (k2 === undefined) k2 = k;
7
- o[k2] = m[k];
8
- }));
9
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
10
- Object.defineProperty(o, "default", { enumerable: true, value: v });
11
- }) : function(o, v) {
12
- o["default"] = v;
13
- });
14
- var __importStar = (this && this.__importStar) || function (mod) {
15
- if (mod && mod.__esModule) return mod;
16
- var result = {};
17
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
18
- __setModuleDefault(result, mod);
19
- return result;
20
- };
21
2
  var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
22
3
  function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
23
4
  return new (P || (P = Promise))(function (resolve, reject) {
@@ -30,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
30
11
  Object.defineProperty(exports, "__esModule", { value: true });
31
12
  exports.logSystemDiagnostics = void 0;
32
13
  const logger_1 = require("./logger");
33
- const dockerCompose = __importStar(require("docker-compose"));
14
+ const docker_compose_1 = require("./docker-compose/docker-compose");
34
15
  const get_info_1 = require("./docker/functions/get-info");
35
16
  const logSystemDiagnostics = () => __awaiter(void 0, void 0, void 0, function* () {
36
17
  const info = {
@@ -51,7 +32,7 @@ const getNodeInfo = () => {
51
32
  const getDockerComposeInfo = () => __awaiter(void 0, void 0, void 0, function* () {
52
33
  try {
53
34
  return {
54
- version: (yield dockerCompose.version()).data.version,
35
+ version: (yield docker_compose_1.version()).data.version,
55
36
  };
56
37
  }
57
38
  catch (err) {
@@ -1,34 +1,23 @@
1
1
  import { GenericContainer } from "../../generic-container/generic-container";
2
2
  import { BoundPorts } from "../../bound-ports";
3
- import { StartedNetwork } from "../../network";
4
3
  import { Port } from "../../port";
5
- import { StartedTestContainer, StoppedTestContainer } from "../..";
6
- import { StopOptions } from "../../test-container";
4
+ import { StartedTestContainer } from "../..";
7
5
  import { AbstractStartedContainer } from "../abstract-started-container";
8
6
  import { Host } from "../../docker/types";
7
+ import { InspectResult } from "../../docker/functions/container/inspect-container";
9
8
  export declare const KAFKA_IMAGE = "confluentinc/cp-kafka:5.5.4";
10
- export declare const ZK_IMAGE = "confluentinc/cp-zookeeper:5.5.4";
11
9
  export declare class KafkaContainer extends GenericContainer {
12
- private readonly zooKeeperImage;
13
- private readonly host;
14
10
  private readonly uuid;
15
11
  private readonly portGenerator;
16
12
  private isZooKeeperProvided;
17
13
  private zooKeeperHost?;
18
14
  private zooKeeperPort?;
19
- private network?;
20
- private zooKeeperContainer?;
21
- constructor(image?: string, host?: Host, zooKeeperImage?: string);
15
+ constructor(image?: string);
22
16
  withZooKeeper(host: Host, port: Port): this;
23
- protected preCreate(boundPorts: BoundPorts): Promise<void>;
17
+ protected preStart(): Promise<void>;
24
18
  start(): Promise<StartedKafkaContainer>;
19
+ protected postStart(container: StartedTestContainer, inspectResult: InspectResult, boundPorts: BoundPorts): Promise<void>;
25
20
  }
26
21
  export declare class StartedKafkaContainer extends AbstractStartedContainer {
27
- private readonly network?;
28
- private readonly zooKeeperContainer?;
29
- private readonly zooKeeperPort?;
30
- constructor(startedTestContainer: StartedTestContainer, network?: StartedNetwork | undefined, zooKeeperContainer?: StartedTestContainer | undefined, zooKeeperPort?: number | undefined);
31
- stop(options?: Partial<StopOptions>): Promise<StoppedTestContainer>;
32
- getZookeeperName(): string | undefined;
33
- getZookeeperPort(): number | undefined;
22
+ constructor(startedTestContainer: StartedTestContainer);
34
23
  }
@@ -9,26 +9,33 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.StartedKafkaContainer = exports.KafkaContainer = exports.ZK_IMAGE = exports.KAFKA_IMAGE = void 0;
12
+ exports.StartedKafkaContainer = exports.KafkaContainer = exports.KAFKA_IMAGE = void 0;
13
13
  const generic_container_1 = require("../../generic-container/generic-container");
14
- const network_1 = require("../../network");
15
14
  const uuid_1 = require("../../uuid");
16
- const logger_1 = require("../../logger");
17
15
  const abstract_started_container_1 = require("../abstract-started-container");
18
16
  const port_generator_1 = require("../../port-generator");
19
17
  const docker_host_1 = require("../../docker/docker-host");
20
18
  const KAFKA_PORT = 9093;
21
19
  const KAFKA_BROKER_PORT = 9092;
22
20
  exports.KAFKA_IMAGE = "confluentinc/cp-kafka:5.5.4";
23
- exports.ZK_IMAGE = "confluentinc/cp-zookeeper:5.5.4";
24
21
  class KafkaContainer extends generic_container_1.GenericContainer {
25
- constructor(image = exports.KAFKA_IMAGE, host, zooKeeperImage = exports.ZK_IMAGE) {
22
+ constructor(image = exports.KAFKA_IMAGE) {
26
23
  super(image);
27
- this.zooKeeperImage = zooKeeperImage;
28
24
  this.uuid = new uuid_1.RandomUuid();
29
25
  this.portGenerator = new port_generator_1.RandomUniquePortGenerator();
30
26
  this.isZooKeeperProvided = false;
31
- this.host = host === undefined ? this.uuid.nextUuid() : host;
27
+ this.withExposedPorts(KAFKA_PORT)
28
+ .withStartupTimeout(180000)
29
+ .withEnv("KAFKA_LISTENERS", `PLAINTEXT://0.0.0.0:${KAFKA_PORT},BROKER://0.0.0.0:${KAFKA_BROKER_PORT}`)
30
+ .withEnv("KAFKA_LISTENER_SECURITY_PROTOCOL_MAP", "BROKER:PLAINTEXT,PLAINTEXT:PLAINTEXT")
31
+ .withEnv("KAFKA_INTER_BROKER_LISTENER_NAME", "BROKER")
32
+ .withEnv("KAFKA_BROKER_ID", "1")
33
+ .withEnv("KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR", "1")
34
+ .withEnv("KAFKA_OFFSETS_TOPIC_NUM_PARTITIONS", "1")
35
+ .withEnv("KAFKA_TRANSACTION_STATE_LOG_MIN_ISR", "1")
36
+ .withEnv("KAFKA_LOG_FLUSH_INTERVAL_MESSAGES", "9223372036854775807")
37
+ .withEnv("KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS", "0")
38
+ .withEnv("KAFKA_CONFLUENT_SUPPORT_METRICS_ENABLE", "false");
32
39
  }
33
40
  withZooKeeper(host, port) {
34
41
  this.isZooKeeperProvided = true;
@@ -36,10 +43,27 @@ class KafkaContainer extends generic_container_1.GenericContainer {
36
43
  this.zooKeeperPort = port;
37
44
  return this;
38
45
  }
39
- preCreate(boundPorts) {
46
+ preStart() {
40
47
  return __awaiter(this, void 0, void 0, function* () {
41
- const kafkaInternalPort = boundPorts.getBinding(KAFKA_PORT);
42
- this.withEnv("KAFKA_ADVERTISED_LISTENERS", `PLAINTEXT://${this.host}:${KAFKA_BROKER_PORT},EXTERNAL_LISTENER://${yield docker_host_1.dockerHost}:${kafkaInternalPort}`);
48
+ const network = this.networkMode && this.networkAliases.length > 0 ? this.networkAliases[0] : "localhost";
49
+ this.withEnv("KAFKA_ADVERTISED_LISTENERS", `BROKER://${network}:${KAFKA_BROKER_PORT}`);
50
+ let command = "#!/bin/bash\n";
51
+ if (this.isZooKeeperProvided) {
52
+ this.withEnv("KAFKA_ZOOKEEPER_CONNECT", `${this.zooKeeperHost}:${this.zooKeeperPort}`);
53
+ }
54
+ else {
55
+ this.zooKeeperHost = this.uuid.nextUuid();
56
+ this.zooKeeperPort = yield this.portGenerator.generatePort();
57
+ this.addExposedPorts(this.zooKeeperPort);
58
+ this.withEnv("KAFKA_ZOOKEEPER_CONNECT", `localhost:${this.zooKeeperPort}`);
59
+ command += "echo 'clientPort=" + this.zooKeeperPort + "' > zookeeper.properties\n";
60
+ command += "echo 'dataDir=/var/lib/zookeeper/data' >> zookeeper.properties\n";
61
+ command += "echo 'dataLogDir=/var/lib/zookeeper/log' >> zookeeper.properties\n";
62
+ command += "zookeeper-server-start zookeeper.properties &\n";
63
+ }
64
+ command += "echo '' > /etc/confluent/docker/ensure \n";
65
+ command += "/etc/confluent/docker/run \n";
66
+ this.withCmd(["sh", "-c", command]);
43
67
  });
44
68
  }
45
69
  start() {
@@ -47,71 +71,35 @@ class KafkaContainer extends generic_container_1.GenericContainer {
47
71
  start: { get: () => super.start }
48
72
  });
49
73
  return __awaiter(this, void 0, void 0, function* () {
50
- this.withName(this.host)
51
- .withStartupTimeout(180000)
52
- .withEnv("KAFKA_LISTENER_SECURITY_PROTOCOL_MAP", "PLAINTEXT:PLAINTEXT,EXTERNAL_LISTENER:PLAINTEXT")
53
- .withEnv("KAFKA_INTER_BROKER_LISTENER_NAME", "PLAINTEXT")
54
- .withEnv("KAFKA_BROKER_ID", "1")
55
- .withEnv("KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR", "1")
56
- .withEnv("KAFKA_CONFLUENT_SUPPORT_METRICS_ENABLE", "false")
57
- .withEnv("KAFKA_LISTENERS", `PLAINTEXT://0.0.0.0:${KAFKA_BROKER_PORT},EXTERNAL_LISTENER://0.0.0.0:${KAFKA_PORT}`);
58
- let zooKeeperPort;
59
- if (this.isZooKeeperProvided) {
60
- this.withEnv("KAFKA_ZOOKEEPER_CONNECT", `${this.zooKeeperHost}:${this.zooKeeperPort}`);
61
- }
62
- else {
63
- const zooKeeperHost = this.uuid.nextUuid();
64
- zooKeeperPort = yield this.portGenerator.generatePort();
65
- this.withEnv("KAFKA_ZOOKEEPER_CONNECT", `${zooKeeperHost}:${zooKeeperPort}`);
66
- const zookeeperContainer = new generic_container_1.GenericContainer(this.zooKeeperImage)
67
- .withName(zooKeeperHost)
68
- .withEnv("ZOOKEEPER_CLIENT_PORT", zooKeeperPort.toString());
69
- if (this.networkMode !== undefined) {
70
- zookeeperContainer.withNetworkMode(this.networkMode);
71
- }
72
- else {
73
- this.network = yield new network_1.Network().start();
74
- this.withNetworkMode(this.network.getName());
75
- zookeeperContainer.withNetworkMode(this.network.getName());
76
- }
77
- this.zooKeeperContainer = yield zookeeperContainer.start();
74
+ return new StartedKafkaContainer(yield _super.start.call(this));
75
+ });
76
+ }
77
+ postStart(container, inspectResult, boundPorts) {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ const brokerAdvertisedListener = `BROKER://${inspectResult.hostname}:${KAFKA_BROKER_PORT}`;
80
+ const bootstrapServers = `PLAINTEXT://${yield docker_host_1.dockerHost}:${boundPorts.getBinding(KAFKA_PORT)}`;
81
+ const { output, exitCode } = yield container.exec([
82
+ "kafka-configs",
83
+ "--alter",
84
+ "--bootstrap-server",
85
+ brokerAdvertisedListener,
86
+ "--entity-type",
87
+ "brokers",
88
+ "--entity-name",
89
+ this.env["KAFKA_BROKER_ID"],
90
+ "--add-config",
91
+ `advertised.listeners=[${bootstrapServers},${brokerAdvertisedListener}]`,
92
+ ]);
93
+ if (exitCode !== 0) {
94
+ throw new Error(`Kafka container configuration failed with exit code ${exitCode}: ${output}`);
78
95
  }
79
- return new StartedKafkaContainer(yield _super.start.call(this), this.network, this.zooKeeperContainer, zooKeeperPort);
80
96
  });
81
97
  }
82
98
  }
83
99
  exports.KafkaContainer = KafkaContainer;
84
100
  class StartedKafkaContainer extends abstract_started_container_1.AbstractStartedContainer {
85
- constructor(startedTestContainer, network, zooKeeperContainer, zooKeeperPort) {
101
+ constructor(startedTestContainer) {
86
102
  super(startedTestContainer);
87
- this.network = network;
88
- this.zooKeeperContainer = zooKeeperContainer;
89
- this.zooKeeperPort = zooKeeperPort;
90
- }
91
- stop(options) {
92
- const _super = Object.create(null, {
93
- stop: { get: () => super.stop }
94
- });
95
- return __awaiter(this, void 0, void 0, function* () {
96
- logger_1.log.debug("Stopping Kafka container");
97
- const stoppedContainer = yield _super.stop.call(this, options);
98
- if (this.zooKeeperContainer) {
99
- logger_1.log.debug("Stopping ZooKeeper container");
100
- yield this.zooKeeperContainer.stop(options);
101
- }
102
- if (this.network) {
103
- logger_1.log.debug("Stopping Kafka network");
104
- yield this.network.stop();
105
- }
106
- return stoppedContainer;
107
- });
108
- }
109
- getZookeeperName() {
110
- var _a;
111
- return (_a = this.zooKeeperContainer) === null || _a === void 0 ? void 0 : _a.getName();
112
- }
113
- getZookeeperPort() {
114
- return this.zooKeeperPort;
115
103
  }
116
104
  }
117
105
  exports.StartedKafkaContainer = StartedKafkaContainer;
package/dist/reaper.d.ts CHANGED
@@ -8,6 +8,7 @@ export declare class ReaperInstance {
8
8
  static getInstance(): Promise<Reaper>;
9
9
  static stopInstance(): Promise<void>;
10
10
  private static isEnabled;
11
+ private static isPrivileged;
11
12
  private static createDisabledInstance;
12
13
  private static createRealInstance;
13
14
  }
package/dist/reaper.js CHANGED
@@ -68,6 +68,9 @@ class ReaperInstance {
68
68
  static isEnabled() {
69
69
  return process.env.TESTCONTAINERS_RYUK_DISABLED !== "true";
70
70
  }
71
+ static isPrivileged() {
72
+ return process.env.TESTCONTAINERS_RYUK_PRIVILEGED === "true";
73
+ }
71
74
  static createDisabledInstance() {
72
75
  logger_1.log.debug(`Not creating new Reaper for session: ${session_id_1.sessionId}`);
73
76
  return Promise.resolve(new DisabledReaper());
@@ -77,33 +80,36 @@ class ReaperInstance {
77
80
  return __awaiter(this, void 0, void 0, function* () {
78
81
  const dockerSocket = (_a = process.env["TESTCONTAINERS_DOCKER_SOCKET_OVERRIDE"]) !== null && _a !== void 0 ? _a : "/var/run/docker.sock";
79
82
  logger_1.log.debug(`Creating new Reaper for session: ${session_id_1.sessionId}`);
80
- const container = yield new generic_container_1.GenericContainer(images_1.REAPER_IMAGE)
83
+ const container = new generic_container_1.GenericContainer(images_1.REAPER_IMAGE)
81
84
  .withName(`testcontainers-ryuk-${session_id_1.sessionId}`)
82
85
  .withExposedPorts(8080)
83
- .withBindMount(dockerSocket, "/var/run/docker.sock")
84
- .withPrivilegedMode()
85
- .start();
86
+ .withBindMount(dockerSocket, "/var/run/docker.sock");
87
+ if (this.isPrivileged()) {
88
+ container.withPrivilegedMode();
89
+ }
90
+ const startedContainer = yield container.start();
91
+ const containerId = startedContainer.getId();
86
92
  const host = yield docker_host_1.dockerHost;
87
- const port = container.getMappedPort(8080);
88
- logger_1.log.debug(`Connecting to Reaper ${container.getId()} on ${host}:${port}`);
93
+ const port = startedContainer.getMappedPort(8080);
94
+ logger_1.log.debug(`Connecting to Reaper ${containerId} on ${host}:${port}`);
89
95
  const socket = new net_1.Socket();
90
96
  socket.unref();
91
97
  socket
92
- .on("timeout", () => logger_1.log.error(`Reaper ${container.getId()} socket timed out`))
93
- .on("error", (err) => logger_1.log.error(`Reaper ${container.getId()} socket error: ${err}`))
98
+ .on("timeout", () => logger_1.log.error(`Reaper ${containerId} socket timed out`))
99
+ .on("error", (err) => logger_1.log.error(`Reaper ${containerId} socket error: ${err}`))
94
100
  .on("close", (hadError) => {
95
101
  if (hadError) {
96
- logger_1.log.error(`Connection to Reaper ${container.getId()} closed with error`);
102
+ logger_1.log.error(`Connection to Reaper ${containerId} closed with error`);
97
103
  }
98
104
  else {
99
- logger_1.log.warn(`Connection to Reaper ${container.getId()} closed`);
105
+ logger_1.log.warn(`Connection to Reaper ${containerId} closed`);
100
106
  }
101
107
  });
102
108
  return new Promise((resolve) => {
103
109
  socket.connect(port, host, () => {
104
- logger_1.log.debug(`Connected to Reaper ${container.getId()}`);
110
+ logger_1.log.debug(`Connected to Reaper ${containerId}`);
105
111
  socket.write(`label=org.testcontainers.session-id=${session_id_1.sessionId}\r\n`);
106
- const reaper = new RealReaper(container, socket);
112
+ const reaper = new RealReaper(startedContainer, socket);
107
113
  resolve(reaper);
108
114
  });
109
115
  });
@@ -0,0 +1 @@
1
+ export declare const loadTestcontainersPropertiesFile: () => void;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.loadTestcontainersPropertiesFile = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const logger_1 = require("./logger");
9
+ const os_1 = require("os");
10
+ const fs_1 = require("fs");
11
+ const properties_reader_1 = __importDefault(require("properties-reader"));
12
+ const loadTestcontainersPropertiesFile = () => {
13
+ const file = path_1.default.resolve(os_1.homedir(), ".testcontainers.properties");
14
+ if (fs_1.existsSync(file)) {
15
+ logger_1.log.debug("Found .testcontainers.properties file");
16
+ const string = fs_1.readFileSync(file, { encoding: "utf-8" });
17
+ const properties = properties_reader_1.default("").read(string);
18
+ const host = properties.get("docker.host");
19
+ if (host !== null) {
20
+ logger_1.log.debug(`Setting DOCKER_HOST to ${host}`);
21
+ process.env.DOCKER_HOST = host;
22
+ }
23
+ const tlsVerify = properties.get("docker.tls.verify");
24
+ if (tlsVerify !== null) {
25
+ logger_1.log.debug(`Setting DOCKER_TLS_VERIFY to ${tlsVerify}`);
26
+ process.env.DOCKER_TLS_VERIFY = `${tlsVerify}`;
27
+ }
28
+ const certPath = properties.get("docker.cert.path");
29
+ if (certPath !== null) {
30
+ logger_1.log.debug(`Setting DOCKER_CERT_PATH to ${certPath}`);
31
+ process.env.DOCKER_CERT_PATH = certPath;
32
+ }
33
+ }
34
+ };
35
+ exports.loadTestcontainersPropertiesFile = loadTestcontainersPropertiesFile;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "testcontainers",
3
3
  "author": "Cristian Greco",
4
- "version": "7.24.0",
4
+ "version": "8.0.0",
5
5
  "main": "dist/index",
6
6
  "types": "dist/index",
7
7
  "keywords": [
@@ -41,6 +41,7 @@
41
41
  "dockerode": "^3.3.1",
42
42
  "get-port": "^5.1.1",
43
43
  "glob": "^7.2.0",
44
+ "properties-reader": "^2.2.0",
44
45
  "slash": "^3.0.0",
45
46
  "ssh-remote-port-forward": "^1.0.4",
46
47
  "tar-fs": "^2.1.1"
@@ -54,6 +55,7 @@
54
55
  "@types/node": "^16.9.6",
55
56
  "@types/node-fetch": "^2.5.11",
56
57
  "@types/pg": "^8.6.1",
58
+ "@types/properties-reader": "^2.1.1",
57
59
  "@types/tar-fs": "^2.0.1",
58
60
  "@typescript-eslint/eslint-plugin": "^4.31.2",
59
61
  "@typescript-eslint/parser": "^4.31.2",