Building efficient Node.js Docker image(specfy.io)
specfy.io
Building efficient Node.js Docker image
https://www.specfy.io/blog/1-efficient-dockerfile-nodejs-in-7-steps
8 comments
I don't fully understand the `RUN true \ && blah' bit?
Wouldn't that mean the RUN always succeeds?
Wouldn't that mean the RUN always succeeds?
Ah yes I didn't explain this part, it's just an habit.
It allows to modify the chained scripts without loosing the Git history, see this best practice guide https://github.com/projectatomic/container-best-practices/bl...
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:
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).Thanks.
1. That's interesting, I actually never thought about that. It could work in practice and could even be parallelised! It would just download some, or most, packages twice. I'll test that, thanks.
2. Indeed, it's easier when building a small repo but with a monorepos you need to be careful about copying the /dist at the right place + the package.json to not break runtime import. I think once again it's balance between what would be perfect and what we can live with.
1. That's interesting, I actually never thought about that. It could work in practice and could even be parallelised! It would just download some, or most, packages twice. I'll test that, thanks.
2. Indeed, it's easier when building a small repo but with a monorepos you need to be careful about copying the /dist at the right place + the package.json to not break runtime import. I think once again it's balance between what would be perfect and what we can live with.
This is some great advice, manage to reduce my deploy & build time by half, but most importantly, understand better what I'm doing. As a Docker casual user, most resources out there never take the time to break it down like that. I remember reading about using the same Docker image for local dev too, so you're ISO in both environments, but it requires some more steps to watch for changes. Any plans to write an article about that?
Thanks for the feedback,
I actually don't use Docker images locally (except for services), I never found it particularly easy to do especially with hot-reload, node_modules, etc.
I wish in 2023 we had the tools to have a unified local-prod environment but seems like it's not for today
I wish in 2023 we had the tools to have a unified local-prod environment but seems like it's not for today
I'm curious though, why do you need to install `devDependencies` and other crap?