問題
docker build
の中で npm install
すると、下記のようなエラーが出て ret val != 0 となりコケる。
npm ERR! EXDEV: cross-device link not permitted, rename '/usr/local/lib/node_modules/npm' -> '/usr/local/lib/node_modules/.npm.DELETE'
上記は npm
の例ですが、各所で発生し、阿鼻叫喚になっていた。
冒頭の github issues の長さでお察し
解決方法
Dockerfile
内に下記を記載
RUN cd $(npm root -g)/npm \
&& npm install fs-extra \
&& sed -i -e s/graceful-fs/fs-extra/ -e s/fs\.rename/fs.move/ ./lib/utils/rename.js
原因
ここまでわかっている模様
- (docker の)aufs に固有の問題
- aufs では多くの子レイヤがあるため、ディレクトリの rename が難しい(すべての子レイヤから探しだして、変更しないといけない。 inode の rename も含む)。この操作はコスト高で、 aufs は実行することを(たまに)拒否して、 EXDEV を返す。
- EXDEV での copy/unlink の実行は、まあ、なんとかなる。
- fs.extra と fs-extra は EXDEV での copy にフォールバックする。このため、不幸にも上記に引っかかる。
- copy/unlink にフォールバックする代わりに、 mkdir/rename を再帰的に実行することができる。この処理は atomic ではなくなってしまう。これで十分かな?奇妙な npm の競合状況に出くわしたことがないので確かではないですが・・・
おしまい
上記の通り、 atomic ではなくなってしまいますが、ほとんどのケースではうまくいくだろうとのことです。