Blubber attempts to optimize the resulting image layers of Node projects, and avoids the need to rebuild all layers, by using multiple steps for `npm install and copying of source files.
- Copy package.json to a temp directory
- Execute npm install in the temp directory
- Copy source files into app directory
- Move node_modules from temp to app directory
However, the move is resulting in a substantial additional layer.
IMAGE CREATED CREATED BY SIZE COMMENT 970771081d8d 19 hours ago /bin/sh -c #(nop) ENTRYPOINT ["npm" "start"] 0B 36f35b6b9662 19 hours ago /bin/sh -c mv /tmp/node-deps/node_modules ./ 150MB (<- wtf.) 1e096ee48098 19 hours ago /bin/sh -c #(nop) COPY dir:af714faee7f3cee... 419kB ac52dc20b7c8 20 hours ago /bin/sh -c cd /tmp/node-deps/ && npm install 200MB 7957b9b068dd 20 hours ago /bin/sh -c #(nop) COPY file:16ecab327f6508... 1.84kB
I wasn't clear to me at first why a move would result in an fs layer of any substance—since moving a file or directory hierarchy is essentially just changing the inode/name entry—but it may be a current limitation of overlayfs and the changes to support more efficient directory tree moves are backwards incompatible. Translation: This is not a reliable optimization as it's currently implemented and won't be for some time.
We should either figure out an alternative way to implement this optimization or get rid of it.
One alternative might be to use a bind mount of node_modules from its original build location to inside the app's directory. It seems convoluted at face value but the solution might have the happy side effect of solving an issue in development where a VOLUME is desired for the app directory over the copying of source files—the bind mount can happen over the shared volume just as it can over the copied directory, hence a higher degree of parity between a dev and staging/prod image.