Skip to content
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 install and other http requests fail with getaddrinfo ENOENT in a Windows Docker container #2578

Closed
StefanScherer opened this issue Aug 27, 2015 · 32 comments
Labels
dns Issues and PRs related to the dns subsystem. windows Issues and PRs related to the Windows platform.

Comments

@StefanScherer
Copy link

I try to run io.js 3.2.0 inside a Windows Docker container within the Windows 2016 Technical Preview 3.
I encounter problems running npm install inside such a container (for a Windows version of the iojs:onbuild Dockerfile) and now I've reduced the problem to a simpler test code.

An http.get() (or https.get()) request fails inside the container with the error Error: getaddrinfo ENOENT

C:\app>node httpsrequest.js
events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: getaddrinfo ENOENT registry.npmjs.org:443
    at Object.exports._errnoException (util.js:837:11)
    at errnoException (dns.js:30:15)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)

C:\app>node httprequest.js
events.js:141
      throw er; // Unhandled 'error' event
      ^

Error: getaddrinfo ENOENT registry.npmjs.org:80
    at Object.exports._errnoException (util.js:837:11)
    at errnoException (dns.js:30:15)
    at GetAddrInfoReqWrap.onlookup [as oncomplete] (dns.js:76:26)

The httprequest.js test code looks like this:

'use strict';

var http = require('http');

http.get({
    host: 'registry.npmjs.org',
    path: '/'
}, function(response) {
    // Continuously update stream with data
    var body = '';
    response.on('data', function(d) {
        body += d;
    });
    response.on('end', function() {
      var parsed = JSON.parse(body);
      console.log('body', parsed);
    });
});

But using the dns module to try the lookup manually works within the same Docker container:

C:\app>node dnstest.js
dns.lookup ...
dns.lookup callback
185.31.17.162
null
dns.resolve ...
dns.resolve callback
[ '185.31.17.162' ]
null

And the dnstest.js test code used is this:

var dataDomain = 'registry.npmjs.org',
    dns = require("dns");

console.log('dns.lookup ...');
dns.lookup(dataDomain, function(error, addr){
  console.log('dns.lookup callback');
  console.log(addr);
  console.log(error);
  console.log('dns.resolve ...');
  dns.resolve(dataDomain, function(error, addr){
    console.log('dns.resolve callback');
    console.log(addr);
    console.log(error);
  });
});

Any ideas why such lookup inside http.get() fails, but dns.lookup() works fine?
This makes it hard to use Node.js/io.js inside a container at the moment.

The ipconfig /all inside the container shows this:

C:\app>ipconfig /all

Windows IP Configuration

   Host Name . . . . . . . . . . . . : vagrant-2016
   Primary Dns Suffix  . . . . . . . :
   Node Type . . . . . . . . . . . . : Hybrid
   IP Routing Enabled. . . . . . . . : No
   WINS Proxy Enabled. . . . . . . . : No
   DNS Suffix Search List. . . . . . : localdomain

Ethernet adapter vEthernet (Virtual Switch-70915fd03979c911c8fb0ec47991ce77edb326d5b0e7696d9ab1bd7f235fdd25-0):

   Connection-specific DNS Suffix  . : localdomain
   Description . . . . . . . . . . . : Hyper-V Virtual Ethernet Adapter #3
   Physical Address. . . . . . . . . : 00-15-5D-00-00-01
   DHCP Enabled. . . . . . . . . . . : Yes
   Autoconfiguration Enabled . . . . : Yes
   Link-local IPv6 Address . . . . . : fe80::851d:8eb3:494c:cd%20(Preferred)
   IPv4 Address. . . . . . . . . . . : 172.16.0.2(Preferred)
   Subnet Mask . . . . . . . . . . . : 255.240.0.0
   Default Gateway . . . . . . . . . : 172.16.0.1
   DNS Servers . . . . . . . . . . . : 192.168.254.2
   NetBIOS over Tcpip. . . . . . . . : Disabled

PS: I also tried a little GO binary inside the container which does pretty the same and that works fine within the Windows Docker container:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "os"
)

func main() {
    response, err := http.Get("http://registry.npmjs.org/")
    if err != nil {
        fmt.Printf("%s", err)
        os.Exit(1)
    } else {
        defer response.Body.Close()
        contents, err := ioutil.ReadAll(response.Body)
        if err != nil {
            fmt.Printf("%s", err)
            os.Exit(1)
        }
        fmt.Printf("%s\n", string(contents))
    }
}
C:\app>httprequest-go.exe
{"db_name":"registry","doc_count":195018,"doc_del_count":363,"update_seq":1278195,"purge_seq":0,"compact_running":false,"disk_size":5170360452,"data_size":702746874,"instance_start_time":"1435359693255822","disk_format_version":6,"committed_update_seq":1278195}
@ChALkeR ChALkeR added http Issues or PRs related to the http subsystem. windows Issues and PRs related to the Windows platform. labels Aug 27, 2015
@StefanScherer
Copy link
Author

Some more details to build the iojs and iojs:onbuild Docker Containers for Windows can be found in this small blog post.

@ChALkeR ChALkeR removed the http Issues or PRs related to the http subsystem. label Aug 27, 2015
@ChALkeR
Copy link
Member

ChALkeR commented Aug 27, 2015

Try this:

  var dns = require('dns');
  var dnsopts = {
    family: undefined,
    hints: dns.ADDRCONFIG | dns.V4MAPPED
  };
  dns.lookup('registry.npmjs.org', dnsopts, function(err, res) {
    console.log(err);
    console.log(res);
  });

I assume that it would fail. Could you confirm that?

@StefanScherer
Copy link
Author

Thanks @ChALkeR!

Yes, this indeed fails:

C:\app>node --version
v3.2.0

C:\app>node dns2.js
{ [Error: getaddrinfo ENOENT]
  code: 'ENOENT',
  errno: 'ENOENT',
  syscall: 'getaddrinfo',
  hostname: 'registry.npmjs.org' }
undefined

@ChALkeR ChALkeR added the dns Issues and PRs related to the dns subsystem. label Aug 27, 2015
@ChALkeR
Copy link
Member

ChALkeR commented Aug 27, 2015

Thanks for confirming.

http calls net.connect, and that's how it resolves an address here: lib/net.js#L907-L989.

@StefanScherer
Copy link
Author

Thanks for the pointer.

Changing the hints to 0 it works:

C:\app>node dns2.js
null
185.31.17.162

C:\app>type dns2.js
  var dns = require('dns');
  var dnsopts = {
    family: undefined,
    hints: 0 // dns.ADDRCONFIG | dns.V4MAPPED
  };
  dns.lookup('registry.npmjs.org', dnsopts, function(err, res) {
    console.log(err);
    console.log(res);
  });

@ChALkeR
Copy link
Member

ChALkeR commented Aug 27, 2015

So, if I got it right: dns.lookup(addr, callback) works, but dns.lookup(addr, {family: undefined, hints: dns.ADDRCONFIG | dns.V4MAPPED}, callback) doesn't.

Could you please check the following:

  1. dns.lookup(addr, {hints: dns.ADDRCONFIG | dns.V4MAPPED}, callback) — does not work as tested above,
  2. dns.lookup(addr, {hints: dns.ADDRCONFIG}, callback),
  3. dns.lookup(addr, {hints: dns.V4MAPPED}, callback),
  4. dns.lookup(addr, {hints: 0}, callback) — works as tested above.

@StefanScherer
Copy link
Author

OK, all combinations.

My test code dns3.js:

C:\app>type dns3.js
var dns = require('dns');

var addr = 'registry.npmjs.org';

dns.lookup(addr, {hints: dns.ADDRCONFIG | dns.V4MAPPED}, function (err, res) {
  console.log('dns.lookup(addr, {hints: dns.ADDRCONFIG | dns.V4MAPPED}');
  console.log(err);
  console.log(res);
  dns.lookup(addr, {hints: dns.ADDRCONFIG}, function (err, res) {
    console.log('dns.lookup(addr, {hints: dns.ADDRCONFIG}');
    console.log(err);
    console.log(res);
    dns.lookup(addr, {hints: dns.V4MAPPED}, function (err, res) {
      console.log('dns.lookup(addr, {hints: dns.V4MAPPED}');
      console.log(err);
      console.log(res);
      dns.lookup(addr, {hints: 0}, function (err, res) {
        console.log('dns.lookup(addr, {hints: 0}');
        console.log(err);
        console.log(res);
      });
    });
  });
});

running this in the Windows container show this:

C:\app>node dns3.js
dns.lookup(addr, {hints: dns.ADDRCONFIG | dns.V4MAPPED}
{ [Error: getaddrinfo ENOENT]
  code: 'ENOENT',
  errno: 'ENOENT',
  syscall: 'getaddrinfo',
  hostname: 'registry.npmjs.org' }
undefined
dns.lookup(addr, {hints: dns.ADDRCONFIG}
{ [Error: getaddrinfo ENOENT]
  code: 'ENOENT',
  errno: 'ENOENT',
  syscall: 'getaddrinfo',
  hostname: 'registry.npmjs.org' }
undefined
dns.lookup(addr, {hints: dns.V4MAPPED}
null
185.31.17.162
dns.lookup(addr, {hints: 0}
null
185.31.17.162

Seems that the dns.ADDRCONFIG causes the trouble.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 27, 2015

Thanks. Looks like dns.ADDRCONFIG makes dns lookup queries fail on your system.

Still, according to your ipconfig /all, your system has an non-loopback IPv4 address, so the lookup shouldn't ignore IPv4 results (see api docs and msdn for details).

The final check here would be to test getaddrinfo() function with AI_ADDRCONFIG hint, but without io.js/node, just with a simple native program.

If you want a workaround, supplying your own lookup function via options could work.
Monkey-patching dns.lookup or dns.ADDRCONFIG or even net.Socket.prototype.connect could also work as a temporary workaround, but I wouldn't recommend doing that.

@StefanScherer
Copy link
Author

I originally tried to run npm install or other 3rd party node apps/modules inside the Windows container.

The npm install ends up with an error:

C:\app>npm install
npm info it worked if it ends with ok
npm info using npm@2.13.3
npm info using node@v3.2.0
npm WARN package.json testapp@0.0.1 No repository field.
npm info preinstall testapp@0.0.1
npm info attempt registry request try #1 at 6:24:06 AM
npm http request GET https://registry.npmjs.org/mongodb
npm info retry will retry, error on last attempt: Error: getaddrinfo ENOENT registry.npmjs.org:443
npm info attempt registry request try #2 at 6:24:16 AM
npm http request GET https://registry.npmjs.org/mongodb
npm info retry will retry, error on last attempt: Error: getaddrinfo ENOENT registry.npmjs.org:443
npm info attempt registry request try #3 at 6:25:16 AM
npm http request GET https://registry.npmjs.org/mongodb
npm ERR! Windows_NT 10.0.10514
npm ERR! argv "C:\\Program Files\\iojs\\node.exe" "C:\\Program Files\\iojs\\node_modules\\npm\\bin\\npm-cli.js" "install"
npm ERR! node v3.2.0
npm ERR! npm  v2.13.3
npm ERR! code ENOENT
npm ERR! errno ENOENT
npm ERR! syscall getaddrinfo

npm ERR! enoent getaddrinfo ENOENT registry.npmjs.org:443
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! Please include the following file with any support request:
npm ERR!     C:\app\npm-debug.log

So I think I should ask someone of the Microsoft team that is currently porting Docker on Windows.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 27, 2015

@StefanScherer I updated my previous comment, please re-read it =).

The final check here would be to test getaddrinfo() function with AI_ADDRCONFIG hint, but without io.js/node, just with a simple native program.

If that fails, this is most likely a Windows/Docker related problem, If it succeeds (which I doubt), then further investigation is needed on the io.js/node side.

@StefanScherer
Copy link
Author

@ChALkeR thanks so far to get to the underlying problem. I try to build a simple Windows C application based on the example code in the msdn reference.

@StefanScherer
Copy link
Author

@ChALkeR as you expected the problem can be reproduced with a simple C application.
I've compiled a static Windows binary with AppVeyor from this public repo: https://github.com/StefanScherer/win-getaddrinfo, the binary is attached as GitHub release.

Running this static binary inside the Windows Container works with hints.ai_flags = 0, but fails with hints.ai_flags = AI_ADDRCONFIG:

C:\app>getaddrinfo.exe registry.npmjs.org 0 0
Calling getaddrinfo with following parameters:
        nodename = registry.npmjs.org
        servname (or port) = 0
        hints.ai_flags = 0x0

getaddrinfo returned success
getaddrinfo response 1
        Flags: 0x0
        Family: AF_INET (IPv4)
        IPv4 address 185.31.17.162
        Socket type: SOCK_STREAM (stream)
        Protocol: IPPROTO_TCP (TCP)
        Length of this sockaddr: 16
        Canonical name: (null)

C:\app>getaddrinfo.exe registry.npmjs.org 0 AI_ADDRCONFIG
Calling getaddrinfo with following parameters:
        nodename = registry.npmjs.org
        servname (or port) = 0
        hints.ai_flags = 0x400

getaddrinfo failed with error: 11004

So I'll open an issue in the Docker repo to ask for help there. Thanks for your help so far.
But still the Go example works right out of the box. So is there a chance to let io.js do a lookup without AI_ADDRCONFIG if it fails with it?

@ChALkeR
Copy link
Member

ChALkeR commented Aug 27, 2015

@StefanScherer, #2578 (comment):

If you want a workaround, supplying your own lookup function via options could work.
Monkey-patching dns.lookup or dns.ADDRCONFIG or even net.Socket.prototype.connect could also work as a temporary workaround, but I wouldn't recommend doing that.

I doubt that any hacks that are related to Windows 2016 bugs will land to node/io.js until that Windows version is released and is shown to be affected.

@silverwind
Copy link
Contributor

Agree with @ChALkeR, AI_ADDRCONFIG is probably there for good reasons. As a workaround til the OS bug is fixed, you can probably just disable IPv6 (which you seem to have no connectivity to) and it'll work.

@ChALkeR
Copy link
Member

ChALkeR commented Aug 28, 2015

Closing the issue for now, this looks like a bug in Windows 2016 Technical Preview 3.
If the usage of AI_ADDRCONFIG will affect a released version of Windows — post a comment here, this will be reopened.

@ChALkeR ChALkeR closed this as completed Aug 28, 2015
@StefanScherer
Copy link
Author

@silverwind I'll try that, thanks!

@sudosean
Copy link

sudosean commented Apr 21, 2016

Hi,

from TP4 I still have the same issue. I am able to get my node api into a microsoft/node image container but when I run npm install I get the following error:


npm ERR! Windows_NT 10.0.10586
npm ERR! argv "C:\\Program Files\\nodejs\\node.exe" "C:\\Program Files\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install"
npm ERR! node v5.0.0
npm ERR! npm  v3.3.6
npm ERR! code ENOENT
npm ERR! errno ENOENT
npm ERR! enoent getaddrinfo ENOENT registry.npmjs.org:443
npm ERR! enoent This is most likely not a problem with npm itself
npm ERR! enoent and is related to npm not being able to find a file.
npm ERR! enoent

npm ERR! Please include the following file with any support request:
npm ERR!     C:\PolicyManagmentAPI\PolicyAPI\PolicyAPI\npm-debug.log

@StefanScherer
Copy link
Author

@seanlarge I can confirm that.

At the moment I use this workaround in my node 5.10.1 Windows Dockerfile.

RUN wget -Uri https://github.com/StefanScherer/win-patch-iojs/releases/download/1.0.9/patchiojs.exe -OutFile patchiojs.exe -UseBasicParsing ; \
    patchiojs.exe 'C:/Program Files/nodejs/node.exe' ; \
    Remove-Item -Path patchiojs.exe

I watch the progress in moby/moby#15889 as well, there is an internal issue open at Microsoft to address this. Let's see what TP5 will do for us.

@sudosean
Copy link

sudosean commented Apr 21, 2016

@StefanScherer thank you for the quick reply...does FROM micorsoft/node not work? here is my dockerfile (I have also had a huge problem with 'invalid directories', do I need to change my WORKDIR to have quotes?):

FROM microsoft/node
#WORKDIR /api
ADD . /PolicyManagmentAPI/PolicyAPI/PolicyAPI
#RUN npm install#
#CMD ['npm','start']#

@StefanScherer
Copy link
Author

@seanlarge The microsoft/node Docker image works with the patch, I've used it in the Docker Birthday App and ported the Dockerfile to Windows.

@sudosean
Copy link

@StefanScherer Thank you so much! I will keep an eye on the open issues.

@sudosean
Copy link

@StefanScherer I end up with the following error:

Step 2 : RUN wget -Uri https://github.com/StefanScherer/win-patch-iojs/releases/download/1.0.9/patchiojs.exe -OutFile patchiojs.exe -UseBasicParsing ;     patchiojs.exe 'C:/Program Files/nodejs/node.exe' ;     Remove-Item -Path patchiojs.exe
image 6801d964fda5b67eb36e005261c1529ec96974bb02dfad52ee249638a18a93d1 does not exist

@sudosean
Copy link

@StefanScherer my dockerfile:

FROM microsoft/node
ENV NPM_CONFIG_LOGLEVEL info
ENV NODE_VERSION 5.10.1
ENV NODE_SHA256 a1207fa1e831c1347d338546e353ea195d5cb1acb7e290dad8836153aad11c35
RUN wget -Uri https://github.com/StefanScherer/win-patch-iojs/releases/download/1.0.9/patchiojs.exe -OutFile patchiojs.exe -UseBasicParsing ; \
    patchiojs.exe 'C:/Program Files/nodejs/node.exe' ; \
    Remove-Item -Path patchiojs.exe
WORKDIR /backend
ADD . /PolicyManagmentAPI/PolicyAPI/PolicyAPI
RUN npm install
ENV PORT 1337
CMD ['npm','start']

@StefanScherer
Copy link
Author

@seanlarge That's another problem of TP4. The network stack is not always up when the RUN command is already running.

RUN powershell -Command \
    Sleep 2 ; \
    wget -Uri https://github.com/StefanScherer/win-patch-iojs/releases/download/1.0.9/patchiojs.exe -OutFile patchiojs.exe -UseBasicParsing ; \
    patchiojs.exe 'C:/Program Files/nodejs/node.exe' ; \
    Remove-Item -Path patchiojs.exe

This is a workaround for TP4, in TP5 the sleep is no longer needed:

RUN powershell -Command \
    wget -Uri https://github.com/StefanScherer/win-patch-iojs/releases/download/1.0.9/patchiojs.exe -OutFile patchiojs.exe -UseBasicParsing ; \
    patchiojs.exe 'C:/Program Files/nodejs/node.exe' ; \
    Remove-Item -Path patchiojs.exe

PS: Perhaps I forgot the powershell -Command in my comments above.

@sudosean
Copy link

@StefanScherer still the same issue =( not sure what to do.

result:

Step 2 : RUN powershell -Command     Sleep 2 ;     wget -Uri https://github.com/StefanScherer/win-patch-iojs/releases/download/1.0.9/patchiojs.exe -OutFile patchiojs.exe -UseBasicParsing ;     patchiojs.exe 'C:/Program Files/nodejs/node.exe' ;     Remove-Item -Path patchiojs.exe
image 6801d964fda5b67eb36e005261c1529ec96974bb02dfad52ee249638a18a93d1 does not exist

dockerfile:

FROM microsoft/node
RUN powershell -Command \
    Sleep 2 ; \
    wget -Uri https://github.com/StefanScherer/win-patch-iojs/releases/download/1.0.9/patchiojs.exe -OutFile patchiojs.exe -UseBasicParsing ; \
    patchiojs.exe 'C:/Program Files/nodejs/node.exe' ; \
    Remove-Item -Path patchiojs.exe
WORKDIR /backend
ADD . /PolicyManagmentAPI/PolicyAPI/PolicyAPI
RUN npm install
ENV PORT 1337
CMD ['npm','start']

@sudosean
Copy link

same thing with docker file from https://github.com/StefanScherer/dockerfiles-windows/blob/776120fb5b24c68e73243eb74b440eb4f2c24059/node/5.9/Dockerfile#L13-L15

I tired FROM windowsservercore instead of microsoft/node, same result.

@StefanScherer the problem is that there is no network connection?

FROM windowsservercore

ENV NPM_CONFIG_LOGLEVEL info \
    NODE_VERSION 5.9.0 \
    NODE_SHA256 f53fac35122dfaec568f998fc210d4ead423c7939c024cd51e240879efd6845b

RUN powershell -Command \
    Sleep 2 ; \
    wget -Uri https://nodejs.org/dist/v%NODE_VERSION%/node-v%NODE_VERSION%-x64.msi -OutFile node.msi -UseBasicParsing ; \
    if ((Get-FileHash node.msi -Algorithm sha256).Hash -ne $env:NODE_SHA256) {exit 1} ; \
    Start-Process -FilePath msiexec -ArgumentList /q, /i, node.msi -Wait ; \
    Remove-Item -Path node.msi ; \
    wget -Uri https://github.com/StefanScherer/win-patch-iojs/releases/download/1.0.9/patchiojs.exe -OutFile patchiojs.exe -UseBasicParsing ; \
    patchiojs.exe 'C:/Program Files/nodejs/node.exe' ; \
    Remove-Item -Path patchiojs.exe

WORKDIR /backend
ADD . /PolicyManagmentAPI/PolicyAPI/PolicyAPI
RUN npm install
ENV PORT 1337
CMD ['npm','start']

@juddybuddy77
Copy link

juddybuddy77 commented Apr 24, 2016

Same issue here.
Tried applying the patch manually, no problem there, still can't get NPM to work in the container. Unfortunately don't know enough to attempt to patch myself, so I'll site back quietly and watch for now. Thanks for posting this.

Woah, moving too fast there, not sure why running the patch failed the first time, this time got the message it was updating hints, after fixing the npm registry it worked. Thank you!

@StefanScherer
Copy link
Author

It seems that is fixed in TP5. Got npm install working inside a windowsservercore container without a patched node.exe.

@binarymist
Copy link

If using Docker, this known issue is discussed in detail here: https://development.robinwinslow.uk/2016/06/23/fix-docker-networking-dns/

Simple fix is to create the file /etc/docker/daemon.json

and insert:

{
    "dns": ["10.0.0.2", "8.8.8.8"]
}

where 10.0.0.2 is the first DNS server your machine requests records from, and 8.8.8.8 is the fallback DNS server, google in this case.

@grantwparks
Copy link

binarymist - Where's the /etc dir on Windows?

@binarymist
Copy link

binarymist commented Dec 22, 2018

%systemroot%\system32\drivers\etc
Usually:
C:\Windows\System32\drivers\etc
I'm thinking
PS: It's usually quicker and easier to ask a search engine these types of generic questions.

@grantwparks
Copy link

I'm just trying to point out that a linux answer is not relevant.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
dns Issues and PRs related to the dns subsystem. windows Issues and PRs related to the Windows platform.
Projects
None yet
Development

No branches or pull requests

7 participants