Node: Windows Container: fs.realpathSync() is broken on shared volumes

Created on 2 Oct 2016  ·  68Comments  ·  Source: nodejs/node

  • Version: 4.6.1, 6.9.1, 7.0.0
  • Platform: Windows 10 1607 or Windows Server 2016 with Docker + Windows Containers
  • Subsystem: fs

The function fs.realpathSync() and/or pathModule._makeLong() is broken using it on shared Docker volumes mapped from host into a Windows Container. It seems to interpret the junction point incorrectly which is an UNC path and interprets it as c:\ContainerMappedDirectories.

Steps to reproduce

You need Windows 10 Anniversary update with Containers feature and Docker installed. Or an Windows Server 2016 with Containers feature and Docker installed, eg. an Azure VM.

Create a test directory with a minimal Dockerfile to just put node.exe into a Windows container.

PS C:\> mkdir test
PS C:\> cd test
PS C:\test> notepad Dockerfile.

This is the content of the Dockerfile

FROM microsoft/nanoserver

ARG NODE_VERSION=4.6.1

RUN powershell -Command \
    Invoke-WebRequest https://nodejs.org/dist/v$env:NODE_VERSION/win-x64/node.exe \
      -OutFile node.exe -UseBasicParsing

CMD [ "node.exe" ]

Now build a Docker image eg. for Node.js 4.6.1 using a build argument:

PS C:\test> docker build -t nodeexe:4.6.1 --build-arg NODE_VERSION=4.6.1 .

We can check that the binary works inside the Windows container by showing the version

PS C:\test> docker run nodeexe:4.6.1 node --version
v4.6.1

Now check that fs.realpathSync() works with an existing directory inside the container.

PS C:\test> docker run nodeexe:4.6.1 node -p "const fs=require('fs'); fs.realpathSync('c:/windows')"
c:\windows

OK. Now we mount the current directory as shared volume into the container and have a look at it with the dir command:

PS C:\test> docker run -v "$(pwd):C:\test" nodeexe:4.6.1 cmd /c dir c:\
 Volume in drive C has no label.
 Volume Serial Number is B097-15C5

 Directory of c:\

10/09/2016  10:57 PM             1,894 License.txt
11/04/2016  12:50 PM        14,259,744 node.exe
07/16/2016  05:20 AM    <DIR>          Program Files
07/16/2016  05:09 AM    <DIR>          Program Files (x86)
11/04/2016  01:43 PM    <SYMLINKD>     test [\\?\ContainerMappedDirectories\6C4D3D41-7E32-4992-BC03-44E1FAC23C0B]
10/09/2016  10:58 PM    <DIR>          Users
11/04/2016  12:50 PM    <DIR>          Windows
               2 File(s)     14,261,638 bytes
               5 Dir(s)  21,210,304,512 bytes free

OK, the directory C:\test is there, but you can see that it is a symlink to an UNC path. Let's check that this directory is accessible.

PS C:\test> docker run -v "$(pwd):C:\test" nodeexe:4.6.1 cmd /c dir c:\test
 Volume in drive C has no label.
 Volume Serial Number is B097-15C5

 Directory of c:\test

11/04/2016  01:44 PM    <DIR>          .
11/04/2016  01:44 PM    <DIR>          ..
11/04/2016  01:46 PM               231 Dockerfile
               1 File(s)            231 bytes
               2 Dir(s)  21,837,713,408 bytes free

OK, we can see the Dockerfile from the host. So let's now check fs.realpathSync with that directory.

PS C:\test> docker run -v "$(pwd):C:\test" nodeexe:4.6.1 node -p "const fs=require('fs'); fs.realpathSync('c:/test')"
fs.js:839
  return binding.lstat(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, lstat 'c:\ContainerMappedDirectories'
    at Error (native)
    at Object.fs.lstatSync (fs.js:839:18)
    at Object.realpathSync (fs.js:1439:21)
    at [eval]:1:28
    at Object.exports.runInThisContext (vm.js:54:17)
    at Object.<anonymous> ([eval]-wrapper:6:22)
    at Module._compile (module.js:409:26)
    at node.js:579:27
    at nextTickCallbackWith0Args (node.js:420:9)
    at process._tickCallback (node.js:349:13)

Boom! As you can see the UNC path is misinterpreted as c:\ContainerMappedDirectories and then of course this directory does not exist inside the Windows container.

This error breaks eg. using npm install on such a shared volume or even running simple Node.js code from it.

Let's create a small hello.js, map the current folder into a container and try to run it.

PS C:\test> "console.log('hello');" | Out-File hello.js -Encoding Ascii
PS C:\test> docker run -v "$(pwd):C:\test" nodeexe:4.6.1 node c:\test\hello.js
fs.js:839
  return binding.lstat(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, lstat 'c:\ContainerMappedDirectories'
    at Error (native)
    at Object.fs.lstatSync (fs.js:839:18)
    at Object.realpathSync (fs.js:1439:21)
    at toRealPath (module.js:112:13)
    at Function.Module._findPath (module.js:151:20)
    at Function.Module._resolveFilename (module.js:323:25)
    at Function.Module._load (module.js:276:25)
    at Function.Module.runMain (module.js:441:10)
    at startup (node.js:139:18)
    at node.js:974:3

When we copy the file from the shared volume into a local directory of the Windows container Node.exe is able to run it:

PS C:\test> docker run -v "$(pwd):C:\test" nodeexe:4.6.1 cmd "/c copy c:\test\hello.js . & node hello.js"
        1 file(s) copied.
hello

Another problem of this bug is that running npm install also does not work in a shared volume.

fs windows

Most helpful comment

@dealdiane At the moment you can use the following workaround using a mapped drive in the container.

Let's say your code is in C:\code then mapping that to a drive, eg. G: and then changing working to that drive works.

Add these lines until Node.js itself has a fix for the realPath problem in folders mounted into Windows containers.

VOLUME C:/code
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices' -Name 'G:' -Value '\??\C:\code' -Type String
WORKDIR 'G:\\'

All 68 comments

Does node --preserve-symlinks c:\nodejs\node_modules\npm\bin\npm-cli.js install work?

No, still the same. Can't see the --preserve-symlink in the argv output:

C:\code>node --preserve-symlinks c:\nodejs\node_modules\npm\bin\npm-cli.js install
npm info it worked if it ends with ok
npm info using [email protected]
npm info using [email protected]
npm ERR! Windows_NT 10.0.14393
npm ERR! argv "C:\\nodejs\\node.exe" "c:\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install"
npm ERR! node v6.7.0
npm ERR! npm  v3.10.3
npm ERR! path C:\ContainerMappedDirectories
npm ERR! code ENOENT
npm ERR! errno -4058
npm ERR! syscall lstat

npm ERR! enoent ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
npm ERR! enoent ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
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:\code\npm-debug.log

C:\code>type npm-debug.log
0 info it worked if it ends with ok
1 verbose cli [ 'C:\\nodejs\\node.exe',
1 verbose cli   'c:\\nodejs\\node_modules\\npm\\bin\\npm-cli.js',
1 verbose cli   'install' ]
2 info using [email protected]
3 info using [email protected]
4 silly loadCurrentTree Starting
5 silly install loadCurrentTree
6 silly install readLocalPackageData
7 silly rollbackFailedOptional Starting
8 silly rollbackFailedOptional Finishing
9 silly runTopLevelLifecycles Starting
10 silly runTopLevelLifecycles Finishing
11 silly install printInstalled
12 verbose stack Error: ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
12 verbose stack     at Error (native)
13 verbose cwd C:\code
14 error Windows_NT 10.0.14393
15 error argv "C:\\nodejs\\node.exe" "c:\\nodejs\\node_modules\\npm\\bin\\npm-cli.js" "install"
16 error node v6.7.0
17 error npm  v3.10.3
18 error path C:\ContainerMappedDirectories
19 error code ENOENT
20 error errno -4058
21 error syscall lstat
22 error enoent ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
23 error enoent ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
23 error enoent This is most likely not a problem with npm itself
23 error enoent and is related to npm not being able to find a file.
24 verbose exit [ -4058, true ]

It seems that node can't find/load js files in the volume mount point.

C:\code>type test.js
console.log('hello');

C:\code>node
> process.cwd()
'C:\\code'
>
(To exit, press ^C again or type .exit)
>

C:\code>node test.js
fs.js:982
  return binding.lstat(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
    at Error (native)
    at Object.fs.lstatSync (fs.js:982:18)
    at Object.realpathSync (fs.js:1647:19)
    at Function.Module._findPath (module.js:167:25)
    at Function.Module._resolveFilename (module.js:453:25)
    at Function.Module._load (module.js:403:25)
    at Module.runMain (module.js:590:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3

C:\code>node c:\code\test.js
fs.js:982
  return binding.lstat(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, lstat 'c:\ContainerMappedDirectories'
    at Error (native)
    at Object.fs.lstatSync (fs.js:982:18)
    at Object.realpathSync (fs.js:1647:19)
    at Function.Module._findPath (module.js:167:25)
    at Function.Module._resolveFilename (module.js:453:25)
    at Function.Module._load (module.js:403:25)
    at Module.runMain (module.js:590:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3

C:\code>node --preserve-symlinks test.js
fs.js:982
  return binding.lstat(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
    at Error (native)
    at Object.fs.lstatSync (fs.js:982:18)
    at Object.realpathSync (fs.js:1647:19)
    at Function.Module._findPath (module.js:167:25)
    at Function.Module._resolveFilename (module.js:453:25)
    at Function.Module._load (module.js:403:25)
    at Module.runMain (module.js:590:10)
    at run (bootstrap_node.js:394:7)
    at startup (bootstrap_node.js:149:9)
    at bootstrap_node.js:509:3

Just to clarify, if someone else tries this and wants a temporary solution. This only occurs with Node.js 6.x and works fine with Node.js 4.6.0

docker run -it --rm --name my-app -v "${pwd}:C:\App" -w "C:\App" -p 3000:3000 -p 9000:9000 stefanscherer/node-windows:4.6.0 powershell

This also affects opening files, eg. TLS certs mapped into a container through a volume. How can we proceed getting this fixed in LTS version of Node.js 6?

How sure are you it's a node issue and not a docker-on-windows issue? Does the same node binary work outside of the container?

@bnoordhuis I'm sure this is a Node.js problem. I've stripped down the problem as in #7044 to fs.realpathSync()

An internal directory works:

PS C:\> docker run -v "$(pwd):c:\code" stefanscherer/node-windows:7 node -p "fs.realpathSync('c:\windows')"
c:\windows

But a volume directory throws an exception:

PS C:\> docker run -v "$(pwd):c:\code" stefanscherer/node-windows:7 node -p "fs.realpathSync('c:\code')"
fs.js:893
  return binding.lstat(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, lstat 'c:\ContainerMappedDirectories'
    at Object.fs.lstatSync (fs.js:893:18)
    at Object.realpathSync (fs.js:1527:21)
    at [eval]:1:4
    at ContextifyScript.Script.runInThisContext (vm.js:25:33)
    at Object.exports.runInThisContext (vm.js:77:17)
    at Object.<anonymous> ([eval]-wrapper:6:22)
    at Module._compile (module.js:573:32)
    at bootstrap_node.js:345:29
    at _combinedTickCallback (internal/process/next_tick.js:67:7)
    at process._tickCallback (internal/process/next_tick.js:98:9)

Tested with both Node.js 6.9.1 and 7.0.0.

cc @nodejs/platform-windows @nodejs/docker

If this is really is a Node.js issue, can you edit the issue title and description with a purely Windows + Node.js test case? (without references to third-party tools)

@seishun Updated both title and description with a walkthrough with only Win10+Docker

If you want a better Dockerfile with both node.exe + npm installed, have a look at the proposal in https://github.com/nodejs/docker-node/pull/223 or in the meantime use one of my docker images at https://hub.docker.com/r/stefanscherer/node-windows/

At the moment only this issue with the shared volume is a big difference to the node Linux container where you can work with shared folders from an editor/IDE with live coding from your host.

$ docker run -v $(pwd):/test node:4.6.1 node -p "const fs=require('fs'); fs.realpathSync('/test')"
/test

$ echo "console.log('hello');" >hello.js

$ docker run -v $(pwd):/test node:4.6.1 node /test/hello.js
hello

Just sent https://github.com/nodejs/node/pull/9475 as a proposal to fix this issue.

Here is a repro of what I think is the same issue, without docker.

Windows 7 computer 1 (hostname REMOTE1):

>mkdir C:\temp\localdir
>mkdir C:\temp\mountpoint
>net share mountpoint=C:\temp\mountpoint
mountpoint was shared successfully.

>mklink /J C:\temp\mountpoint\junc c:\temp\localdir
Junction created for C:\temp\mountpoint\junc <<===>> c:\temp\localdir

Windows 10 computer 2:

>net use X: \\REMOTE1\mountpoint
The command completed successfully.

>net use X:
Local name        X:
Remote name       \\REMOTE1\mountpoint

>dir X:\ /A:L

11/15/2016  09:43 PM    <JUNCTION>     junc [c:\temp\localdir]

>node --version
v6.9.1

>node -p "fs.realpathSync('X:\\junc')"
fs.js:982
  return binding.lstat(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, lstat 'c:\temp\localdir'
    at Error (native)
    at Object.fs.lstatSync (fs.js:982:18)
    at Object.realpathSync (fs.js:1662:21)
    at [eval]:1:4
    at ContextifyScript.Script.runInThisContext (vm.js:25:33)
    at Object.exports.runInThisContext (vm.js:77:17)
    at Object.<anonymous> ([eval]-wrapper:6:22)
    at Module._compile (module.js:570:32)
    at bootstrap_node.js:357:29
    at _combinedTickCallback (internal/process/next_tick.js:67:7)

@yoweiner Junctions can only link across local volumes, and not network volumes. see here

@phestermcs In my example, the junction is all between local volumes on REMOTE1. It works; try it out yourself.

@yoweiner My mistake. It misread thinking you were creating a junction from computer2 to REMOTE1, as opposed to accessing a junction on REMOTE1 from computer2.

Is there a any progress on this? It's badly needed to work with docker compose and windows containers.

Well, I at least started with this Dockerfile to setup a build environment in a Windows container.

FROM microsoft/windowsservercore

SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]

ENV chocolateyUseWindowsCompression false

RUN iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'));

RUN choco install -y nodejs -version 7.3.0
RUN choco install -y git -params "/GitAndUnixToolsOnPath"
RUN npm install --global --production windows-build-tools

RUN git clone https://github.com/nodejs/node.git
RUN cd node ; git pull ; \
    $env:PATH += ';C:\Users\ContainerAdministrator\.windows-build-tools\python27' ; \
    .\vcbuild.bat test nosign

With that I also compiled a node.exe with my rough PR. Next I want to try is to build libuv in it and run the tests. But some help with better knowledge about the code base would be helpful.
I can provide a Win2016 Docker VM on Azure for tests and debugging if that is the problem.

I did some more tests, but this time compiling and testing libuv. See https://github.com/StefanScherer/dockerfiles-windows/tree/master/nodejs-node-8897 for details.
TL/DR the libuv tests show errors in a Windows container when running on a host mounted volume.
So we have to look there.

Just found this comment https://go-review.googlesource.com/c/41834/ which seems to fix it in Golang.

Currently windows Stat uses combination of Lstat and Readlink to
walk symlinks until it reaches file or directory. Windows Readlink
is implemented via Windows DeviceIoControl(FSCTL_GET_REPARSE_POINT, ...)
call, but that call does not work on network shares or inside of
Docker container (see issues #18555 ad #19922 for details).

But Raymond Chen suggests different approach:
https://blogs.msdn.microsoft.com/oldnewthing/20100212-00/?p=14963/

  • he suggests to use Windows I/O manager to dereferences the
    symbolic link.

This appears to work for all normal symlinks, but also for network
shares and inside of Docker container.

I'm on node 4.6.0 and getting the same problem with gulp. Every time I run gulp -v, it only returns the cli version. No gulp version. All the gulp files are in the file system (./node_modules/gulp). If I force gulp to run, I get this exception:

fs.js:839
  return binding.lstat(pathModule._makeLong(path));
                 ^

Error: ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
    at Error (native)
    at Object.fs.lstatSync (fs.js:839:18)
    at Object.realpathSync (fs.js:1439:21)
    at toRealPath (module.js:112:13)
    at Function.Module._findPath (module.js:151:20)
    at Function.Module._resolveFilename (module.js:323:25)
    at Function.Module._load (module.js:276:25)
    at Function.Module.runMain (module.js:441:10)
    at startup (node.js:139:18)
    at node.js:974:3

Any ideas?

Here's what I have installed (notice gulp -v)

PS C:\app\test> node -v
v4.6.0
PS C:\app\test> npm -v
2.15.9
PS C:\app\test> gulp -v
[20:41:59] CLI version 1.3.0
PS C:\app\test> ls node_modules

    Directory: C:\app\test\node_modules


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         5/2/2017   8:32 PM                .bin
d-----         5/2/2017   8:32 PM                gulp

@dealdiane At the moment you can use the following workaround using a mapped drive in the container.

Let's say your code is in C:\code then mapping that to a drive, eg. G: and then changing working to that drive works.

Add these lines until Node.js itself has a fix for the realPath problem in folders mounted into Windows containers.

VOLUME C:/code
RUN set-itemproperty -path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices' -Name 'G:' -Value '\??\C:\code' -Type String
WORKDIR 'G:\\'

@StefanScherer that works. Thanks!

I did saw your node-example branch before adding that comment but thought I'd stay clear of that because it involves hard-coding the mapped drive which isn't ideal. Anyway, looks like that's the only workaround for now so I'll have to live with that until fixed. Cheers. :)

@StefanScherer I am not sure this solution works if you are not doing it as part of the container image build. I used this command as well as just

New-PSDrive -Name "K" -PSProvider FileSystem -Root "\??\C:\source"

While the drive is mounted, NodeJS does not seem to start the app at all. The registry entry won't take effect immediately will it?

@vikalyan The New-PSDrive command doesn't seem to be enough as I cannot start any program from that drive.
The Set-ItemProperty trick has to be done in a Dockerfile with a separate RUN before you run a real Windows container with it.

@StefanScherer Makes sense. That's what I suspected. Will that work well when the bind mount is dynamic? That is, the bind-mount is done at the time of docker run instead of being part of the Docker file itself? Maybe doing the trick as a first step using docker exec before doing further docker exec commands in the container will work?

Ran into this issue as well the last two days. Basically exactly what @StefanScherer reports.

@vikalyan Yes, mounting a data volume using docker run --volume C:\code-on-host:C:\code works using the workaround (https://github.com/nodejs/node/issues/8897#issuecomment-298662512) @StefanScherer provided

@VolleMelk Thank you. Yes, we had to rebuild our container images and make some code changes to take advantage of @StefanScherer 's workaround. It works.

I just recalled, we did implement this a little bit different:

Dockerfile:

RUN mkdir C:/target
RUN Set-ItemProperty -Path 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\DOS Devices' -Name 'K:' -Value '\??\C:\target' -Type String

and we run with docker run --volume c:\my-host-dir:c:\target mycontainer

The main difference is that we are not using VOLUME, but just creating an empty directory for Set-ItemProperty to use. It feels 'cleaner', since there's no use for a data volume

Good news. Beginning with Windows Server Insider Preview 17046 (I've tested 17074 today) the mounted volumes just look like normal folders inside the Windows container.

So Node.js just works fine with it.

Even my more complex scenario VSCode on Mac with sourcecode -> mapped into a VMware shared folder into the Win 17074 VM -> mapped into a 17074 windowsservercore-insider container worked in conjunction with nodemon --inspect. This means I can develop native Windows apps on a Mac with the help of Windows containers (and the helper VM running Docker).

@StefanScherer Cool!

@jhowardmsft, @jstarks, @patricklang - Does this work with Hyper-V containers as well?

@vikalyan Yes, also Hyper-V containers 😍

# on my Mac
$ ls
Dockerfile         app.js             index.html         package-lock.json
README.md          docker-compose.yml node_modules       package.json

# in a Windows Hyper-V container
$ docker run -v C:$(pwd):C:/spec --isolation hyperv microsoft/nanoserver-insider cmd /c dir spec
 Volume in drive C has no label.
 Volume Serial Number is 2C0C-0420

 Directory of C:\spec

01/17/2018  03:40 PM    <DIR>          .
01/16/2018  11:09 PM    <DIR>          ..
10/05/2016  08:36 AM               482 index.html
01/17/2018  03:40 PM               301 Dockerfile
01/17/2018  01:58 PM    <DIR>          node_modules
01/17/2018  03:40 PM               744 README.md
01/17/2018  03:40 PM           106,091 package-lock.json
01/17/2018  03:40 PM               236 package.json
01/17/2018  03:40 PM               376 docker-compose.yml
01/17/2018  03:40 PM               808 app.js
               7 File(s)        119,790 bytes
               3 Dir(s)  127,956,414,464 bytes free

@StefanScherer - Very cool. This should unblock a lot of scenarios that were blocked for us.

@StefanScherer probably a dumb question but what do I need to run Windows Server Insider Preview >= 17074? Do I need to use that as my OS or can I just docker run it?

I've been docker running it but have been getting this error:
failed to register layer: re-exec error: exit status 1: output: ProcessUtilityVMImage C:\ProgramData\Docker\windowsfilte r\xxxx\UtilityVM: The system cannot find the path specified.

That's when I run it inside Server 2016. No bitlocker nor any AV running.

@dealdiane That‘s ‚normal‘, you can‘t run containers newer than the host kernel version.

To run insider containers you need a Server Insider.

You can register to the Windows Server Insider Preview program and download the VHD or ISO from https://www.microsoft.com/en-us/software-download/windowsinsiderpreviewserver

I have a Packer template to automate the creation of a Vagrant box file to have a complete Docker VM with the Insider base images installed.

@StefanScherer Thanks. That's what I was worried about.

This is for a build server. I was hoping that there's a way to use it without having to setup another build server. Based on your comment, I guess there isn't.

I'm currently stuck with something where even the mapped drive trick doesn't work.

I am not able to use the workaround @StefanScherer posted right now on windows 10. Could it be it's related to using the stefanscherer/node-windows container on windows 10 instead of server 1709?

I can do the set-itemproperty command in my dockerfile. I can start a container with no volumes and the working direct is G:\ and I can see files. If however I put an volume statement in the dockerfile before the set-itemproperty command as shown in the workaround, I get this error.

Error response from daemon: container 191662a7b37115c4cace466370f23540db542103eee1d6ea765bca78d2197f86 encountered an error during Start: failure in a Windows system call: The compute system exited unexpectedly. (0xc0370106).

similarly, if I leave the volume statements out of the dockerfile and specify them on the docker run command with -v I get the same error.

@panmanphil Could you try my suggestion?

My solution does not use a VOLUME, but en emptry directory

@VolleMelk yeah, an empty directory does the trick, no more error. thanks!

After searching hours with the exception , I got to know this is an existing issue.

I have a asp.net core api application running under a windows docker container. In my application I invoke node js using INodeService . It is working fine in local mode without docker and also working well in any cloud hosting without docker. But when I am running my application inside docker windows container, I am getting following exception in my InodeServices.InvokeAsync() method where I am giving the location of the js file and other parameters.

Microsoft.AspNetCore.NodeServices.HostingModels.NodeInvocationException: ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
Error: ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
at Object.patchedLStat [as lstat] (C:\Users\ContainerAdministratorAppData\Local\Temp\32zx2v0u.50k:155:27)
at Object.realpathSync (fs.js:1649:15)
at toRealPath (module.js:158:13)
at tryFile (module.js:154:22)
at tryExtensions (module.js:166:22)
at Function.Module._findPath (module.js:219:20)
at Function.Module._resolveFilename (module.js:536:25)
at Function.Module._load (module.js:468:25)
at Module.require (module.js:587:17)
at require (internal/module.js:11:18)
at Microsoft.AspNetCore.NodeServices.HostingModels.HttpNodeInstance.d__71.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance.d__131.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
at Microsoft.AspNetCore.NodeServices.NodeServicesImpl.d__101.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.NodeServices.NodeServicesImpl.d__101.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at WebApplication1.Implementation.AssetReportMgr.d__10.MoveNext() in C:\sourceTree\connected assets\253\careports\HON.SPS.SIOT.CA.REPORT.API\HON.SPS.SIOT.CA.REPORT.API\ImplementationAssetReportMgr.cs:line 143

Here is my invoking code and docker file details:

var report = await _nodeServices.InvokeAsync

the pdf.js file is under my project root directory.

dockerFile:

FROM microsoft/aspnetcore:2.0-nanoserver-sac2016 AS base

ENV NODE_VERSION 8.9.4
ENV NODE_DOWNLOAD_SHA 48946e99ac4484e071df25741d2300f3a656f476c5ff3f8116a4746c07ebe3b7

Retrieve node and git
https://nodejs.org/dist/v8.9.4/
ENV NODE_VERSION 8.9.4
ENV NODE_DOWNLOAD_SHA 48946e99ac4484e071df25741d2300f3a656f476c5ff3f8116a4746c07ebe3b7

RUN Invoke-WebRequest -UseBasicParsing https://nodejs.org/dist/v${env:NODE_VERSION}/node-v${env:NODE_VERSION}-win-x64.zip -outfile node.zip;
if ((Get-FileHash node.zip -Algorithm sha256).Hash -ne $env:NODE_DOWNLOAD_SHA) {
Write-Host 'NODEJS CHECKSUM VERIFICATION FAILED!';
exit 1;
};

Expand-Archive node.zip -DestinationPath nodejs-tmp;
Move-Item nodejs-tmp/node-v${env:NODE_VERSION}-win-x64 "${Env:ProgramFiles}/nodejs";
Remove-Item -Force node.zip;
Remove-Item -Force nodejs-tmp

RUN setx /M PATH $($Env:PATH + ';' + $Env:ProgramFiles + '/nodejs')

WORKDIR /app
EXPOSE 80

FROM microsoft/aspnetcore-build:2.0-nanoserver-sac2016 AS build
WORKDIR /src
COPY *.sln ./
COPY HON.SPS.SIOT.CA.REPORT.API/HON.SPS.SIOT.CA.REPORT.API.csproj HON.SPS.SIOT.CA.REPORT.API/
COPY HON.SPS.SIOT.CA.REPORT.Azure.Blob/HON.SPS.SIOT.CA.REPORT.Azure.Blob.csproj HON.SPS.SIOT.CA.REPORT.Azure.Blob/
RUN dotnet restore
COPY . .
WORKDIR /src/HON.SPS.SIOT.CA.REPORT.API
RUN dotnet build -c Release -o /app

FROM build AS publish
RUN dotnet publish -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
RUN npm install
ENTRYPOINT ["dotnet", "HON.SPS.SIOT.CA.REPORT.API.dll"]

Dockercompose File:

version: '3'

services:
hon.sps.siot.ca.report.api:
image: hon.sps.siot.ca.report.api
build:
context: .
dockerfile: HON.SPS.SIOT.CA.REPORT.APIDockerfile

Node Version: 8.9.4
Platform: Docker Windows Container

If will be great help if some one tell me how to provide the relative path for pdf.js because /pdf is not working here.

@arupbaroi: What command are you using to start the docker container?

@VolleMelk docker run -d -p 8080:80 --name myrunningapp newimage

I know this is not the issue being discussed here, but i wanted to point that although the latest windows version (Win10 April Update) and latests nano-insider builds solve this issue, i get stuck running npm or other node programs that use symbolic links on mounted volumes.

Looks like symbolic lynking is not supported on mounted volumes, even running mklink manually does not work, returning an Access Denied error, see:

https://github.com/docker/for-win/issues/1997

Symlinks don't work on mounted volumes for containers with 'hyper-v'
isolation, but they do work for containers with 'process' isolation.

On Fri, May 4, 2018 at 8:26 AM, Iñaki Elcoro notifications@github.com
wrote:

I know this is not the issue being discussed here, but i wanted to point
that although the latest windows version (Win10 April Update) and latests
nano-insider builds solve this issue, i get stuck running npm or other node
programas that use symbolic links on mounted volumes.

Looks like symbolic lynking is not supported on mounted volumes, even
running mklink manually does not work, returning an Access Denied error,
see:

docker/for-win#1997 https://github.com/docker/for-win/issues/1997


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/nodejs/node/issues/8897#issuecomment-386524057, or mute
the thread
https://github.com/notifications/unsubscribe-auth/ABV6Uo-PJMVnIWbC8lk1nAtqZYm55kLpks5tvAKigaJpZM4KMAbs
.

Good news, as @ielcoro mentioned. Mounted volumes work also with --isolation hyperv (the only available mode in Windows 10) with Windows 10 1803, the Windows Server 17623.1002 and upcoming Windows Server 1803 and next LTSC Windows Server 2019.

@jan11011977 That is dissapointing, one useful (maybe the most useful) use case for mounting volumes in Docker is for live editing during development and isolating development tools and dependency versions between projects, resulting in a clean host environment and making very easy to share the same development environment between team members.
And development is usually done in Windows 10 client operating system which does not support process isolation.

This affects tools like npm or git, and makes for us Docker unusable as development platform on Windows.
:-(

When Windows Server 2016, Version 1803 arrives in a few days/weeks we should have new base images instead of the latest insider images. Then it should work with these base images. Looking forward to this.

@StefanScherer Yes, the new base images are much better and will make Docker on Windows more approachable to a lot of people.

Still us will be blocked by the symlink error on hyperv isolation mode aka "the only Windows 10 mode for containers"

Hi,
thanks for your resolution tracks but --isolation hyperv did not solved the issue in my case.
So,... is there a way to be able to develop locally nodejs files and build thems in a nodejs container ?

I finaly followed this solution.
Problem with symlinks are now fixed but I now facing another issue. Access to drive G:\ seems to be forbiden :

webapp.cdn.build_1  | .\combine.ps1 : AuthorizationManager check failed.
webapp.cdn.build_1  | At line:1 char:34
webapp.cdn.build_1  | + $ErrorActionPreference = 'Stop'; .\combine.ps1
webapp.cdn.build_1  | +                                  ~~~~~~~~~~~~~
webapp.cdn.build_1  |     + CategoryInfo          : SecurityError: (:) [], ParentContainsErrorRecord
webapp.cdn.build_1  |    Exception
webapp.cdn.build_1  |     + FullyQualifiedErrorId : UnauthorizedAccess

Thanks

My mistake, problem was related to PS's Execution Policies. I switched from Unrestricted to Bypass and the issue disappeared.

Thank so much for your work and helping us.

I am getting below error

  • InnerException {Microsoft.AspNetCore.NodeServices.HostingModels.NodeInvocationException:
    Webpack dev middleware failed because of an error while loading 'aspnet-webpack'.
    Error was: Error: ENOENT: no such file or directory, lstat 'C:\ContainerMappedDirectories'
    at Object.realpathSync (fs.js:1430:7)
    at toRealPath (internal/modules/cjs/loader.js:202:13)
    at tryFile (internal/modules/cjs/loader.js:198:22)
    at tryPackage (internal/modules/cjs/loader.js:179:10)
    at Function.Module._findPath (internal/modules/cjs/loader.js:284:18)
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:578:25)
    at Function.Module._load (internal/modules/cjs/loader.js:507:25)
    at Module.require (internal/modules/cjs/loader.js:637:17)
    at require (internal/modules/cjs/helpers.js:20:18)
    at Object. (C:\Users\ContainerAdministratorAppData\Local\Temp\rzvqlxpj.bl4:83:19)
    Current directory is: C:\app

    at Microsoft.AspNetCore.NodeServices.HostingModels.HttpNodeInstance.d__71.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
    at Microsoft.AspNetCore.NodeServices.HostingModels.OutOfProcessNodeInstance.d__131.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()
    at Microsoft.AspNetCore.NodeServices.NodeServicesImpl.d__101.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.AspNetCore.NodeServices.NodeServicesImpl.<InvokeExportWithPossibleRetryAsync>d__101.MoveNext()} System.Exception {Microsoft.AspNetCore.NodeServices.HostingModels.NodeInvocationException}

Running into this issue using microsoft/dotnet:4.7.2-sdk trying to use NPM
Will try microsoft/dotnet-framework:4.7.2-sdk-20180814-windowsservercore-1803 and see if the problem still persists.

So after reading this article is appears -- https://docs.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility

It appears I can't use the version that's based off windowservercore-1803, while I could try it, it really wouldn't solve my problem to begin with.

@Francommit if it‘s hard to have a Windows Server 1803 semi-annual release watch out for the next long-term supported Windows Server 2019 which will be available soon.

Yeah unfortunately I'm going to have to wait for WS2019.

Given I'm building node-packages in my container as a workaround I've just robocopied everything from a mount-point to a directory in the container then copied the artifacts back to the mount point.

Not the most elegant solution or quickest but it proves my code will build for now!|

EDIT: Why robocopy and not xcopy you might ask? Try and run xcopy in a Windows Server 2016 based windowsservercore image and see what happens 👎

@StefanScherer I still have this issue with your latest nanoserver nodejs image, so I assume this is still not resolved. Do you have a new workaround? The powershell-trick is not working, I still have the error from your first post.

EDIT:
Got a brainwave, I decided to copy the mount to a folder inside the container before attempting to run. It's not ideal, technically takes double the size, but it works...

Dockerfile

FROM stefanscherer/node-windows:latest

RUN mkdir C:\app
RUN mkdir C:\app\mount
RUN mkdir C:\app\user

COPY startup.bat C:/app/startup.bat

CMD ["C:\app\startup.bat"]

startup.bat

copy C:\app\mount\* C:\app\user
cd C:\app\user
node app.js

Would very much still like an actual fix or workaround :S

EDIT EDIT: I'm an idiot, I didn't switch to the new volume... The workaround still works fine.

@LennardF1989 The problem isn't fixed with the Windows 2016 base images. We have seen progress and fixes in the 1803 images, but people have to run Windows Server Core version 1803 which is quite rare.

Now Windows Server 2019 / Windows 10 1809 Update is around the corner with two new Windows base images

mcr.microsoft.com/windows/servercore:ltsc2019
mcr.microsoft.com/windows/nanoserver:1809

And with these images bind mounting a folder into the container works fine in combination with Node.js.

Edit: I also just tried to run a Windows 2016 based Node image on a Windows Server 2019 in HyperV isolation mode, but the problem still exists. This is because the Windows 2016 base image brings its old Windows kernel where the bind mount isn't fixed for Node.js. So the best experience will be only with the new 1809/ltsc2019 base images running on the latest Windows OS.

I can confirm this is fixed in 1803 Core. Got it working today!

Still having this issue with Windows 10!
I've tried tfrijsewijk's solution, but get this error

/bin/sh: Set-ItemProperty: not found

Dockerfile

FROM node:alpine
#Create app directory
WORKDIR /usr/src/app
#Install nodemon for hot reloading
RUN npm install nodemon -g
#Install app dependencies
#A wildcard is used to ensure both package.json AND package-lock.json are copied
COPY package*.json ./
RUN npm install
#Bundle app source
COPY . .
EXPOSE 8080
CMD [ "nodemon", "-L", "server/server.js" ]

I'm trying to setup hot reloading with nodemon for a dev environment.
However using a volume like so:

docker build -t node-api .
docker run --rm -it -p 8080:8080 -v "${PWD}:/usr/src/app" node-api

outputs

[nodemon] 1.18.6
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node server/server.js`
internal/modules/cjs/loader.js:605
    throw err;
    ^

Error: Cannot find module 'express'
    at Function.Module._resolveFilename (internal/modules/cjs/loader.js:603:15)
    at Function.Module._load (internal/modules/cjs/loader.js:529:25)
    at Module.require (internal/modules/cjs/loader.js:658:17)
    at require (internal/modules/cjs/helpers.js:22:18)
    at Object.<anonymous> (/usr/src/app/server/server.js:1:79)
    at Module._compile (internal/modules/cjs/loader.js:722:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:733:10)
    at Module.load (internal/modules/cjs/loader.js:620:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:560:12)
    at Function.Module._load (internal/modules/cjs/loader.js:552:3)
[nodemon] app crashed - waiting for file changes before starting...

If I exclude the -v flag and docker run then it starts with no errors, but doesn't detect changes or restart on file saves.

Github repo for code

Thanks @bcowell for sharing your code. But FROM node:alpine is a Linux image, there is no PowerShell inside. That's why Set-ItemPropery does not work.

This issue is about the problem with the "V1" of Windows containers beginning with Windows Server 2016 and Windows 10.

The problem is solved beginning with Windows Server, version 1803 and Windows 10 1803 when you run the 1803 Windows images and Node.js inside. The Server 1803 isn't available for all users, but the Windows Server 2019 ("V2" of Windows containers :-) ) now is here. Embracing the new 1809 / ltsc2019 Windows images also solves this problem.

The issue remains in the ltsc2016 images, but I think we can close this issue if people use the newer images soon.

Thanks @StefanScherer you're right.

Some of us would love for this to work in a ltc2016 container! @StefanScherer I'm yet to test this with the recent update to the ltc2016 base layers, will give it a try later in the week and report back.

On a seim-unrelated note.

I made a Windows Server 1803 version of my process using a shared volume mount that did part of a npm command, it was SLOWER overall than me performing a robocopy to a folder from the volume mount than performing the build on the volume mount directly.

It appears to be an open issue on Docker for Windows community edition, just interesting to see it in practice.

Is this problem still present? node v7 b488b19eaf2b2e7a3ca5eccd2445e245847a5f76 (#3594) may have inadvently fixed it as a side effect, as uv_fs_realpath() on windows has always used the IO Manager magic since its introduction in https://github.com/libuv/libuv/commit/e76b8838e51f6e8f1944b6c6d50c3948ed764a0b.


Oh well, they decided the js readlink-and-stich-by-resolve version is superior. The native one is now fs.realpathSync.native().

path.resolve now recognizes UNC targets of the form \\foo\bar

path.resolve('nothere', '\\\\ContainerMappedDirectories\\6C4D3D41-7E32-4992-BC 03-44E1FAC23C0B')

However, this breaks:

D:\>mklink /D smbex \\?\notRealDevice\foo
D:\> dir /aL
2019/12/13  20:13    <SYMLINKD>     smbex [\\?\notRealDevice\foo]
fs.readlinkSync('D:\\smbex\\')
// '\\??\\notRealDevice\\foo'
path.resolve('notreal', fs.readlinkSync('D:\\smbex\\'))
// 'C:\\??\\notRealDevice\\foo'

readlink somehow converted the \\?\ local dosDevices prefix into the NT \??\ prefix without removing it. path.resolve did not see two slashes, so it treated it as a relative path even though this is a thing in NT speak.

This is still an issue in v14.0.0, can't use it in my GitLab CI pipeline...

Some details: I need node.exe to compile the .ts files in .js files as part of a ASP.NET MVC project.

I use the GitLab CI + Docker functionality to compile my project, but I have noticed that the .js files were missing. By digging in the issue I have discovered that I get the C:\ContainerMappedDirectories bug.

I have tried some versions: 14.0.0, 10.19.0, 4.6.0 and 4.5.0, but no one will work with Docker with a mapped directory.

@schifazl I was also having trouble with NodeJS in my mcr.microsoft.com/dotnet/framework/sdk:4.8-windowsservercore-ltsc2016 based image, however, this article's solution solved my problem with subst: https://blog.sixeyed.com/docker-volumes-on-windows-the-case-of-the-g-drive/

I'm going to close this issue.
The problem was fixed with Windows Server 2019 and it's highly recommended to use Windows Containers with at least Windows Server 2019 or newer to have all benefits of the underlying improvements.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

feross picture feross  ·  208Comments

nicolo-ribaudo picture nicolo-ribaudo  ·  147Comments

addaleax picture addaleax  ·  146Comments

mikeal picture mikeal  ·  197Comments

benjamingr picture benjamingr  ·  135Comments