docker-modem icon indicating copy to clipboard operation
docker-modem copied to clipboard

Requests that return HttpDuplex (eg docker exec start) hang when using named pipe on windows.

Open pirog opened this issue 6 years ago • 2 comments

Found an interesting situation that i was able to track down a bit. I am unsure if this is a bug with docker-modem or potentially how Docker for Windows sets up the named pipe to begin with.

Here is a file to reproduce (uses latest node-docker-api but upgraded to docker-modem 1.0.0), the same thing happens if you use analogous code for dockerode

'use strict'
const Docker = require('node-docker-api').Docker

const promisifyStream = (stream) => new Promise((resolve, reject) => {
  stream.on('data', (d) => console.log(d.toString()))
  stream.on('end', () => {
      if (process.stdin.setRawMode) {
        process.stdin.setRawMode(false);
      }
      process.stdin.pause();
      resolve()
  })
  stream.on('error', reject)
})

var thing
const docker = new Docker({ socketPath: '//./pipe/docker_engine' })
//const docker = new Docker({host: '127.0.0.1', port: 2375})
let _container

  docker.container.create({
    Image: 'debian:jessie',
    Cmd: [ '/bin/bash', '-c', 'tail -f /var/log/dmesg' ]
  })
  .then((container) => container.start())
  .then((container) => {
    _container = container
    return container.exec.create({
	    AttachStdin: true,
	    AttachStdout: true, 
	    AttachStderr: true,
	    Cmd: ['echo', 'thing'],
	    Tty: true
    })
  })
  .then((exec) => {
    return exec.start({ 
      hijack: false,
      Detach: false,
      Tty: true,
      stdin: true,
    })
  })
  .then((stream) => {
  	thing = stream
  })
  .then(() => {
  	thing.pipe(process.stdout);    

  	// Restart stdin with correct encoding
  	process.stdin.resume();
  	process.stdin.setEncoding('utf8');

  	// Make sure rawMode matches up
  	if (process.stdin.setRawMode) {
  	  process.stdin.setRawMode(true);
  	}        

  	// Send our processes stdin into the container
  	process.stdin.pipe(thing);

  })
  .then(() => promisifyStream(thing))
  .then(() => _container.delete({force: true}))
  .catch((error) => console.log(error))

If you connect over tcp (need to allow insecure connections in the docker for windows app first), it works as expected but if you switch over to the named pipe it will hang after "thing" is written to stdout. What is extremely interesting is after this happens you can get the stream to close and the process to resume by pressing any key three times.

Another interesting data point here is it looks like docker-compose itself avoids using the API for this on Windows, deciding to just delegate directly to a shell call to docker exec. see: https://github.com/docker/compose/blob/master/compose/cli/main.py#L411

My best guesses at this point are:

  1. there is is some additional buffer with named pipes that is not being correctly flushed and its causing things to hang up
  2. writes are not happening or getting lost duringish reads

Any thoughts about why this could be happening?

pirog avatar Jul 22 '17 21:07 pirog

Hi, I'm most likely running in to the same problem with Dockerode 2.5.4 which relies on Docker-modem 1.0.4 . Anything with exec.start gets stuck and won't terminate properly.

JoonasVali avatar Dec 13 '18 11:12 JoonasVali

docker desktop 4.12 has a compatibility shim that should fix this. https://docs.docker.com/desktop/release-notes/#bug-fixes-and-minor-changes see my comments about it here: https://github.com/apocas/dockerode/issues/534

nicks avatar Sep 01 '22 20:09 nicks