Skip to content
Merged
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
11 changes: 11 additions & 0 deletions docs/features/images.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ const container = await GenericContainer
.build("my-custom-image", { deleteOnExit: false });
```

### With buildkit

```javascript
const { GenericContainer } = require("testcontainers");

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

### With a pull policy

Testcontainers will automatically pull an image if it doesn't exist. This is configurable:
Expand Down
119 changes: 62 additions & 57 deletions package-lock.json

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
FROM node:10-alpine

MAINTAINER Cristian Greco

EXPOSE 8080

RUN --mount=type=tmpfs,target=/buildkit-test \
echo "BuildKit tmpfs mount is working" > /buildkit-test/success.txt && \
cat /buildkit-test/success.txt

RUN 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,7 @@
services:
container:
build:
context: .
dockerfile: Dockerfile
ports:
- 8080
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,25 @@
FROM node:10-alpine

MAINTAINER Cristian Greco

EXPOSE 8080

RUN --mount=type=tmpfs,target=/buildkit-test \
echo "BuildKit tmpfs mount is working" > /buildkit-test/success.txt && \
cat /buildkit-test/success.txt

RUN 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}`));
4 changes: 2 additions & 2 deletions packages/testcontainers/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@
},
"dependencies": {
"@balena/dockerignore": "^1.0.2",
"@types/dockerode": "^3.3.29",
"@types/dockerode": "^3.3.35",
"archiver": "^7.0.1",
"async-lock": "^1.4.1",
"byline": "^5.0.0",
"debug": "^4.3.5",
"docker-compose": "^0.24.8",
"dockerode": "^3.3.5",
"dockerode": "^4.0.4",
"get-port": "^7.1.0",
"proper-lockfile": "^4.1.2",
"properties-reader": "^2.3.0",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ describe("DockerComposeEnvironment", { timeout: 180_000 }, () => {
await startedEnvironment.down();
});

if (!process.env.CI_PODMAN) {
it("should work with buildkit", async () => {
const buildkitFixtures = path.resolve(fixtures, "docker-compose-with-buildkit");
const startedEnvironment = await new DockerComposeEnvironment(buildkitFixtures, "docker-compose.yml").up();
await checkEnvironmentContainerIsHealthy(startedEnvironment, await composeContainerName("container"));
await startedEnvironment.down();
});
}

it("should use pull policy", async () => {
const env = new DockerComposeEnvironment(fixtures, "docker-compose-with-many-services.yml");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export class GenericContainerBuilder {
private buildArgs: BuildArgs = {};
private pullPolicy: ImagePullPolicy = PullPolicy.defaultPolicy();
private cache = true;
private buildkit = false;
private target?: string;
private platform?: string;

Expand All @@ -41,6 +42,11 @@ export class GenericContainerBuilder {
return this;
}

public withBuildkit(): this {
this.buildkit = true;
return this;
}

public withPlatform(platform: string): this {
this.platform = platform;
return this;
Expand Down Expand Up @@ -79,6 +85,7 @@ export class GenericContainerBuilder {
labels,
target: this.target,
platform: this.platform,
version: this.buildkit ? "2" : "1",
};

if (this.pullPolicy.shouldPull()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ describe("GenericContainer Dockerfile", { timeout: 180_000 }, () => {
await startedContainer.stop();
});

if (!process.env.CI_PODMAN) {
it("should build with buildkit", async () => {
const context = path.resolve(fixtures, "docker-with-buildkit");
const container = await GenericContainer.fromDockerfile(context).withBuildkit().build();
const startedContainer = await container.withExposedPorts(8080).start();

await checkContainerIsHealthy(startedContainer);

await startedContainer.stop();
});
}

it("should have a session ID label to be cleaned up by the Reaper", async () => {
const context = path.resolve(fixtures, "docker");
const imageName = `${uuidGen.nextUuid()}:${uuidGen.nextUuid()}`;
Expand Down