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.
Files changed (60) hide show
  1. package/README.md +160 -43
  2. package/dist/bound-ports.d.ts +4 -4
  3. package/dist/docker/docker-client.d.ts +1 -2
  4. package/dist/docker/functions/container/container-logs.js +1 -6
  5. package/dist/docker/functions/container/create-container.d.ts +9 -5
  6. package/dist/docker/functions/container/create-container.js +19 -6
  7. package/dist/docker/functions/container/exec-container.d.ts +2 -2
  8. package/dist/docker/functions/container/exec-container.js +10 -3
  9. package/dist/docker/functions/container/get-container.d.ts +1 -2
  10. package/dist/docker/functions/container/inspect-container.d.ts +2 -2
  11. package/dist/docker/functions/create-labels.d.ts +1 -1
  12. package/dist/docker/functions/image/build-image.d.ts +3 -2
  13. package/dist/docker/functions/image/build-image.js +14 -9
  14. package/dist/docker/functions/run-in-container.d.ts +1 -2
  15. package/dist/docker/types.d.ts +29 -22
  16. package/dist/docker-compose/default-docker-compose-options.d.ts +1 -1
  17. package/dist/docker-compose/default-docker-compose-options.js +2 -2
  18. package/dist/docker-compose/docker-compose-options.d.ts +2 -2
  19. package/dist/docker-compose/functions/docker-compose-down.d.ts +2 -1
  20. package/dist/docker-compose/functions/docker-compose-down.js +12 -2
  21. package/dist/docker-compose/functions/docker-compose-up.d.ts +1 -1
  22. package/dist/docker-compose/functions/docker-compose-up.js +1 -1
  23. package/dist/docker-compose-environment/docker-compose-environment.d.ts +5 -5
  24. package/dist/docker-compose-environment/docker-compose-environment.js +12 -12
  25. package/dist/docker-compose-environment/started-docker-compose-environment.d.ts +2 -1
  26. package/dist/docker-compose-environment/started-docker-compose-environment.js +3 -2
  27. package/dist/docker-compose-environment/stopped-docker-compose-environment.d.ts +2 -1
  28. package/dist/docker-compose-environment/stopped-docker-compose-environment.js +3 -2
  29. package/dist/generic-container/generic-container-builder.d.ts +5 -3
  30. package/dist/generic-container/generic-container-builder.js +8 -2
  31. package/dist/generic-container/generic-container.d.ts +24 -17
  32. package/dist/generic-container/generic-container.js +48 -24
  33. package/dist/generic-container/started-generic-container.d.ts +7 -8
  34. package/dist/generic-container/started-generic-container.js +1 -2
  35. package/dist/logger.d.ts +1 -0
  36. package/dist/logger.js +2 -1
  37. package/dist/modules/abstract-started-container.d.ts +6 -7
  38. package/dist/modules/arangodb/arangodb-container.js +2 -2
  39. package/dist/modules/elasticsearch/elasticsearch-container.js +2 -2
  40. package/dist/modules/kafka/kafka-container.d.ts +4 -5
  41. package/dist/modules/kafka/kafka-container.js +41 -34
  42. package/dist/modules/mongodb/mongodb-container.js +1 -1
  43. package/dist/modules/mysql/mysql-container.d.ts +1 -2
  44. package/dist/modules/mysql/mysql-container.js +7 -5
  45. package/dist/modules/nats/nats-container.d.ts +1 -1
  46. package/dist/modules/nats/nats-container.js +2 -2
  47. package/dist/modules/neo4j/neo4j-container.js +10 -4
  48. package/dist/modules/postgresql/postgresql-container.d.ts +1 -2
  49. package/dist/modules/postgresql/postgresql-container.js +5 -3
  50. package/dist/port-binder.d.ts +1 -2
  51. package/dist/port-check.d.ts +4 -6
  52. package/dist/port-check.js +1 -1
  53. package/dist/port-forwarder.d.ts +1 -2
  54. package/dist/port-forwarder.js +2 -2
  55. package/dist/port-generator.d.ts +4 -5
  56. package/dist/port.d.ts +3 -5
  57. package/dist/reaper.js +1 -1
  58. package/dist/test-container.d.ts +24 -14
  59. package/dist/test-containers.d.ts +1 -2
  60. package/package.json +29 -25
package/README.md CHANGED
@@ -5,8 +5,6 @@
5
5
  [![Node.js CI](https://github.com/testcontainers/testcontainers-node/actions/workflows/node.js.yml/badge.svg?branch=master)](https://github.com/testcontainers/testcontainers-node/actions/workflows/node.js.yml)
6
6
  [![npm version](https://badge.fury.io/js/testcontainers.svg)](https://www.npmjs.com/package/testcontainers)
7
7
  [![npm version](https://img.shields.io/npm/dm/testcontainers.svg)](https://www.npmjs.com/package/testcontainers)
8
- [![Thundra Foresight](https://thundra-assets-prod.s3.us-west-2.amazonaws.com/images/badges/thundra-foresight-badge-enabled.svg)](https://foresight.thundra.live/testRuns/57175ecb-d5ac-4129-957a-9dd617fd27d0)
9
- [![Foresight Test Summary](https://foresight.service.thundra.us/public/api/v1/badge/test/57175ecb-d5ac-4129-957a-9dd617fd27d0)](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
- .withBuildArg("ARG_KEY", "ARG_VALUE")
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
- .withCmd(["sleep", "infinity"])
167
+ .withCommand(["sleep", "infinity"])
154
168
  .withReuse()
155
169
  .start();
156
170
 
157
171
  const container2 = await new GenericContainer("alpine")
158
- .withCmd(["sleep", "infinity"])
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
- .withCmd(["sleep", "infinity"])
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
- .withCmd(["sleep", "infinity"])
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
- .withBindMount("/local/file.txt", "/remote/file.txt")
230
- .withBindMount("/local/dir", "/remote/dir", "ro")
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
- .withCopyFileToContainer("/local/file.txt", "/remote/file1.txt")
253
- .withCopyContentToContainer("hello world", "/remote/file2.txt")
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
- .withEnv("ENV_KEY", "ENV_VALUE")
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
- Creating a container that connects to a specific network:
335
+ To execute the `test` in a shell use the form `["CMD-SHELL", "command"]`, for example:
298
336
 
299
337
  ```javascript
300
- const { GenericContainer } = require("testcontainers");
338
+ ["CMD-SHELL", "curl -f http://localhost:8000 || exit 1"]
339
+ ```
301
340
 
302
- const container = await new GenericContainer("alpine")
303
- .withNetworkMode("network_name")
304
- .start();
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
- Create user-defined bridge network and attach the container to it:
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
- .start();
353
+ .start();
314
354
 
315
355
  const container = await new GenericContainer("alpine")
316
- .withNetworkMode(network.getName())
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
- .withCmd(["sleep", "infinity"])
333
- .withNetworkMode(network.getName())
382
+ .withCommand(["sleep", "infinity"])
383
+ .withNetwork(network)
334
384
  .start();
335
385
 
336
386
  const fooContainer = await new GenericContainer("alpine")
337
- .withCmd(["sleep", "infinity"])
338
- .withNetworkMode(network.getName())
387
+ .withCommand(["sleep", "infinity"])
388
+ .withNetwork(network)
339
389
  .withNetworkAliases("foo", "bar")
340
390
  .start();
341
391
 
342
- expect((await container.exec(["nslookup", "foo"])).exitCode).toBe(0);
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
- { host: "foo", ipAddress: "10.11.12.13" },
353
- { host: "bar", ipAddress: "11.12.13.14" }
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(["nslookup", "foo"])).exitCode).toBe(0);
358
- expect((await container.exec(["nslookup", "bar"])).exitCode).toBe(0);
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
- .withNetworkMode(network.getName())
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
- .withCmd(["sleep", "infinity"])
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).up();
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]).up();
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).up();
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
- .withEnv("TAG", "value")
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 | Default
730
- | --- | --- | --- |
731
- | ryuk | `RYUK_CONTAINER_IMAGE` | `testcontainers/ryuk:0.3.2` |
732
- | SSHd | `SSHD_CONTAINER_IMAGE` | `testcontainers/sshd:1.0.0` |
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
 
@@ -1,10 +1,10 @@
1
- import { Port, PortWithOptionalBinding } from "./port";
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: Port): Port;
6
- setBinding(key: Port, value: Port): void;
7
- iterator(): Iterable<[Port, Port]>;
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: 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 options = {
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, Command, ContainerName, Env, ExtraHost, HealthCheck, Labels, NetworkMode, TmpFs } from "../../types";
4
+ import { BindMount, Environment, ExtraHost, HealthCheck, Labels, TmpFs, Ulimits } from "../../types";
5
5
  export declare type CreateContainerOptions = {
6
6
  imageName: DockerImageName;
7
- env: Env;
8
- cmd: Command[];
7
+ environment: Environment;
8
+ command: string[];
9
+ entrypoint?: string[];
9
10
  bindMounts: BindMount[];
10
11
  tmpFs: TmpFs;
11
12
  exposedPorts: PortWithOptionalBinding[];
12
- name?: ContainerName;
13
+ name?: string;
13
14
  reusable: boolean;
14
15
  labels?: Labels;
15
- networkMode?: 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: getEnv(options.env),
25
+ Env: getEnvironment(options.environment),
26
26
  ExposedPorts: getExposedPorts(options.exposedPorts),
27
- Cmd: options.cmd,
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 getEnv = (env) => Object.entries(env).reduce((dockerodeEnvironment, [key, value]) => [...dockerodeEnvironment, `${key}=${value}`], []);
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, bindMode }) => `${source}:${target}:${bindMode}`);
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: ["CMD-SHELL", healthCheck.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 { Command, ExecResult } from "../../types";
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: Command[], options: ExecContainerOptions) => Promise<ExecResult>;
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 execContainer = (container, command, options) => __awaiter(void 0, void 0, void 0, function* () {
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
- import { Id } from "../../types";
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 { ContainerName, HealthCheckStatus, Labels, NetworkSettings, Ports } from "../../types";
1
+ import { HealthCheckStatus, Labels, NetworkSettings, Ports } from "../../types";
2
2
  import Dockerode from "dockerode";
3
3
  export declare type InspectResult = {
4
- name: ContainerName;
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 | undefined, extraLabels?: Labels) => Labels;
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, BuildContext, RegistryConfig } from "../../types";
3
+ import { BuildArgs, RegistryConfig } from "../../types";
4
4
  export declare type BuildImageOptions = {
5
5
  imageName: DockerImageName;
6
- context: BuildContext;
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
- return new Promise((resolve) => dockerode
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
- .then((stream) => (0, byline_1.default)(stream))
50
- .then((stream) => {
51
- stream.setEncoding("utf-8");
52
- stream.on("data", (line) => logger_1.log.trace(`${options.imageName.toString()}: ${line}`));
53
- stream.on("end", () => resolve());
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: Command[]) => Promise<string | undefined>;
2
+ export declare const runInContainer: (dockerode: Dockerode, image: string, command: string[]) => Promise<string | undefined>;