apocas / docker-modem

Docker Remote API network stack driver.
Apache License 2.0
234 stars 112 forks source link

Uncatchable DNS errors #176

Open MorningLightMountain713 opened 3 months ago

MorningLightMountain713 commented 3 months ago

If a user adds a leading backslash to an image name, it causes an uncatchable DNS error to be thrown. One of ENOTFOUND, EAI_AGAIN or ESERVFAIL.

I am working around this currently by catching this globally with process.on('uncaughtException', ...) but it's ugly.

Error: (HTTP code 301) unexpected -
    at /home/davew/testDocker/node_modules/docker-modem/lib/modem.js:382:17
    at getCause (/home/davew/testDocker/node_modules/docker-modem/lib/modem.js:417:7)
    at Modem.buildPayload (/home/davew/testDocker/node_modules/docker-modem/lib/modem.js:378:5)
    at IncomingMessage.<anonymous> (/home/davew/testDocker/node_modules/docker-modem/lib/modem.js:346:16)
    at IncomingMessage.emit (node:events:526:35)
    at endReadableNT (node:internal/streams/readable:1408:12)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  reason: undefined,
  statusCode: 301,
  json: <Buffer >
}
node:events:492
      throw er; // Unhandled 'error' event
      ^

Error: getaddrinfo EAI_AGAIN images
    at GetAddrInfoReqWrap.onlookupall [as oncomplete] (node:dns:118:26)
Emitted 'error' event on ClientRequest instance at:
    at Socket.socketErrorListener (node:_http_client:495:9)
    at Socket.emit (node:events:514:28)
    at emitErrorNT (node:internal/streams/destroy:151:8)
    at emitErrorCloseNT (node:internal/streams/destroy:116:3)
    at process.processTicksAndRejections (node:internal/process/task_queues:82:21) {
  errno: -3001,
  code: 'EAI_AGAIN',
  syscall: 'getaddrinfo',
  hostname: 'images'
}

Node.js v20.9.0

Here is an MRE:

const Dockerode = require('dockerode');

const docker = new Dockerode();

async function main() {
    image = docker.getImage('/nginx:latest');
    await image.remove().catch((err) => console.log(err));

    await new Promise((r) => setTimeout(r, 3_000_000));
}

main();

Reading the docker docs, it states The path consists of slash-separated components., which implies that they can't start or end with a slash. The easy solution here is to throw an error in Modem.prototype.dial if the path starts with a slash.