Since your Dockerfile has a line reading RUN yarn
(i.e. not using yarn's offline options), yarn attempts to determine if the internet is likely to be available automatically without sending any packets.
How does yarn check online status?
This is done by enumerating the available network interfaces in the docker builder context using node's os.networkInterfaces()
, which is documented here.
This in turn calls GetInterfaceAddresses
which is backed by libuv's uv_interface_addresses
. The libuv function only returns interfaces that have an IP address assigned and the IFF_UP
and IFF_RUNNING
flags set.
To see which addresses are actually being returned to Javascript code, you can temporarily add this line to your Dockerfile:
RUN node -e 'const os = require("os"); const interfaces = os.networkInterfaces(); for (const interface in interfaces) {console.log(interface); const addrs = interfaces[interface]; for (const addr of addrs) {console.log(addr.address)}}'
At least in my case this only returned the loopback address, which yarn explicitly ignores in 1:
lo
127.0.0.1
::1
But running ifconfig
in the docker image showed an eth0
interface as well. The HWaddr
of this interface matches that of the docker0
interface on the machine running the docker daemon. This suggests the builder context runs with the docker bridge network.
So what criteria is excluding the bridge network from libuv's list?
In my case, the docker network did not set IFF_RUNNING
. This is not too surprising as the Linux documentation says this field is for backward compatibility.
To verify this is the case in your instance you can use a slightly modified version of the sample program in this document, add this code after the first printf()
call:
printf("RUNNING: %s", (ifa->ifa_flags & IFF_RUNNING) ? "TRUE" : "FALSE");
Why isn't docker setting IFF_RUNNING
?
Setting interface flags is a low-level operation that docker does not handle itself. Docker's libnetwork delegates to the netlink library here, but netlink only sets IFF_UP
.
How can it be fixed?
The relevant moving parts to this issue are open source!
netlink was changed to expose IFF_RUNNING
for reading - it might be possible to enable libnetwork (and thus docker) to set that flag via a further change to netlink.
Alternately libuv might be extended following a Github issue on the subject. Such a new API could eventually be used in node.js and yarn that would list interfaces regardless of assigned IP addresses and IFF_RUNNING
state.