testcontainers 8.15.0 → 9.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.
- package/README.md +160 -43
- package/dist/bound-ports.d.ts +4 -4
- package/dist/docker/docker-client.d.ts +1 -2
- package/dist/docker/functions/container/container-logs.js +1 -6
- package/dist/docker/functions/container/create-container.d.ts +9 -5
- package/dist/docker/functions/container/create-container.js +19 -6
- package/dist/docker/functions/container/exec-container.d.ts +2 -2
- package/dist/docker/functions/container/exec-container.js +10 -3
- package/dist/docker/functions/container/get-container.d.ts +1 -2
- package/dist/docker/functions/container/inspect-container.d.ts +2 -2
- package/dist/docker/functions/create-labels.d.ts +1 -1
- package/dist/docker/functions/image/build-image.d.ts +3 -2
- package/dist/docker/functions/image/build-image.js +14 -9
- package/dist/docker/functions/run-in-container.d.ts +1 -2
- package/dist/docker/types.d.ts +29 -22
- package/dist/docker-compose/default-docker-compose-options.d.ts +1 -1
- package/dist/docker-compose/default-docker-compose-options.js +2 -2
- package/dist/docker-compose/docker-compose-options.d.ts +2 -2
- 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.d.ts +1 -1
- package/dist/docker-compose/functions/docker-compose-up.js +1 -1
- package/dist/docker-compose-environment/docker-compose-environment.d.ts +5 -5
- package/dist/docker-compose-environment/docker-compose-environment.js +12 -12
- 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 +5 -3
- package/dist/generic-container/generic-container-builder.js +8 -2
- package/dist/generic-container/generic-container.d.ts +24 -17
- package/dist/generic-container/generic-container.js +48 -24
- package/dist/generic-container/started-generic-container.d.ts +7 -8
- 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/modules/abstract-started-container.d.ts +6 -7
- package/dist/modules/arangodb/arangodb-container.js +2 -2
- package/dist/modules/elasticsearch/elasticsearch-container.js +2 -2
- package/dist/modules/kafka/kafka-container.d.ts +4 -5
- package/dist/modules/kafka/kafka-container.js +41 -34
- package/dist/modules/mongodb/mongodb-container.js +1 -1
- package/dist/modules/mysql/mysql-container.d.ts +1 -2
- package/dist/modules/mysql/mysql-container.js +7 -5
- package/dist/modules/nats/nats-container.d.ts +1 -1
- package/dist/modules/nats/nats-container.js +2 -2
- package/dist/modules/neo4j/neo4j-container.js +10 -4
- package/dist/modules/postgresql/postgresql-container.d.ts +1 -2
- package/dist/modules/postgresql/postgresql-container.js +5 -3
- package/dist/port-binder.d.ts +1 -2
- package/dist/port-check.d.ts +4 -6
- package/dist/port-check.js +1 -1
- package/dist/port-forwarder.d.ts +1 -2
- package/dist/port-forwarder.js +2 -2
- package/dist/port-generator.d.ts +4 -5
- package/dist/port.d.ts +3 -5
- package/dist/reaper.js +1 -1
- package/dist/test-container.d.ts +24 -14
- package/dist/test-containers.d.ts +1 -2
- package/package.json +29 -25
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
|
|
@@ -117,7 +118,10 @@ const { GenericContainer } = require("testcontainers");
|
|
|
117
118
|
const buildContext = path.resolve(__dirname, "dir-containing-dockerfile");
|
|
118
119
|
|
|
119
120
|
const container = await GenericContainer.fromDockerfile(buildContext)
|
|
120
|
-
.
|
|
121
|
+
.withBuildArgs({
|
|
122
|
+
ARG_1: "ARG_VALUE_1",
|
|
123
|
+
ARG_2: "ARG_VALUE_2",
|
|
124
|
+
})
|
|
121
125
|
.build();
|
|
122
126
|
|
|
123
127
|
const startedContainer = await container
|
|
@@ -134,6 +138,16 @@ const container = await GenericContainer.fromDockerfile(buildContext, "my-docker
|
|
|
134
138
|
.build();
|
|
135
139
|
```
|
|
136
140
|
|
|
141
|
+
Build the image without using the cache:
|
|
142
|
+
|
|
143
|
+
```javascript
|
|
144
|
+
const { GenericContainer } = require("testcontainers");
|
|
145
|
+
|
|
146
|
+
const container = await GenericContainer.fromDockerfile(buildContext, "my-dockerfile")
|
|
147
|
+
.withCache(false)
|
|
148
|
+
.build();
|
|
149
|
+
```
|
|
150
|
+
|
|
137
151
|
Creating a container with multiple exposed ports:
|
|
138
152
|
|
|
139
153
|
```javascript
|
|
@@ -150,12 +164,12 @@ Enabling container reuse, note that two containers are considered equal if their
|
|
|
150
164
|
const { GenericContainer } = require("testcontainers");
|
|
151
165
|
|
|
152
166
|
const container1 = await new GenericContainer("alpine")
|
|
153
|
-
.
|
|
167
|
+
.withCommand(["sleep", "infinity"])
|
|
154
168
|
.withReuse()
|
|
155
169
|
.start();
|
|
156
170
|
|
|
157
171
|
const container2 = await new GenericContainer("alpine")
|
|
158
|
-
.
|
|
172
|
+
.withCommand(["sleep", "infinity"])
|
|
159
173
|
.withReuse()
|
|
160
174
|
.start();
|
|
161
175
|
|
|
@@ -189,7 +203,17 @@ Creating a container with a command:
|
|
|
189
203
|
const { GenericContainer } = require("testcontainers");
|
|
190
204
|
|
|
191
205
|
const container = await new GenericContainer("alpine")
|
|
192
|
-
.
|
|
206
|
+
.withCommand(["sleep", "infinity"])
|
|
207
|
+
.start();
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Creating a container with entrypoint:
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
const { GenericContainer } = require("testcontainers");
|
|
214
|
+
|
|
215
|
+
const container = await new GenericContainer("alpine")
|
|
216
|
+
.withEntrypoint(["cat"])
|
|
193
217
|
.start();
|
|
194
218
|
```
|
|
195
219
|
|
|
@@ -199,7 +223,7 @@ Execute commands inside a running container:
|
|
|
199
223
|
const { GenericContainer } = require("testcontainers");
|
|
200
224
|
|
|
201
225
|
const container = await new GenericContainer("alpine")
|
|
202
|
-
.
|
|
226
|
+
.withCommand(["sleep", "infinity"])
|
|
203
227
|
.start();
|
|
204
228
|
|
|
205
229
|
const { output, exitCode } = await container.exec(["echo", "hello", "world"]);
|
|
@@ -217,7 +241,6 @@ stream
|
|
|
217
241
|
.on("data", line => console.log(line))
|
|
218
242
|
.on("err", line => console.error(line))
|
|
219
243
|
.on("end", () => console.log("Stream closed"));
|
|
220
|
-
|
|
221
244
|
```
|
|
222
245
|
|
|
223
246
|
Creating a container with bind mounts:
|
|
@@ -226,8 +249,14 @@ Creating a container with bind mounts:
|
|
|
226
249
|
const { GenericContainer } = require("testcontainers");
|
|
227
250
|
|
|
228
251
|
const container = await new GenericContainer("alpine")
|
|
229
|
-
.
|
|
230
|
-
|
|
252
|
+
.withBindMounts([{
|
|
253
|
+
source: "/local/file.txt",
|
|
254
|
+
target:"/remote/file.txt"
|
|
255
|
+
}, {
|
|
256
|
+
source: "/local/dir",
|
|
257
|
+
target:"/remote/dir",
|
|
258
|
+
mode: "ro"
|
|
259
|
+
}])
|
|
231
260
|
.start();
|
|
232
261
|
```
|
|
233
262
|
|
|
@@ -249,8 +278,14 @@ const { GenericContainer } = require("testcontainers");
|
|
|
249
278
|
|
|
250
279
|
const container = await new GenericContainer("postgres")
|
|
251
280
|
.withExposedPorts(5432)
|
|
252
|
-
.
|
|
253
|
-
|
|
281
|
+
.withCopyFilesToContainer([{
|
|
282
|
+
source: "/local/file.txt",
|
|
283
|
+
target: "/remote/file1.txt"
|
|
284
|
+
}])
|
|
285
|
+
.withCopyContentToContainer([{
|
|
286
|
+
content: "hello world",
|
|
287
|
+
target: "/remote/file2.txt"
|
|
288
|
+
}])
|
|
254
289
|
.start();
|
|
255
290
|
```
|
|
256
291
|
|
|
@@ -260,7 +295,10 @@ Creating a container with environment variables:
|
|
|
260
295
|
const { GenericContainer } = require("testcontainers");
|
|
261
296
|
|
|
262
297
|
const container = await new GenericContainer("alpine")
|
|
263
|
-
.
|
|
298
|
+
.withEnvironment({
|
|
299
|
+
ENV_1: "ENV_VALUE_1",
|
|
300
|
+
ENV_2: "ENV_VALUE_2",
|
|
301
|
+
})
|
|
264
302
|
.start();
|
|
265
303
|
```
|
|
266
304
|
|
|
@@ -284,7 +322,7 @@ const { GenericContainer, Wait } = require("testcontainers");
|
|
|
284
322
|
|
|
285
323
|
const container = await new GenericContainer("alpine")
|
|
286
324
|
.withHealthCheck({
|
|
287
|
-
test: "curl -f http://localhost || exit 1",
|
|
325
|
+
test: ["CMD-SHELL", "curl -f http://localhost || exit 1"],
|
|
288
326
|
interval: 1000,
|
|
289
327
|
timeout: 3000,
|
|
290
328
|
retries: 5,
|
|
@@ -294,32 +332,44 @@ const container = await new GenericContainer("alpine")
|
|
|
294
332
|
.start();
|
|
295
333
|
```
|
|
296
334
|
|
|
297
|
-
|
|
335
|
+
To execute the `test` in a shell use the form `["CMD-SHELL", "command"]`, for example:
|
|
298
336
|
|
|
299
337
|
```javascript
|
|
300
|
-
|
|
338
|
+
["CMD-SHELL", "curl -f http://localhost:8000 || exit 1"]
|
|
339
|
+
```
|
|
301
340
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
341
|
+
To execute the `test` without a shell, use the form: `["CMD", "command", "arg1", "arg2"]`, for example:
|
|
342
|
+
|
|
343
|
+
```javascript
|
|
344
|
+
["CMD", "/usr/bin/wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8080/hello-world"]
|
|
305
345
|
```
|
|
306
346
|
|
|
307
|
-
|
|
347
|
+
Creating a container within a network:
|
|
308
348
|
|
|
309
349
|
```javascript
|
|
310
350
|
const { GenericContainer, Network } = require("testcontainers");
|
|
311
351
|
|
|
312
352
|
const network = await new Network()
|
|
313
|
-
|
|
353
|
+
.start();
|
|
314
354
|
|
|
315
355
|
const container = await new GenericContainer("alpine")
|
|
316
|
-
.
|
|
356
|
+
.withNetwork(network)
|
|
317
357
|
.start();
|
|
318
358
|
|
|
319
359
|
await container.stop();
|
|
320
360
|
await network.stop();
|
|
321
361
|
```
|
|
322
362
|
|
|
363
|
+
Creating a container with a network mode:
|
|
364
|
+
|
|
365
|
+
```javascript
|
|
366
|
+
const { GenericContainer } = require("testcontainers");
|
|
367
|
+
|
|
368
|
+
const container = await new GenericContainer("alpine")
|
|
369
|
+
.withNetworkMode("bridge")
|
|
370
|
+
.start();
|
|
371
|
+
```
|
|
372
|
+
|
|
323
373
|
Communicate to containers on the same network via aliases:
|
|
324
374
|
|
|
325
375
|
```javascript
|
|
@@ -329,17 +379,17 @@ const network = await new Network()
|
|
|
329
379
|
.start();
|
|
330
380
|
|
|
331
381
|
const container = await new GenericContainer("alpine")
|
|
332
|
-
.
|
|
333
|
-
.
|
|
382
|
+
.withCommand(["sleep", "infinity"])
|
|
383
|
+
.withNetwork(network)
|
|
334
384
|
.start();
|
|
335
385
|
|
|
336
386
|
const fooContainer = await new GenericContainer("alpine")
|
|
337
|
-
.
|
|
338
|
-
.
|
|
387
|
+
.withCommand(["sleep", "infinity"])
|
|
388
|
+
.withNetwork(network)
|
|
339
389
|
.withNetworkAliases("foo", "bar")
|
|
340
390
|
.start();
|
|
341
391
|
|
|
342
|
-
expect((await container.exec(["
|
|
392
|
+
expect((await container.exec(["getent", "hosts", "foo"])).exitCode).toBe(0);
|
|
343
393
|
```
|
|
344
394
|
|
|
345
395
|
Add hostname mappings:
|
|
@@ -348,14 +398,17 @@ Add hostname mappings:
|
|
|
348
398
|
const { GenericContainer } = require("testcontainers");
|
|
349
399
|
|
|
350
400
|
const container = await new GenericContainer("alpine")
|
|
351
|
-
.withExtraHosts(
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
401
|
+
.withExtraHosts([{
|
|
402
|
+
host: "foo",
|
|
403
|
+
ipAddress: "10.11.12.13"
|
|
404
|
+
}, {
|
|
405
|
+
host: "bar",
|
|
406
|
+
ipAddress: "11.12.13.14"
|
|
407
|
+
}])
|
|
355
408
|
.start();
|
|
356
409
|
|
|
357
|
-
expect((await container.exec(["
|
|
358
|
-
expect((await container.exec(["
|
|
410
|
+
expect((await container.exec(["getent", "hosts", "foo"])).exitCode).toBe(0);
|
|
411
|
+
expect((await container.exec(["getent", "hosts", "bar"])).exitCode).toBe(0);
|
|
359
412
|
```
|
|
360
413
|
|
|
361
414
|
Specifying a pull policy. Note that if omitted will use the `DefaultPullPolicy` which will use a locally cached image
|
|
@@ -414,6 +467,41 @@ const container = await new GenericContainer("alpine")
|
|
|
414
467
|
.start();
|
|
415
468
|
```
|
|
416
469
|
|
|
470
|
+
Creating a container with added [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html):
|
|
471
|
+
|
|
472
|
+
```javascript
|
|
473
|
+
const { GenericContainer } = require("testcontainers");
|
|
474
|
+
|
|
475
|
+
const container = await new GenericContainer("aline")
|
|
476
|
+
.withAddedCapabilities("NET_ADMIN", "IPC_LOCK")
|
|
477
|
+
.start();
|
|
478
|
+
```
|
|
479
|
+
|
|
480
|
+
Creating a container with dropped [capabilities](https://man7.org/linux/man-pages/man7/capabilities.7.html):
|
|
481
|
+
|
|
482
|
+
```javascript
|
|
483
|
+
const { GenericContainer } = require("testcontainers");
|
|
484
|
+
|
|
485
|
+
const container = await new GenericContainer("aline")
|
|
486
|
+
.withDroppedCapabilities("NET_ADMIN", "IPC_LOCK")
|
|
487
|
+
.start();
|
|
488
|
+
```
|
|
489
|
+
|
|
490
|
+
Creating a container with ulimits:
|
|
491
|
+
|
|
492
|
+
```javascript
|
|
493
|
+
const { GenericContainer } = require("testcontainers");
|
|
494
|
+
|
|
495
|
+
const container = await new GenericContainer("aline")
|
|
496
|
+
.withUlimits({
|
|
497
|
+
memlock: {
|
|
498
|
+
hard: -1,
|
|
499
|
+
soft: -1
|
|
500
|
+
}
|
|
501
|
+
})
|
|
502
|
+
.start();
|
|
503
|
+
```
|
|
504
|
+
|
|
417
505
|
Creating a container with [IPC mode](https://docs.docker.com/engine/reference/run/#ipc-settings---ipc):
|
|
418
506
|
|
|
419
507
|
```javascript
|
|
@@ -462,7 +550,7 @@ const network = await new Network()
|
|
|
462
550
|
.start();
|
|
463
551
|
|
|
464
552
|
const container = await new GenericContainer("alpine")
|
|
465
|
-
.
|
|
553
|
+
.withNetwork(network)
|
|
466
554
|
.start();
|
|
467
555
|
|
|
468
556
|
const networkIpAddress = container.getIpAddress(network.getName());
|
|
@@ -483,7 +571,7 @@ server.listen(8000);
|
|
|
483
571
|
await TestContainers.exposeHostPorts(8000);
|
|
484
572
|
|
|
485
573
|
const container = await new GenericContainer("alpine")
|
|
486
|
-
.
|
|
574
|
+
.withCommand(["sleep", "infinity"])
|
|
487
575
|
.start();
|
|
488
576
|
|
|
489
577
|
const { output } = await container.exec(["curl", `http://host.testcontainers.internal:8000`]);
|
|
@@ -582,7 +670,8 @@ Once the environment has started, you can interact with the containers as you wo
|
|
|
582
670
|
```javascript
|
|
583
671
|
const { DockerComposeEnvironment } = require("testcontainers");
|
|
584
672
|
|
|
585
|
-
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile)
|
|
673
|
+
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile)
|
|
674
|
+
.up();
|
|
586
675
|
|
|
587
676
|
const container = environment.getContainer("alpine_1");
|
|
588
677
|
const { output, exitCode } = await container.exec(["echo", "hello", "world"]);
|
|
@@ -593,7 +682,8 @@ You can supply [multiple compose files](https://docs.docker.com/compose/extends/
|
|
|
593
682
|
```javascript
|
|
594
683
|
const { DockerComposeEnvironment } = require("testcontainers");
|
|
595
684
|
|
|
596
|
-
const environment = await new DockerComposeEnvironment(composeFilePath, [composeFile1, composeFile2])
|
|
685
|
+
const environment = await new DockerComposeEnvironment(composeFilePath, [composeFile1, composeFile2])
|
|
686
|
+
.up();
|
|
597
687
|
|
|
598
688
|
await environment.stop();
|
|
599
689
|
```
|
|
@@ -603,7 +693,8 @@ If you have multiple docker-compose environments which share dependencies such a
|
|
|
603
693
|
```javascript
|
|
604
694
|
const { DockerComposeEnvironment } = require("testcontainers");
|
|
605
695
|
|
|
606
|
-
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile)
|
|
696
|
+
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile)
|
|
697
|
+
.up();
|
|
607
698
|
|
|
608
699
|
await environment.stop();
|
|
609
700
|
```
|
|
@@ -662,10 +753,36 @@ Then we can set `TAG` as follows:
|
|
|
662
753
|
const { DockerComposeEnvironment } = require("testcontainers");
|
|
663
754
|
|
|
664
755
|
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile)
|
|
665
|
-
.
|
|
756
|
+
.withEnvironment({ "TAG": "VALUE" })
|
|
666
757
|
.up();
|
|
667
758
|
```
|
|
668
759
|
|
|
760
|
+
Testcontainers will not wait for an environment to down, to override:
|
|
761
|
+
|
|
762
|
+
```javascript
|
|
763
|
+
const { GenericContainer } = require("testcontainers");
|
|
764
|
+
|
|
765
|
+
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile)
|
|
766
|
+
.up();
|
|
767
|
+
|
|
768
|
+
await environment.down({
|
|
769
|
+
timeout: 10000
|
|
770
|
+
});
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
Testcontainers will remove associated volumes created by the environment when downed, to override:
|
|
774
|
+
|
|
775
|
+
```javascript
|
|
776
|
+
const { GenericContainer } = require("testcontainers");
|
|
777
|
+
|
|
778
|
+
const environment = await new DockerComposeEnvironment(composeFilePath, composeFile)
|
|
779
|
+
.up();
|
|
780
|
+
|
|
781
|
+
await environment.down({
|
|
782
|
+
removeVolumes: false
|
|
783
|
+
});
|
|
784
|
+
```
|
|
785
|
+
|
|
669
786
|
## Wait Strategies
|
|
670
787
|
|
|
671
788
|
Ordinarily Testcontainers will wait for up to 60 seconds for the container's mapped network ports to start listening.
|
|
@@ -726,10 +843,10 @@ Testcontainers may need to create auxiliary containers to provide its functional
|
|
|
726
843
|
|
|
727
844
|
To avoid Docker pull limits, you can host your own images and use them by setting the appropriate environment variables:
|
|
728
845
|
|
|
729
|
-
| Container | Environment Variable
|
|
730
|
-
|
|
731
|
-
| ryuk
|
|
732
|
-
| SSHd
|
|
846
|
+
| Container | Environment Variable | Default |
|
|
847
|
+
|-----------|------------------------|-----------------------------|
|
|
848
|
+
| ryuk | `RYUK_CONTAINER_IMAGE` | `testcontainers/ryuk:0.3.2` |
|
|
849
|
+
| SSHd | `SSHD_CONTAINER_IMAGE` | `testcontainers/sshd:1.0.0` |
|
|
733
850
|
|
|
734
851
|
### ryuk
|
|
735
852
|
|
package/dist/bound-ports.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { PortWithOptionalBinding } from "./port";
|
|
2
2
|
import { InspectResult } from "./docker/functions/container/inspect-container";
|
|
3
3
|
export declare class BoundPorts {
|
|
4
4
|
private readonly ports;
|
|
5
|
-
getBinding(port:
|
|
6
|
-
setBinding(key:
|
|
7
|
-
iterator(): Iterable<[
|
|
5
|
+
getBinding(port: number): number;
|
|
6
|
+
setBinding(key: number, value: number): void;
|
|
7
|
+
iterator(): Iterable<[number, number]>;
|
|
8
8
|
filter(ports: PortWithOptionalBinding[]): BoundPorts;
|
|
9
9
|
static fromInspectResult(inspectResult: InspectResult): BoundPorts;
|
|
10
10
|
}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import Dockerode from "dockerode";
|
|
2
|
-
import { Host } from "./types";
|
|
3
2
|
import "../testcontainers-properties-file";
|
|
4
3
|
declare type DockerClient = {
|
|
5
|
-
host:
|
|
4
|
+
host: string;
|
|
6
5
|
dockerode: Dockerode;
|
|
7
6
|
};
|
|
8
7
|
export declare const dockerClient: () => Promise<DockerClient>;
|
|
@@ -15,12 +15,7 @@ const demux_stream_1 = require("../demux-stream");
|
|
|
15
15
|
const docker_client_1 = require("../../docker-client");
|
|
16
16
|
const containerLogs = (container) => __awaiter(void 0, void 0, void 0, function* () {
|
|
17
17
|
try {
|
|
18
|
-
const
|
|
19
|
-
follow: true,
|
|
20
|
-
stdout: true,
|
|
21
|
-
stderr: true,
|
|
22
|
-
};
|
|
23
|
-
const stream = (yield container.logs(options));
|
|
18
|
+
const stream = (yield container.logs({ follow: true, stdout: true, stderr: true }));
|
|
24
19
|
stream.socket.unref();
|
|
25
20
|
return (0, demux_stream_1.demuxStream)((yield (0, docker_client_1.dockerClient)()).dockerode, stream);
|
|
26
21
|
}
|
|
@@ -1,24 +1,28 @@
|
|
|
1
1
|
import { DockerImageName } from "../../../docker-image-name";
|
|
2
2
|
import Dockerode from "dockerode";
|
|
3
3
|
import { PortWithOptionalBinding } from "../../../port";
|
|
4
|
-
import { BindMount,
|
|
4
|
+
import { BindMount, Environment, ExtraHost, HealthCheck, Labels, TmpFs, Ulimits } from "../../types";
|
|
5
5
|
export declare type CreateContainerOptions = {
|
|
6
6
|
imageName: DockerImageName;
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
environment: Environment;
|
|
8
|
+
command: string[];
|
|
9
|
+
entrypoint?: string[];
|
|
9
10
|
bindMounts: BindMount[];
|
|
10
11
|
tmpFs: TmpFs;
|
|
11
12
|
exposedPorts: PortWithOptionalBinding[];
|
|
12
|
-
name?:
|
|
13
|
+
name?: string;
|
|
13
14
|
reusable: boolean;
|
|
14
15
|
labels?: Labels;
|
|
15
|
-
networkMode?:
|
|
16
|
+
networkMode?: string;
|
|
16
17
|
healthCheck?: HealthCheck;
|
|
17
18
|
useDefaultLogDriver: boolean;
|
|
18
19
|
privilegedMode: boolean;
|
|
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>;
|
|
@@ -22,11 +22,11 @@ const createContainer = (options) => __awaiter(void 0, void 0, void 0, function*
|
|
|
22
22
|
name: options.name,
|
|
23
23
|
User: options.user,
|
|
24
24
|
Image: options.imageName.toString(),
|
|
25
|
-
Env:
|
|
25
|
+
Env: getEnvironment(options.environment),
|
|
26
26
|
ExposedPorts: getExposedPorts(options.exposedPorts),
|
|
27
|
-
Cmd: options.
|
|
27
|
+
Cmd: options.command,
|
|
28
|
+
Entrypoint: options.entrypoint,
|
|
28
29
|
Labels: (0, create_labels_1.createLabels)(options.reusable, options.imageName, options.labels),
|
|
29
|
-
// @ts-ignore
|
|
30
30
|
Healthcheck: getHealthCheck(options.healthCheck),
|
|
31
31
|
HostConfig: {
|
|
32
32
|
IpcMode: options.ipcMode,
|
|
@@ -38,6 +38,9 @@ const createContainer = (options) => __awaiter(void 0, void 0, void 0, function*
|
|
|
38
38
|
Tmpfs: options.tmpFs,
|
|
39
39
|
LogConfig: getLogConfig(options.useDefaultLogDriver),
|
|
40
40
|
Privileged: options.privilegedMode,
|
|
41
|
+
Ulimits: getUlimits(options.ulimits),
|
|
42
|
+
CapAdd: options.addedCapabilities,
|
|
43
|
+
CapDrop: options.droppedCapabilities,
|
|
41
44
|
},
|
|
42
45
|
});
|
|
43
46
|
}
|
|
@@ -47,7 +50,7 @@ const createContainer = (options) => __awaiter(void 0, void 0, void 0, function*
|
|
|
47
50
|
}
|
|
48
51
|
});
|
|
49
52
|
exports.createContainer = createContainer;
|
|
50
|
-
const
|
|
53
|
+
const getEnvironment = (environment) => Object.entries(environment).reduce((dockerodeEnvironment, [key, value]) => [...dockerodeEnvironment, `${key}=${value}`], []);
|
|
51
54
|
const getExposedPorts = (exposedPorts) => {
|
|
52
55
|
const dockerodeExposedPorts = {};
|
|
53
56
|
for (const exposedPort of exposedPorts) {
|
|
@@ -71,14 +74,14 @@ const getPortBindings = (exposedPorts) => {
|
|
|
71
74
|
return dockerodePortBindings;
|
|
72
75
|
};
|
|
73
76
|
const getBindMounts = (bindMounts) => {
|
|
74
|
-
return bindMounts.map(({ source, target,
|
|
77
|
+
return bindMounts.map(({ source, target, mode }) => `${source}:${target}:${mode}`);
|
|
75
78
|
};
|
|
76
79
|
const getHealthCheck = (healthCheck) => {
|
|
77
80
|
if (healthCheck === undefined) {
|
|
78
81
|
return undefined;
|
|
79
82
|
}
|
|
80
83
|
return {
|
|
81
|
-
Test:
|
|
84
|
+
Test: healthCheck.test,
|
|
82
85
|
Interval: healthCheck.interval ? toNanos(healthCheck.interval) : 0,
|
|
83
86
|
Timeout: healthCheck.timeout ? toNanos(healthCheck.timeout) : 0,
|
|
84
87
|
Retries: healthCheck.retries || 0,
|
|
@@ -95,3 +98,13 @@ const getLogConfig = (useDefaultLogDriver) => {
|
|
|
95
98
|
Config: {},
|
|
96
99
|
};
|
|
97
100
|
};
|
|
101
|
+
const getUlimits = (ulimits) => {
|
|
102
|
+
if (!ulimits) {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
return Object.entries(ulimits).map(([key, value]) => ({
|
|
106
|
+
Name: key,
|
|
107
|
+
Hard: value.hard,
|
|
108
|
+
Soft: value.soft,
|
|
109
|
+
}));
|
|
110
|
+
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExecResult } from "../../types";
|
|
2
2
|
import Dockerode from "dockerode";
|
|
3
3
|
declare type ExecContainerOptions = {
|
|
4
4
|
tty: boolean;
|
|
5
5
|
stdin: boolean;
|
|
6
6
|
detach: boolean;
|
|
7
7
|
};
|
|
8
|
-
export declare const execContainer: (container: Dockerode.Container, command:
|
|
8
|
+
export declare const execContainer: (container: Dockerode.Container, command: string[], 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
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import Dockerode from "dockerode";
|
|
2
|
-
|
|
3
|
-
export declare const getContainerById: (id: Id) => Promise<Dockerode.Container>;
|
|
2
|
+
export declare const getContainerById: (id: string) => Promise<Dockerode.Container>;
|
|
4
3
|
export declare const getContainerByHash: (hash: string) => Promise<Dockerode.Container | undefined>;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { HealthCheckStatus, Labels, NetworkSettings, Ports } from "../../types";
|
|
2
2
|
import Dockerode from "dockerode";
|
|
3
3
|
export declare type InspectResult = {
|
|
4
|
-
name:
|
|
4
|
+
name: string;
|
|
5
5
|
hostname: string;
|
|
6
6
|
ports: Ports;
|
|
7
7
|
healthCheckStatus: HealthCheckStatus;
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { DockerImageName } from "../../docker-image-name";
|
|
2
2
|
import { Labels } from "../types";
|
|
3
|
-
export declare const createLabels: (reusable: boolean, dockerImageName?: DockerImageName
|
|
3
|
+
export declare const createLabels: (reusable: boolean, dockerImageName?: DockerImageName, extraLabels?: Labels) => Labels;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { DockerImageName } from "../../../docker-image-name";
|
|
2
2
|
import { PullPolicy } from "../../../pull-policy";
|
|
3
|
-
import { BuildArgs,
|
|
3
|
+
import { BuildArgs, RegistryConfig } from "../../types";
|
|
4
4
|
export declare type BuildImageOptions = {
|
|
5
5
|
imageName: DockerImageName;
|
|
6
|
-
context:
|
|
6
|
+
context: string;
|
|
7
7
|
dockerfileName: string;
|
|
8
8
|
buildArgs: BuildArgs;
|
|
9
9
|
pullPolicy: PullPolicy;
|
|
10
10
|
registryConfig: RegistryConfig;
|
|
11
|
+
cache: boolean;
|
|
11
12
|
};
|
|
12
13
|
export declare const buildImage: (options: BuildImageOptions) => Promise<void>;
|
|
@@ -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}`);
|
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
import { Command } from "../types";
|
|
2
1
|
import Dockerode from "dockerode";
|
|
3
|
-
export declare const runInContainer: (dockerode: Dockerode, image: string, command:
|
|
2
|
+
export declare const runInContainer: (dockerode: Dockerode, image: string, command: string[]) => Promise<string | undefined>;
|