Npm link not working with CMD in Dockerfile? docker beta on Mac OS

My Dockerfile takes care of setting up a simple CLI node app. If I add a ‘CMD npm link’ instruction at the end, I expect it to create a symlink that I can then use to invoke my .js entrypoint.

When I build the image, it all appears to go well, including running the aforementioned CMD. Yet, when I create a container from the built image by running it, I can’t invoke the CLI/program using the symlink. I have to manually run npm link in the shell to get it to work, even through npm link should have run as part of the image creation (?).

This happens with docker beta for Mac 1.11.1.

Am I missing something? Thank you!

Same problem on windows. I’m trying to install npm modules on some web project

I can’t say I fully understand osxfs - and I also don’t use npm-link for cli apps unless I’m testing them. This what I could find in the documentation

Mounting/unmounting OS X volumes that are also bind mounted into containers may result in unexpected behavior in those containers. Unmount events are not supported. Mount export support is planned but is still under development.

Symlinks

Symlinks are shared unmodified. This may cause issues when symlinks contain paths that rely on the default case-insensitivity of the default OS X file system, HFS+.

File types

Symlinks, hardlinks, socket files, named pipes, regular files, and directories are supported. Socket files and named pipes only transmit between containers and between OS X processes – no transmission across the hypervisor is supported,

Honestly I’ve never thought about running CMD npm link in a Dockerfile, but there’s other ways to accomplish the same goal. For example, I use the glances (system monitor) with docker, so I just wrote an alias glances=docker run ... in my dot files. I’ve also worked with and contributed to a a few cli apps using node/npm, so I’m familiar with 3 or 4 different ways to do it. I can build a node app to run docker via the cli, but I’ve never attempted using a docker container for the base of an npm cli app

Hi Ramon,

CMD sets the command to run if you docker run the image. CMD is not run and its effects are not available in the built image. CMD only supplies the default command to use when no other command is specified on the command line.

For example, if you build this Dockerfile:

FROM alpine

CMD touch TEST_FILE

with docker build -t test-image . and then run it with docker run --rm -it test-image ls, you will observe:

bin      etc      lib      media    proc     run      sys      usr
dev      home     linuxrc  mnt      root     sbin     tmp      var

Instead of CMD, you should use RUN if you want the effects of the command to take place during the build. Please see https://docs.docker.com/engine/reference/builder/ for more information.

Hope this helps,

David

Thank you! This is useful. I have not found a way to address this in a practical way just yet, but it certainly made me think about the implications (and feasibility) of using symlinks in a container.

Thank you very much David. This did indeed solve it for me. I obviously did not have a solid understanding of the differences between CMD and RUN. I think doing a npm link may not be a sensible thing to do, but for the time being, replacing a CMD with a RUN at least does what I need it do. Again, thank you!

Interesting… thanks for the clarifying RUN vs CMD - if npm link works - that might be a really simple way to link cli apps globally… I’ve been working with this library recently https://github.com/matthieudelaro/nut attempted to make a brew for it so it was easier to install. But I couldn’t figure out how to mix docker / brew, and the binary itself needed signed permissions - so I just used node to link it in the path npm install -g nut-bin - and it worked, but using npm link is intriguing because the nut is built with docker. Thanks for raising this issue.

Has anyone been able to figure out how to use npm link with Docker? In my case I would like to run a server in a docker container than is npm-linked to a local module. This generates a symlink like this:

node_modules/my_library → …/…/…/…/…/opt/nodes/6.2.1/lib/node_modules/my_library

which obviously won’t resolve in Docker.

I’m a bit stumped on coming up with a workaround, short of copying the entire library into the container’s path.

1 Like

At GoSquared they use volumes for each symlinked module in docker-compose. But this will be problematic for nested npm links and it is complicated.

I think the only solution is to mount your npm linked root folders (e.g. ~/dev) and hook the Node require resolver and redirect requests for modules to the mounted dir path.

I’ve implemented the redirection already because I wanted to dedupe npm linked modules for performance reasons which is a problem with npm2 and npm3. I am happy because it was a lot of work, and now I find this perfect use case for it.

See here: https://github.com/live-js/live-perf

Actually, there is an easy replacement of npm link. Use yalc. See my answer on stackoverflow.