testcontainers 8.15.0 → 8.16.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.
- package/README.md +82 -2
- package/dist/docker/functions/container/create-container.d.ts +5 -1
- package/dist/docker/functions/container/create-container.js +14 -0
- package/dist/docker/functions/container/exec-container.d.ts +1 -1
- package/dist/docker/functions/container/exec-container.js +10 -3
- package/dist/docker/functions/image/build-image.d.ts +1 -0
- package/dist/docker/functions/image/build-image.js +14 -9
- package/dist/docker/types.d.ts +6 -0
- package/dist/docker-compose/functions/docker-compose-down.d.ts +2 -1
- package/dist/docker-compose/functions/docker-compose-down.js +12 -2
- package/dist/docker-compose/functions/docker-compose-up.js +1 -1
- package/dist/docker-compose-environment/docker-compose-environment.js +1 -1
- package/dist/docker-compose-environment/started-docker-compose-environment.d.ts +2 -1
- package/dist/docker-compose-environment/started-docker-compose-environment.js +3 -2
- package/dist/docker-compose-environment/stopped-docker-compose-environment.d.ts +2 -1
- package/dist/docker-compose-environment/stopped-docker-compose-environment.js +3 -2
- package/dist/generic-container/generic-container-builder.d.ts +2 -0
- package/dist/generic-container/generic-container-builder.js +6 -0
- package/dist/generic-container/generic-container.d.ts +9 -1
- package/dist/generic-container/generic-container.js +20 -0
- package/dist/generic-container/started-generic-container.js +1 -2
- package/dist/logger.d.ts +1 -0
- package/dist/logger.js +2 -1
- package/dist/port-check.js +1 -1
- package/dist/test-container.d.ts +9 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,8 +5,6 @@
|
|
|
5
5
|
[](https://github.com/testcontainers/testcontainers-node/actions/workflows/node.js.yml)
|
|
6
6
|
[](https://www.npmjs.com/package/testcontainers)
|
|
7
7
|
[](https://www.npmjs.com/package/testcontainers)
|
|
8
|
-
[](https://foresight.thundra.live/testRuns/57175ecb-d5ac-4129-957a-9dd617fd27d0)
|
|
9
|
-
[](https://foresight.thundra.live/testruns/57175ecb-d5ac-4129-957a-9dd617fd27d0)
|
|
10
8
|
|
|
11
9
|
## Install
|
|
12
10
|
|
|
@@ -22,8 +20,11 @@ The following environment variables are supported:
|
|
|
22
20
|
|
|
23
21
|
- `DEBUG=testcontainers` Enable testcontainers logs
|
|
24
22
|
- `DEBUG=testcontainers:containers` Enable container logs
|
|
23
|
+
- `DEBUG=testcontainers:exec` Enable container exec logs
|
|
25
24
|
- `DEBUG=testcontainers*` Enable all logs
|
|
26
25
|
|
|
26
|
+
Note that you can enable specific loggers, e.g: `DEBUG=testcontainers,testcontainers:exec`.
|
|
27
|
+
|
|
27
28
|
### Docker
|
|
28
29
|
|
|
29
30
|
- `DOCKER_HOST=tcp://docker:2375` Sets the URL of the docker daemon
|
|
@@ -134,6 +135,16 @@ const container = await GenericContainer.fromDockerfile(buildContext, "my-docker
|
|
|
134
135
|
.build();
|
|
135
136
|
```
|
|
136
137
|
|
|
138
|
+
Build the image without using the cache:
|
|
139
|
+
|
|
140
|
+
```javascript
|
|
141
|
+
const { GenericContainer } = require("testcontainers");
|
|
142
|
+
|
|
143
|
+
const container = await GenericContainer.fromDockerfile(buildContext, "my-dockerfile")
|
|
144
|
+
.withCache(false)
|
|
145
|
+
.build();
|
|
146
|
+
```
|
|
147
|
+
|
|
137
148
|
Creating a container with multiple exposed ports:
|
|
138
149
|
|
|
139
150
|
```javascript
|
|
@@ -193,6 +204,16 @@ const container = await new GenericContainer("alpine")
|
|
|
193
204
|
.start();
|
|
194
205
|
```
|
|
195
206
|
|
|
207
|
+
Creating a container with entrypoint:
|
|
208
|
+
|
|
209
|
+
```javascript
|
|
210
|
+
const { GenericContainer } = require("testcontainers");
|
|
211
|
+
|
|
212
|
+
const container = await new GenericContainer("alpine")
|
|
213
|
+
.withEntrypoint(["cat"])
|
|
214
|
+
.start();
|
|
215
|
+
```
|
|
216
|
+
|
|
196
217
|
Execute commands inside a running container:
|
|
197
218
|
|
|
198
219
|
```javascript
|
|
@@ -242,6 +263,41 @@ const container = await new GenericContainer("postgres")
|
|
|
242
263
|
.start();
|
|
243
264
|
```
|
|
244
265
|
|
|
266
|
+
Creating a container with ulimits:
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
const { GenericContainer } = require("testcontainers");
|
|
270
|
+
|
|
271
|
+
const container = await new GenericContainer("aline")
|
|
272
|
+
.withUlimits({
|
|
273
|
+
memlock: {
|
|
274
|
+
hard: -1,
|
|
275
|
+
soft: -1
|
|
276
|
+
}
|
|
277
|
+
})
|
|
278
|
+
.start();
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Creating a container with added [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html):
|
|
282
|
+
|
|
283
|
+
```javascript
|
|
284
|
+
const { GenericContainer } = require("testcontainers");
|
|
285
|
+
|
|
286
|
+
const container = await new GenericContainer("aline")
|
|
287
|
+
.withAddedCapabilities("NET_ADMIN", "IPC_LOCK")
|
|
288
|
+
.start();
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
Creating a container with dropped [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html):
|
|
292
|
+
|
|
293
|
+
```javascript
|
|
294
|
+
const { GenericContainer } = require("testcontainers");
|
|
295
|
+
|
|
296
|
+
const container = await new GenericContainer("aline")
|
|
297
|
+
.withDroppedCapabilities("NET_ADMIN", "IPC_LOCK")
|
|
298
|
+
.start();
|
|
299
|
+
```
|
|
300
|
+
|
|
245
301
|
Copy a file to a container before it is started:
|
|
246
302
|
|
|
247
303
|
```javascript
|
|
@@ -666,6 +722,30 @@ const environment = await new DockerComposeEnvironment(composeFilePath, composeF
|
|
|
666
722
|
.up();
|
|
667
723
|
```
|
|
668
724
|
|
|
725
|
+
Testcontainers will not wait for an environment to down, to override:
|
|
726
|
+
|
|
727
|
+
```javascript
|
|
728
|
+
const { GenericContainer } = require("testcontainers");
|
|
729
|
+
|
|
730
|
+
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile).up();
|
|
731
|
+
|
|
732
|
+
await environment.down({
|
|
733
|
+
timeout: 10000
|
|
734
|
+
});
|
|
735
|
+
```
|
|
736
|
+
|
|
737
|
+
Testcontainers will remove associated volumes created by the environment when downed, to override:
|
|
738
|
+
|
|
739
|
+
```javascript
|
|
740
|
+
const { GenericContainer } = require("testcontainers");
|
|
741
|
+
|
|
742
|
+
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile).up();
|
|
743
|
+
|
|
744
|
+
await environment.down({
|
|
745
|
+
removeVolumes: false
|
|
746
|
+
});
|
|
747
|
+
```
|
|
748
|
+
|
|
669
749
|
## Wait Strategies
|
|
670
750
|
|
|
671
751
|
Ordinarily Testcontainers will wait for up to 60 seconds for the container's mapped network ports to start listening.
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { DockerImageName } from "../../../docker-image-name";
|
|
2
2
|
import Dockerode from "dockerode";
|
|
3
3
|
import { PortWithOptionalBinding } from "../../../port";
|
|
4
|
-
import { BindMount, Command, ContainerName, Env, ExtraHost, HealthCheck, Labels, NetworkMode, TmpFs } from "../../types";
|
|
4
|
+
import { BindMount, Command, ContainerName, Env, ExtraHost, HealthCheck, Labels, NetworkMode, TmpFs, Ulimits } from "../../types";
|
|
5
5
|
export declare type CreateContainerOptions = {
|
|
6
6
|
imageName: DockerImageName;
|
|
7
7
|
env: Env;
|
|
8
8
|
cmd: Command[];
|
|
9
|
+
entrypoint?: string[];
|
|
9
10
|
bindMounts: BindMount[];
|
|
10
11
|
tmpFs: TmpFs;
|
|
11
12
|
exposedPorts: PortWithOptionalBinding[];
|
|
@@ -19,6 +20,9 @@ export declare type CreateContainerOptions = {
|
|
|
19
20
|
autoRemove: boolean;
|
|
20
21
|
extraHosts: ExtraHost[];
|
|
21
22
|
ipcMode?: string;
|
|
23
|
+
ulimits?: Ulimits;
|
|
24
|
+
addedCapabilities?: string[];
|
|
25
|
+
droppedCapabilities?: string[];
|
|
22
26
|
user?: string;
|
|
23
27
|
};
|
|
24
28
|
export declare const createContainer: (options: CreateContainerOptions) => Promise<Dockerode.Container>;
|
|
@@ -25,6 +25,7 @@ const createContainer = (options) => __awaiter(void 0, void 0, void 0, function*
|
|
|
25
25
|
Env: getEnv(options.env),
|
|
26
26
|
ExposedPorts: getExposedPorts(options.exposedPorts),
|
|
27
27
|
Cmd: options.cmd,
|
|
28
|
+
Entrypoint: options.entrypoint,
|
|
28
29
|
Labels: (0, create_labels_1.createLabels)(options.reusable, options.imageName, options.labels),
|
|
29
30
|
// @ts-ignore
|
|
30
31
|
Healthcheck: getHealthCheck(options.healthCheck),
|
|
@@ -38,6 +39,9 @@ const createContainer = (options) => __awaiter(void 0, void 0, void 0, function*
|
|
|
38
39
|
Tmpfs: options.tmpFs,
|
|
39
40
|
LogConfig: getLogConfig(options.useDefaultLogDriver),
|
|
40
41
|
Privileged: options.privilegedMode,
|
|
42
|
+
Ulimits: getUlimits(options.ulimits),
|
|
43
|
+
CapAdd: options.addedCapabilities,
|
|
44
|
+
CapDrop: options.droppedCapabilities,
|
|
41
45
|
},
|
|
42
46
|
});
|
|
43
47
|
}
|
|
@@ -95,3 +99,13 @@ const getLogConfig = (useDefaultLogDriver) => {
|
|
|
95
99
|
Config: {},
|
|
96
100
|
};
|
|
97
101
|
};
|
|
102
|
+
const getUlimits = (ulimits) => {
|
|
103
|
+
if (!ulimits) {
|
|
104
|
+
return undefined;
|
|
105
|
+
}
|
|
106
|
+
return Object.entries(ulimits).map(([key, value]) => ({
|
|
107
|
+
Name: key,
|
|
108
|
+
Hard: value.hard,
|
|
109
|
+
Soft: value.soft,
|
|
110
|
+
}));
|
|
111
|
+
};
|
|
@@ -5,5 +5,5 @@ declare type ExecContainerOptions = {
|
|
|
5
5
|
stdin: boolean;
|
|
6
6
|
detach: boolean;
|
|
7
7
|
};
|
|
8
|
-
export declare const execContainer: (container: Dockerode.Container, command: Command[], options: ExecContainerOptions) => Promise<ExecResult>;
|
|
8
|
+
export declare const execContainer: (container: Dockerode.Container, command: Command[], options: ExecContainerOptions, shouldLog?: boolean) => Promise<ExecResult>;
|
|
9
9
|
export {};
|
|
@@ -8,10 +8,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
9
|
});
|
|
10
10
|
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
11
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
15
|
exports.execContainer = void 0;
|
|
13
16
|
const logger_1 = require("../../../logger");
|
|
14
|
-
const
|
|
17
|
+
const byline_1 = __importDefault(require("byline"));
|
|
18
|
+
const execContainer = (container, command, options, shouldLog = true) => __awaiter(void 0, void 0, void 0, function* () {
|
|
19
|
+
const chunks = [];
|
|
15
20
|
try {
|
|
16
21
|
const exec = yield container.exec({
|
|
17
22
|
Cmd: command,
|
|
@@ -19,14 +24,16 @@ const execContainer = (container, command, options) => __awaiter(void 0, void 0,
|
|
|
19
24
|
AttachStderr: true,
|
|
20
25
|
});
|
|
21
26
|
const stream = yield startExec(exec, options);
|
|
22
|
-
const chunks = [];
|
|
23
27
|
stream.on("data", (chunk) => chunks.push(chunk));
|
|
28
|
+
if (shouldLog) {
|
|
29
|
+
(0, byline_1.default)(stream).on("data", (line) => logger_1.execLog.trace(`${container.id}: ${line}`));
|
|
30
|
+
}
|
|
24
31
|
const exitCode = yield waitForExec(exec);
|
|
25
32
|
stream.destroy();
|
|
26
33
|
return { output: chunks.join(""), exitCode };
|
|
27
34
|
}
|
|
28
35
|
catch (err) {
|
|
29
|
-
logger_1.log.error(`Failed to exec container ${container.id} with command "${command.join(" ")}": ${err}`);
|
|
36
|
+
logger_1.log.error(`Failed to exec container ${container.id} with command "${command.join(" ")}": ${err}. Container output: ${chunks.join("")}`);
|
|
30
37
|
throw err;
|
|
31
38
|
}
|
|
32
39
|
});
|
|
@@ -37,21 +37,26 @@ const buildImage = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
|
37
37
|
},
|
|
38
38
|
});
|
|
39
39
|
const { dockerode } = yield (0, docker_client_1.dockerClient)();
|
|
40
|
-
|
|
41
|
-
.buildImage(tarStream, {
|
|
40
|
+
const buildImageOptions = {
|
|
42
41
|
dockerfile: options.dockerfileName,
|
|
42
|
+
// @ts-ignore
|
|
43
|
+
nocache: !options.cache,
|
|
43
44
|
buildargs: options.buildArgs,
|
|
44
45
|
t: options.imageName.toString(),
|
|
45
46
|
labels: (0, create_labels_1.createLabels)(false, options.imageName),
|
|
46
47
|
registryconfig: options.registryConfig,
|
|
47
48
|
pull: options.pullPolicy.shouldPull() ? "any" : undefined,
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
49
|
+
};
|
|
50
|
+
return new Promise((resolve) => {
|
|
51
|
+
dockerode
|
|
52
|
+
.buildImage(tarStream, buildImageOptions)
|
|
53
|
+
.then((stream) => (0, byline_1.default)(stream))
|
|
54
|
+
.then((stream) => {
|
|
55
|
+
stream.setEncoding("utf-8");
|
|
56
|
+
stream.on("data", (line) => logger_1.log.trace(`${options.imageName.toString()}: ${line}`));
|
|
57
|
+
stream.on("end", () => resolve());
|
|
58
|
+
});
|
|
59
|
+
});
|
|
55
60
|
}
|
|
56
61
|
catch (err) {
|
|
57
62
|
logger_1.log.error(`Failed to build image: ${err}`);
|
package/dist/docker/types.d.ts
CHANGED
|
@@ -15,6 +15,12 @@ export declare type BindMount = {
|
|
|
15
15
|
export declare type TmpFs = {
|
|
16
16
|
[dir in Dir]: Dir;
|
|
17
17
|
};
|
|
18
|
+
export declare type Ulimits = {
|
|
19
|
+
[name: string]: {
|
|
20
|
+
hard: number | undefined;
|
|
21
|
+
soft: number | undefined;
|
|
22
|
+
};
|
|
23
|
+
};
|
|
18
24
|
export declare type HealthCheck = {
|
|
19
25
|
test: string;
|
|
20
26
|
interval?: number;
|
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { DockerComposeOptions } from "../docker-compose-options";
|
|
2
|
-
|
|
2
|
+
import { DockerComposeDownOptions } from "../../test-container";
|
|
3
|
+
export declare const dockerComposeDown: (options: DockerComposeOptions, downOptions: DockerComposeDownOptions) => Promise<void>;
|
|
@@ -13,10 +13,10 @@ exports.dockerComposeDown = void 0;
|
|
|
13
13
|
const logger_1 = require("../../logger");
|
|
14
14
|
const default_docker_compose_options_1 = require("../default-docker-compose-options");
|
|
15
15
|
const docker_compose_1 = require("../docker-compose");
|
|
16
|
-
const dockerComposeDown = (options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
+
const dockerComposeDown = (options, downOptions) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
17
|
logger_1.log.info(`Downing DockerCompose environment`);
|
|
18
18
|
try {
|
|
19
|
-
yield (0, docker_compose_1.down)(Object.assign(Object.assign({}, (0, default_docker_compose_options_1.defaultDockerComposeOptions)(options)), { commandOptions:
|
|
19
|
+
yield (0, docker_compose_1.down)(Object.assign(Object.assign({}, (0, default_docker_compose_options_1.defaultDockerComposeOptions)(options)), { commandOptions: commandOptions(downOptions) }));
|
|
20
20
|
logger_1.log.info(`Downed DockerCompose environment`);
|
|
21
21
|
}
|
|
22
22
|
catch (err) {
|
|
@@ -26,3 +26,13 @@ const dockerComposeDown = (options) => __awaiter(void 0, void 0, void 0, functio
|
|
|
26
26
|
}
|
|
27
27
|
});
|
|
28
28
|
exports.dockerComposeDown = dockerComposeDown;
|
|
29
|
+
const commandOptions = (options) => {
|
|
30
|
+
const result = [];
|
|
31
|
+
if (options.removeVolumes) {
|
|
32
|
+
result.push("-v");
|
|
33
|
+
}
|
|
34
|
+
if (options.timeout) {
|
|
35
|
+
result.push("-t", `${options.timeout / 1000}`);
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
};
|
|
@@ -29,7 +29,7 @@ const dockerComposeUp = (options, services) => __awaiter(void 0, void 0, void 0,
|
|
|
29
29
|
const errorMessage = err.err || err.message || err;
|
|
30
30
|
logger_1.log.error(`Failed to up DockerCompose environment: ${errorMessage}`);
|
|
31
31
|
try {
|
|
32
|
-
yield (0, docker_compose_down_1.dockerComposeDown)(options);
|
|
32
|
+
yield (0, docker_compose_down_1.dockerComposeDown)(options, { removeVolumes: true, timeout: 0 });
|
|
33
33
|
}
|
|
34
34
|
catch (_a) {
|
|
35
35
|
logger_1.log.warn(`Failed to down DockerCompose environment after failed up`);
|
|
@@ -112,7 +112,7 @@ class DockerComposeEnvironment {
|
|
|
112
112
|
catch (err) {
|
|
113
113
|
logger_1.log.error(`Container ${containerName} failed to be ready: ${err}`);
|
|
114
114
|
try {
|
|
115
|
-
yield (0, docker_compose_down_1.dockerComposeDown)(options);
|
|
115
|
+
yield (0, docker_compose_down_1.dockerComposeDown)(options, { removeVolumes: true, timeout: 0 });
|
|
116
116
|
}
|
|
117
117
|
catch (_a) {
|
|
118
118
|
logger_1.log.warn(`Failed to stop DockerCompose environment after failed up`);
|
|
@@ -2,6 +2,7 @@ import { StartedGenericContainer } from "../generic-container/started-generic-co
|
|
|
2
2
|
import { StoppedDockerComposeEnvironment } from "./stopped-docker-compose-environment";
|
|
3
3
|
import { DownedDockerComposeEnvironment } from "./downed-docker-compose-environment";
|
|
4
4
|
import { DockerComposeOptions } from "../docker-compose/docker-compose-options";
|
|
5
|
+
import { DockerComposeDownOptions } from "../test-container";
|
|
5
6
|
export declare class StartedDockerComposeEnvironment {
|
|
6
7
|
private readonly startedGenericContainers;
|
|
7
8
|
private readonly options;
|
|
@@ -9,6 +10,6 @@ export declare class StartedDockerComposeEnvironment {
|
|
|
9
10
|
[containerName: string]: StartedGenericContainer;
|
|
10
11
|
}, options: DockerComposeOptions);
|
|
11
12
|
stop(): Promise<StoppedDockerComposeEnvironment>;
|
|
12
|
-
down(): Promise<DownedDockerComposeEnvironment>;
|
|
13
|
+
down(options?: Partial<DockerComposeDownOptions>): Promise<DownedDockerComposeEnvironment>;
|
|
13
14
|
getContainer(containerName: string): StartedGenericContainer;
|
|
14
15
|
}
|
|
@@ -26,9 +26,10 @@ class StartedDockerComposeEnvironment {
|
|
|
26
26
|
return new stopped_docker_compose_environment_1.StoppedDockerComposeEnvironment(this.options);
|
|
27
27
|
});
|
|
28
28
|
}
|
|
29
|
-
down() {
|
|
29
|
+
down(options = {}) {
|
|
30
30
|
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
-
|
|
31
|
+
const downOptions = Object.assign({ timeout: 0, removeVolumes: true }, options);
|
|
32
|
+
yield (0, docker_compose_down_1.dockerComposeDown)(this.options, downOptions);
|
|
32
33
|
return new downed_docker_compose_environment_1.DownedDockerComposeEnvironment();
|
|
33
34
|
});
|
|
34
35
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { DownedDockerComposeEnvironment } from "./downed-docker-compose-environment";
|
|
2
2
|
import { DockerComposeOptions } from "../docker-compose/docker-compose-options";
|
|
3
|
+
import { DockerComposeDownOptions } from "../test-container";
|
|
3
4
|
export declare class StoppedDockerComposeEnvironment {
|
|
4
5
|
private readonly options;
|
|
5
6
|
constructor(options: DockerComposeOptions);
|
|
6
|
-
down(): Promise<DownedDockerComposeEnvironment>;
|
|
7
|
+
down(options?: Partial<DockerComposeDownOptions>): Promise<DownedDockerComposeEnvironment>;
|
|
7
8
|
}
|
|
@@ -16,9 +16,10 @@ class StoppedDockerComposeEnvironment {
|
|
|
16
16
|
constructor(options) {
|
|
17
17
|
this.options = options;
|
|
18
18
|
}
|
|
19
|
-
down() {
|
|
19
|
+
down(options = {}) {
|
|
20
20
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
|
-
|
|
21
|
+
const resolvedOptions = Object.assign({ timeout: 0, removeVolumes: true }, options);
|
|
22
|
+
yield (0, docker_compose_down_1.dockerComposeDown)(this.options, resolvedOptions);
|
|
22
23
|
return new downed_docker_compose_environment_1.DownedDockerComposeEnvironment();
|
|
23
24
|
});
|
|
24
25
|
}
|
|
@@ -8,9 +8,11 @@ export declare class GenericContainerBuilder {
|
|
|
8
8
|
private readonly uuid;
|
|
9
9
|
private buildArgs;
|
|
10
10
|
private pullPolicy;
|
|
11
|
+
private cache;
|
|
11
12
|
constructor(context: BuildContext, dockerfileName: string, uuid?: Uuid);
|
|
12
13
|
withBuildArg(key: string, value: string): GenericContainerBuilder;
|
|
13
14
|
withPullPolicy(pullPolicy: PullPolicy): this;
|
|
15
|
+
withCache(cache: boolean): this;
|
|
14
16
|
build(image?: string): Promise<GenericContainer>;
|
|
15
17
|
private getRegistryConfig;
|
|
16
18
|
}
|
|
@@ -32,6 +32,7 @@ class GenericContainerBuilder {
|
|
|
32
32
|
this.uuid = uuid;
|
|
33
33
|
this.buildArgs = {};
|
|
34
34
|
this.pullPolicy = new pull_policy_1.DefaultPullPolicy();
|
|
35
|
+
this.cache = true;
|
|
35
36
|
}
|
|
36
37
|
withBuildArg(key, value) {
|
|
37
38
|
this.buildArgs[key] = value;
|
|
@@ -41,6 +42,10 @@ class GenericContainerBuilder {
|
|
|
41
42
|
this.pullPolicy = pullPolicy;
|
|
42
43
|
return this;
|
|
43
44
|
}
|
|
45
|
+
withCache(cache) {
|
|
46
|
+
this.cache = cache;
|
|
47
|
+
return this;
|
|
48
|
+
}
|
|
44
49
|
build(image = `${this.uuid.nextUuid()}:${this.uuid.nextUuid()}`) {
|
|
45
50
|
return __awaiter(this, void 0, void 0, function* () {
|
|
46
51
|
const imageName = docker_image_name_1.DockerImageName.fromString(image);
|
|
@@ -55,6 +60,7 @@ class GenericContainerBuilder {
|
|
|
55
60
|
dockerfileName: this.dockerfileName,
|
|
56
61
|
buildArgs: this.buildArgs,
|
|
57
62
|
pullPolicy: this.pullPolicy,
|
|
63
|
+
cache: this.cache,
|
|
58
64
|
registryConfig,
|
|
59
65
|
});
|
|
60
66
|
const container = new generic_container_1.GenericContainer(imageName.toString());
|
|
@@ -6,7 +6,7 @@ import { PullPolicy } from "../pull-policy";
|
|
|
6
6
|
import { StartedTestContainer, TestContainer } from "../test-container";
|
|
7
7
|
import { WaitStrategy } from "../wait-strategy";
|
|
8
8
|
import { Readable } from "stream";
|
|
9
|
-
import { BindMode, BindMount, BuildContext, Command, ContainerName, Dir, Env, EnvKey, EnvValue, ExtraHost, HealthCheck, NetworkMode, TmpFs, Labels } from "../docker/types";
|
|
9
|
+
import { BindMode, BindMount, BuildContext, Command, ContainerName, Dir, Env, EnvKey, EnvValue, ExtraHost, HealthCheck, NetworkMode, TmpFs, Labels, Ulimits } from "../docker/types";
|
|
10
10
|
import { InspectResult } from "../docker/functions/container/inspect-container";
|
|
11
11
|
import { GenericContainerBuilder } from "./generic-container-builder";
|
|
12
12
|
export declare class GenericContainer implements TestContainer {
|
|
@@ -18,6 +18,7 @@ export declare class GenericContainer implements TestContainer {
|
|
|
18
18
|
protected networkAliases: string[];
|
|
19
19
|
protected ports: PortWithOptionalBinding[];
|
|
20
20
|
protected cmd: Command[];
|
|
21
|
+
protected entrypoint?: string[];
|
|
21
22
|
protected bindMounts: BindMount[];
|
|
22
23
|
protected name?: ContainerName;
|
|
23
24
|
protected labels: Labels;
|
|
@@ -28,6 +29,9 @@ export declare class GenericContainer implements TestContainer {
|
|
|
28
29
|
protected useDefaultLogDriver: boolean;
|
|
29
30
|
protected privilegedMode: boolean;
|
|
30
31
|
protected ipcMode?: string;
|
|
32
|
+
protected ulimits?: Ulimits;
|
|
33
|
+
protected addedCapabilities?: string[];
|
|
34
|
+
protected droppedCapabilities?: string[];
|
|
31
35
|
protected user?: string;
|
|
32
36
|
protected pullPolicy: PullPolicy;
|
|
33
37
|
protected reuse: boolean;
|
|
@@ -41,10 +45,14 @@ export declare class GenericContainer implements TestContainer {
|
|
|
41
45
|
protected postStart?(container: StartedTestContainer, inspectResult: InspectResult, boundPorts: BoundPorts): Promise<void>;
|
|
42
46
|
protected get hasExposedPorts(): boolean;
|
|
43
47
|
withCmd(cmd: Command[]): this;
|
|
48
|
+
withEntrypoint(entrypoint: string[]): this;
|
|
44
49
|
withName(name: ContainerName): this;
|
|
45
50
|
withLabels(labels: Labels): this;
|
|
46
51
|
withEnv(key: EnvKey, value: EnvValue): this;
|
|
47
52
|
withTmpFs(tmpFs: TmpFs): this;
|
|
53
|
+
withUlimits(ulimits: Ulimits): this;
|
|
54
|
+
withAddedCapabilities(...capabilities: string[]): this;
|
|
55
|
+
withDroppedCapabilities(...capabilities: string[]): this;
|
|
48
56
|
withNetworkMode(networkMode: NetworkMode): this;
|
|
49
57
|
withNetworkAliases(...networkAliases: string[]): this;
|
|
50
58
|
withExtraHosts(...extraHosts: ExtraHost[]): this;
|
|
@@ -80,6 +80,7 @@ class GenericContainer {
|
|
|
80
80
|
imageName: this.imageName,
|
|
81
81
|
env: this.env,
|
|
82
82
|
cmd: this.cmd,
|
|
83
|
+
entrypoint: this.entrypoint,
|
|
83
84
|
bindMounts: this.bindMounts,
|
|
84
85
|
tmpFs: this.tmpFs,
|
|
85
86
|
exposedPorts: this.ports,
|
|
@@ -93,6 +94,9 @@ class GenericContainer {
|
|
|
93
94
|
autoRemove: this.imageName.isReaper(),
|
|
94
95
|
extraHosts: this.extraHosts,
|
|
95
96
|
ipcMode: this.ipcMode,
|
|
97
|
+
ulimits: this.ulimits,
|
|
98
|
+
addedCapabilities: this.addedCapabilities,
|
|
99
|
+
droppedCapabilities: this.droppedCapabilities,
|
|
96
100
|
user: this.user,
|
|
97
101
|
};
|
|
98
102
|
if (this.reuse) {
|
|
@@ -170,6 +174,10 @@ class GenericContainer {
|
|
|
170
174
|
this.cmd = cmd;
|
|
171
175
|
return this;
|
|
172
176
|
}
|
|
177
|
+
withEntrypoint(entrypoint) {
|
|
178
|
+
this.entrypoint = entrypoint;
|
|
179
|
+
return this;
|
|
180
|
+
}
|
|
173
181
|
withName(name) {
|
|
174
182
|
this.name = name;
|
|
175
183
|
return this;
|
|
@@ -186,6 +194,18 @@ class GenericContainer {
|
|
|
186
194
|
this.tmpFs = tmpFs;
|
|
187
195
|
return this;
|
|
188
196
|
}
|
|
197
|
+
withUlimits(ulimits) {
|
|
198
|
+
this.ulimits = ulimits;
|
|
199
|
+
return this;
|
|
200
|
+
}
|
|
201
|
+
withAddedCapabilities(...capabilities) {
|
|
202
|
+
this.addedCapabilities = capabilities;
|
|
203
|
+
return this;
|
|
204
|
+
}
|
|
205
|
+
withDroppedCapabilities(...capabilities) {
|
|
206
|
+
this.droppedCapabilities = capabilities;
|
|
207
|
+
return this;
|
|
208
|
+
}
|
|
189
209
|
withNetworkMode(networkMode) {
|
|
190
210
|
this.networkMode = networkMode;
|
|
191
211
|
return this;
|
|
@@ -37,9 +37,8 @@ class StartedGenericContainer {
|
|
|
37
37
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
38
|
const resolvedOptions = Object.assign({ timeout: 0 }, options);
|
|
39
39
|
yield (0, restart_container_1.restartContainer)(this.container, resolvedOptions);
|
|
40
|
-
// Inspect the restarted container and update the bound ports
|
|
41
40
|
this.inspectResult = yield (0, inspect_container_1.inspectContainer)(this.container);
|
|
42
|
-
this.boundPorts =
|
|
41
|
+
this.boundPorts = bound_ports_1.BoundPorts.fromInspectResult(this.inspectResult).filter(Array.from(this.boundPorts.iterator()).map((port) => port[0]));
|
|
43
42
|
yield this.waitForContainer(this.container, this.boundPorts);
|
|
44
43
|
});
|
|
45
44
|
}
|
package/dist/logger.d.ts
CHANGED
package/dist/logger.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.containerLog = exports.log = exports.FakeLogger = void 0;
|
|
6
|
+
exports.execLog = exports.containerLog = exports.log = exports.FakeLogger = void 0;
|
|
7
7
|
const debug_1 = __importDefault(require("debug"));
|
|
8
8
|
class DebugLogger {
|
|
9
9
|
constructor(namespace) {
|
|
@@ -52,3 +52,4 @@ class FakeLogger {
|
|
|
52
52
|
exports.FakeLogger = FakeLogger;
|
|
53
53
|
exports.log = new DebugLogger("testcontainers");
|
|
54
54
|
exports.containerLog = new DebugLogger("testcontainers:containers");
|
|
55
|
+
exports.execLog = new DebugLogger("testcontainers:exec");
|
package/dist/port-check.js
CHANGED
|
@@ -52,7 +52,7 @@ class InternalPortCheck {
|
|
|
52
52
|
["/bin/sh", "-c", `nc -vz -w 1 localhost ${port}`],
|
|
53
53
|
["/bin/bash", "-c", `</dev/tcp/localhost/${port}`],
|
|
54
54
|
];
|
|
55
|
-
const commandResults = yield Promise.all(commands.map((command) => (0, exec_container_1.execContainer)(this.container, command, { stdin: true, detach: false, tty: true })));
|
|
55
|
+
const commandResults = yield Promise.all(commands.map((command) => (0, exec_container_1.execContainer)(this.container, command, { stdin: true, detach: false, tty: true }, false)));
|
|
56
56
|
const isBound = commandResults.some((result) => result.exitCode === 0);
|
|
57
57
|
if (!isBound) {
|
|
58
58
|
const shellExists = commandResults.some((result) => result.exitCode !== 126);
|
package/dist/test-container.d.ts
CHANGED
|
@@ -3,12 +3,16 @@ import { Port, PortWithOptionalBinding } from "./port";
|
|
|
3
3
|
import { PullPolicy } from "./pull-policy";
|
|
4
4
|
import { WaitStrategy } from "./wait-strategy";
|
|
5
5
|
import { Readable } from "stream";
|
|
6
|
-
import { BindMode, Command, ContainerName, Dir, EnvKey, EnvValue, ExecResult, ExtraHost, Host, Id, NetworkMode, TmpFs, Labels } from "./docker/types";
|
|
6
|
+
import { BindMode, Command, ContainerName, Dir, EnvKey, EnvValue, ExecResult, ExtraHost, Host, Id, NetworkMode, TmpFs, Labels, Ulimits } from "./docker/types";
|
|
7
7
|
export interface TestContainer {
|
|
8
8
|
start(): Promise<StartedTestContainer>;
|
|
9
9
|
withEnv(key: EnvKey, value: EnvValue): this;
|
|
10
10
|
withCmd(cmd: Command[]): this;
|
|
11
|
+
withEntrypoint(entrypoint: string[]): this;
|
|
11
12
|
withTmpFs(tmpFs: TmpFs): this;
|
|
13
|
+
withUlimits(ulimits: Ulimits): this;
|
|
14
|
+
withAddedCapabilities(...capabilities: string[]): this;
|
|
15
|
+
withDroppedCapabilities(...capabilities: string[]): this;
|
|
12
16
|
withExposedPorts(...ports: PortWithOptionalBinding[]): this;
|
|
13
17
|
withBindMount(source: Dir, target: Dir, bindMode: BindMode): this;
|
|
14
18
|
withWaitStrategy(waitStrategy: WaitStrategy): this;
|
|
@@ -30,6 +34,10 @@ export interface StopOptions {
|
|
|
30
34
|
timeout: number;
|
|
31
35
|
removeVolumes: boolean;
|
|
32
36
|
}
|
|
37
|
+
export interface DockerComposeDownOptions {
|
|
38
|
+
timeout: number;
|
|
39
|
+
removeVolumes: boolean;
|
|
40
|
+
}
|
|
33
41
|
export interface ExecOptions {
|
|
34
42
|
tty: boolean;
|
|
35
43
|
detach: boolean;
|