Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions docs/features/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ const container = await GenericContainer
.build();
```

### Using BuildKit

```javascript
const container = await GenericContainer
.fromDockerfile("/path/to/build-context")
.withBuildKit()
.build();
```

## Image name substitution

Testcontainers supports automatic substitution of Docker image names.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
FROM node:10-alpine

MAINTAINER Cristian Greco

EXPOSE 8080

RUN --mount=type=cache,target=/var/cache/apk apk add --no-cache curl dumb-init libcap openssl

RUN openssl req -x509 -nodes -days 36500 \
-subj "/C=CA/ST=QC/O=Company Inc/CN=localhost" \
-newkey rsa:2048 -keyout /etc/ssl/private/cert.key \
-out /etc/ssl/certs/cert.crt \
&& chmod 666 /etc/ssl/private/cert.key

RUN npm init -y \
&& npm install [email protected]

COPY index.js .

ENTRYPOINT ["/usr/bin/dumb-init", "--"]
CMD ["node", "index.js"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
const fs = require("fs");
const http = require("http");
const https = require("https");
const express = require("express");

const app = express();

app.get("/hello-world", (req, res) => {
res.status(200).send("hello-world");
});

app.get("/hello-world-delay", (req, res) => {
setTimeout(() => {
res.status(200).send("hello-world");
}, 3000);
});

app.post("/hello-world-post", (req, res) => {
res.status(200).send("hello-world");
});

app.get("/env", (req, res) => {
res.status(200).json(process.env);
});

app.get("/cmd", (req, res) => {
res.status(200).json(process.argv);
});

app.get("/auth", (req, res) => {
const auth = req.headers.authorization;
const [, base64Encoded] = auth.split(" ");
const credentials = Buffer.from(base64Encoded, "base64").toString("ascii");
const [username, password] = credentials.split(":");
if (username === "user" && password === "pass") {
res.status(200).end();
} else {
res.status(401).end();
}
});

app.get("/header-or-400/:headerName", (req, res) => {
if (req.headers[req.params["headerName"]] !== undefined) {
res.status(200).end();
} else {
res.status(400).end();
}
});

const PORT = 8080;
const TLS_PORT = 8443;

http.createServer(app).listen(PORT, () => console.log(`Listening on port ${PORT}`));
https
.createServer(
{
key: fs.readFileSync("/etc/ssl/private/cert.key", "utf8"),
cert: fs.readFileSync("/etc/ssl/certs/cert.crt", "utf8"),
},
app
)
.listen(TLS_PORT, () => console.log(`Listening on secure port ${TLS_PORT}`));
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
hello world
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getAuthConfig, getContainerRuntimeClient, ImageName } from "../containe
import { getReaper } from "../reaper/reaper";
import { getDockerfileImages } from "../utils/dockerfile-parser";
import { createLabels, LABEL_TESTCONTAINERS_SESSION_ID } from "../utils/labels";
import type { ImageBuildOptions } from "dockerode";

export type BuildOptions = {
deleteOnExit: boolean;
Expand All @@ -17,6 +18,7 @@ export class GenericContainerBuilder {
private pullPolicy: ImagePullPolicy = PullPolicy.defaultPolicy();
private cache = true;
private target?: string;
private useBuildKit = false;

constructor(
private readonly context: string,
Expand Down Expand Up @@ -44,6 +46,11 @@ export class GenericContainerBuilder {
return this;
}

public withBuildKit(useBuildKit = true): this {
this.useBuildKit = useBuildKit;
return this;
}

public async build(
image = `localhost/${this.uuid.nextUuid()}:${this.uuid.nextUuid()}`,
options: BuildOptions = { deleteOnExit: true }
Expand All @@ -66,12 +73,13 @@ export class GenericContainerBuilder {
t: imageName.string,
dockerfile: this.dockerfileName,
buildargs: this.buildArgs,
pull: this.pullPolicy ? "true" : undefined,
pull: this.pullPolicy.shouldPull() ? "true" : undefined,
nocache: !this.cache,
registryconfig: registryConfig,
labels,
target: this.target,
});
version: this.useBuildKit ? "2" : undefined,
} as ImageBuildOptions);

const container = new GenericContainer(imageName.string);
if (!(await client.image.exists(imageName))) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,4 +102,14 @@ describe("GenericContainer Dockerfile", () => {

await startedContainer.stop();
});

it("should work with buildKit", async () => {
const context = path.resolve(fixtures, "docker-with-buildkit-features");
const container = await GenericContainer.fromDockerfile(context).withBuildKit().build();
const startedContainer = await container.withExposedPorts(8080).start();

await checkContainerIsHealthy(startedContainer);

await startedContainer.stop();
});
});