-
Notifications
You must be signed in to change notification settings - Fork 5.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
npm:docker-modem doesn't work (and @testcontainers/* as a result) #20255
Comments
I just ran into something similar. When I debugged I saw requests being made to http://localhost instead of /var/run/docker.sock. |
I am also hitting this. Is there any workaround? |
I adapted the workaround proposed by apocas/dockerode#747 (comment) /******************************************************
* Begin workarounds for this showstopper issue:
* https://github.com/apocas/dockerode/issues/747
*/
async function startProxy() {
// Listen on TCP port 3000
const tcpListener = Deno.listen({ port: 3000 });
console.log("Listening on TCP port 3000");
for await (const tcpConn of tcpListener) {
handleConnection(tcpConn);
}
}
async function handleConnection(tcpConn: Deno.Conn) {
try {
// Connect to the Unix socket at /var/run/docker.sock
const unixConn = await Deno.connect({ transport: "unix", path: "/var/run/docker.sock" });
// Bidirectional forwarding
const tcpToUnix = copy(tcpConn, unixConn);
const unixToTcp = copy(unixConn, tcpConn);
// Wait for both copy operations to complete
await Promise.all([tcpToUnix, unixToTcp]);
} catch (error) {
console.error("Error handling connection:", error);
} finally {
tcpConn.close();
}
}
// Utility function to copy data from one stream to another
async function copy(src: Deno.Reader, dst: Deno.Writer) {
const buffer = new Uint8Array(1024);
while (true) {
const bytesRead = await src.read(buffer);
if (bytesRead === null) break;
let offset = 0;
while (offset < bytesRead) {
const bytesWritten = await dst.write(buffer.subarray(offset, bytesRead));
offset += bytesWritten;
}
}
}
// Start the proxy
startProxy();
// and this now needs to be changed because of the above:
// const docker = new Docker({socketPath: "/var/run/docker.sock"});
const docker = new Docker({protocol: 'http', host: 'localhost', port: 3000});
/******************************************************
* End workarounds for this showstopper issue:
* https://github.com/apocas/dockerode/issues/747
*/ |
This is the only thing keeping me from adopting Deno in one of my projects btw (lack of testcontainers support). |
Thanks @dionjwa, was hitting the same issue on Deno 2, but thanks to the workaround I can continue! |
I've tried to combine @dionjwa's solution to work with testcontainers: // docker-proxy.ts
import type { Reader, Writer } from "jsr:@std/io@0.225";
export async function startProxy() {
const tcpListener = Deno.listen({ port: 2375 });
for await (const tcpConn of tcpListener) {
handleConnection(tcpConn);
}
return tcpListener;
}
async function handleConnection(tcpConn: Deno.Conn) {
try {
// Connect to the Unix socket at /var/run/docker.sock
const unixConn = await Deno.connect({
transport: "unix",
path: "/var/run/docker.sock",
});
// Bidirectional forwarding
const tcpToUnix = copy(tcpConn, unixConn);
const unixToTcp = copy(unixConn, tcpConn);
// Wait for both copy operations to complete
await Promise.all([tcpToUnix, unixToTcp]);
} catch (error) {
console.error("Error handling connection:", error);
} finally {
tcpConn.close();
}
}
// Utility function to copy data from one stream to another
async function copy(src: Reader, dst: Writer) {
const buffer = new Uint8Array(1024);
while (true) {
const bytesRead = await src.read(buffer);
if (bytesRead === null) break;
let offset = 0;
while (offset < bytesRead) {
const bytesWritten = await dst.write(buffer.subarray(offset, bytesRead));
offset += bytesWritten;
}
}
} // main.ts
import { GenericContainer } from "testcontainers";
import { startProxy } from "./docker-proxy.ts";
startProxy();
Deno.env.set("DOCKER_HOST", "tcp://localhost:2375");
const container = new GenericContainer("alpine");
const startedContainer = await container.start();
await startedContainer.stop(); Then: ❯ deno run -A main.ts
error: Uncaught (in promise) TypeError: stream.socket.unref is not a function
at DockerContainerClient.logs (file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/container-runtime/clients/container/docker-container-client.js:165:27)
at eventLoopTick (ext:core/01_core.js:175:7)
at async LogWaitStrategy.waitUntilReady (file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/wait-strategies/log-wait-strategy.js:22:24)
at async waitForContainer (file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/wait-strategies/wait-for-container.js:8:9)
at async GenericContainer.startContainer (file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/generic-container/generic-container.js:143:9)
at async createNewReaper (file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/reaper/reaper.js:62:30)
at async file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/reaper/reaper.js:29:20
at async withFileLock (file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/common/file-lock.js:41:16)
at async getReaper (file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/reaper/reaper.js:19:14)
at async GenericContainer.start (file:///home/felipecrs/.cache/deno/npm/registry.npmjs.org/testcontainers/10.13.2/build/generic-container/generic-container.js:75:28) Which refs to a function not yet implemented apparently: I believe it could be related to this issue: Which is a different compatibility issue. |
I managed to get it working by mocking import { ClientRequest } from "node:http";
import * as io from "jsr:@std/io";
const originalSocket = ClientRequest.prototype.onSocket;
ClientRequest.prototype.onSocket = function (socket) {
socket.unref = function () { return this; };
return originalSocket.call(this, socket);
}
async function startProxy() {
const tcpListener = Deno.listen({ port: 3000 });
for await (const tcpConn of tcpListener) {
handleConnection(tcpConn);
}
}
async function handleConnection(tcpConn: Deno.Conn) {
try {
const unixConn = await Deno.connect({ transport: "unix", path: "/var/run/docker.sock" });
await Promise.all([
io.copy(tcpConn, unixConn),
io.copy(unixConn, tcpConn),
]);
} catch (error) {
console.error("Error handling connection:", error);
} finally {
tcpConn.close();
}
} |
The blog post said we should report, so here we go:
I just trying to use testcontainers (@testcontainers/postgresql) with Deno when I got this strange error:
So it seems there might be some http client compatibility issues, as the docker api is just HTTP last time I checked...
Here's the repro code which was inspired by this Testcontainer Node quickstart repo (which runs fine using node):
The text was updated successfully, but these errors were encountered: