Great article, the example makes the point really clear.
It probably applies just as well to other languages by the way.
Two small notes after completing my read:
1. You're using `npm prune --omit=dev` after the build. It's probably fast enough, but I'm wondering if it wouldn't be worth it to install the dependencies in two steps: first `dependencies` in a first image, then in a second image, copy those and rerun `npm install` to also install the `devDependencies`.
You could then copy in the final image:
- The production dependencies from the `deps` image
- The built code from the `build` image
2. Also, it's probably a detail, but you're copying the entire app folder in the final image, maybe you could save some extra bytes by only copying the built artifacts (e.g. `dist/` in most setups).