Open rubennorte opened 7 years ago
I agree but we use the official distribution which include npm. The core node doesn't have a version of node without npm, as far as I am aware.
Yeah, that would be great. I think if we do that we'd have to somehow build node without npm. Or convince the build group that we need that as another option.
It might make sense to do more of a clean break and create a new node-minimal image that better fits this use case.
I just saw that https://github.com/mhart/alpine-node provides that kind of image (with the Node binary only). Maybe you can get some ideas from there.
Yeah they build node with --without-npm
. We could probably do the same thing but the build and release would take longer.
Well, theoretically we could just rm -rf /usr/local/lib/node_modules/npm/ /usr/local/bin/npm
after extracting the Node tarball. I don't see much value in pursuing that though.
@pesho I do see the value. You'd be reducing the image size by 40% (22MB from 54MB belong to npm and yarn in the Node 6.10 image). In some environments that's important.
@rubennorte I spoke too soon before. Indeed, there is value in having a minimal image without package managers for production.
I agree, a minimal image without npm nor yarn would be nice for production use cases. This only makes sens for the alpine
variant (since the ones based on Debian are so huge anyways), and I think it can be solved as easy as rm -rf /path/to/npm
.
Nice issue number #404 😜
I had something in mind when multi-stage builds got introduced to make the smallest possible Node image:
# Dockerfile-alpine-minimal.template
FROM node:0.0.0-alpine AS builder
FROM alpine:0.0
COPY --from=builder /usr/local/bin/node /usr/local/bin/
COPY --from=builder /usr/lib/ /usr/lib/
CMD [ "node" ]
I'm not sure if it's OK to use multi-stage builds in docker-node yet, but I like the idea of using the previously built alpine
image and multi-stage builds to make the minimal version (instead of having to compile Node again).
The core node doesn't have a version of node without npm, as far as I am aware.
They used to have a statically-linked node
binary that you could download just by itself with no other stuff. It looks like they only still have that for Windows (eg. https://nodejs.org/dist/v6.11.1/win-x64/node.exe), the only Linux downloads I could find still contain npm. Having said that, you could just use their Linux tarball and delete the npm directory and executable.
Is this worth revisiting as a variant? Doing rm -rf /usr/local/lib/node_modules/npm/ /usr/local/bin/npm
is easy enough and it would be useful with multi-stage builds. And what would we call the variant?
And what would we call the variant?
A few suggestions: production
, micro
, tiny
, nano
I like the idea in general.
The complexity this would bring kind of scares me.
@valeriangalliat I like your approach but in the current setup, that would mean building the alpine images twice because different images are not aware of each other.
I think we should only do this for Debian, something like:
FROM debian:jessie-slim
RUN groupadd --gid 1000 node \
&& useradd --uid 1000 --gid node --shell /bin/bash --create-home node
# gpg keys listed at https://github.com/nodejs/node#release-team
RUN set -ex \
&& for key in \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
56730D5401028683275BD23C23EFEFE93C4CFFFE \
77984A986EBC2AA786BC0F66B01FBB92821C587A \
; do \
gpg --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done
ENV NODE_VERSION 10.2.0
RUN buildDeps='ca-certificates curl xz-utils' \
&& ARCH= && dpkgArch="$(dpkg --print-architecture)" \
&& case "${dpkgArch##*-}" in \
amd64) ARCH='x64';; \
ppc64el) ARCH='ppc64le';; \
s390x) ARCH='s390x';; \
arm64) ARCH='arm64';; \
armhf) ARCH='armv7l';; \
i386) ARCH='x86';; \
*) echo "unsupported architecture"; exit 1 ;; \
esac \
&& set -x \
&& apt-get update && apt-get install -y $buildDeps --no-install-recommends \
&& rm -rf /var/lib/apt/lists/* \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH.tar.xz" \
&& curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/SHASUMS256.txt.asc" \
&& gpg --batch --decrypt --output SHASUMS256.txt SHASUMS256.txt.asc \
&& grep " node-v$NODE_VERSION-linux-$ARCH.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
&& tar -xJf "node-v$NODE_VERSION-linux-$ARCH.tar.xz" -C /usr/local --strip-components=1 --no-same-owner \
&& rm -rf /usr/local/lib/node_modules/ \
&& rm -rf /usr/local/bin/npm \
&& rm -rf /usr/local/bin/npx \
&& rm "node-v$NODE_VERSION-linux-$ARCH.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt \
&& apt-get purge -y --auto-remove $buildDeps \
&& ln -s /usr/local/bin/node /usr/local/bin/nodejs
CMD [ "node" ]
The above image is about 125MB
(edit: updated to delete /usr/local/lib/node_modules/
)
Also, for a variant name, I kind of like node:core
, node:10-core
etc.
How much space is saved on Debian?
You can delete the entire node_modules directory, not just the npm directory. The only other modules that ship with Node.js are npm's dependencies.
Instead of installing Node.js and npm and then deleting npm, could you just avoid installing npm in the first place? I think the Node.js site has a statically compiled version of Node.js with no npm (just the Node.js executable), and I believe Debian packages Node.js and npm in two separate packages.
Sent from my phone.
On Fri, May 25, 2018, 8:02 AM Christopher Horrell notifications@github.com wrote:
Also, for a variant name, I kind of like node:core, node:10-core
— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/nodejs/docker-node/issues/404#issuecomment-392086064, or mute the thread https://github.com/notifications/unsubscribe-auth/AAFnHTq78qfmFrNjk4vx1TZyRxfj507kks5t2Bz4gaJpZM4Ncdol .
We're looking at a ~60MB difference using the rm -r
approach:
[chorrell:~/GitHub/docker-node-main] master(+6/-6)* ± docker images | grep 10.2.0-slim
node 10.2.0-slim c164ad185a38 20 hours ago 184MB
vs
[chorrell:~/GitHub/docker-node-main] master(+6/-6)* ± docker images | grep 10.2.0-core
node 10.2.0-core 68519b454a55 3 minutes ago 125MB
Note that I don't think the statically compiled versions are available, or at least I cannot find them at https://nodejs.org/dist/
for v10. And we would want versions for each of the architectures we support too.
love this idea, @chorrell how soon this can be released?
Seems like this may be worth putting on the TSC agenda to see how the core project can help out with this 🤔
@chorrell is currently working on it (see references). But if you think it's worth it feel free :)
@SimenB definitely think it's worth it – the fact that y'all are getting the work done is super valuable if Node.js core were to do the same 💚
@bnb Feel free to put this on the TSC agenda by adding the label to it and/or mentioning it in the current TSC meeting issue (https://github.com/nodejs/TSC/issues/565) – ideally with a short summary of the question you’d like to see answered, which decision you’d like to see made, or what you’d like to raise awareness about. (It’s not super-clear from this thread for me, so that’s why I’m mentioning it :slightly_smiling_face:).
Would really like to see this as well. It's actually far-preferred to not involve global dependencies at all for your production apps.
A potentially related issue: https://github.com/nodejs/Release/issues/341. The discussion is related to having different versions, some without extras.
Discussed in last TSC meeting, but this should not block this issue and ongoing discussion about whether we should do something on the release side will continue in: https://github.com/nodejs/Release/issues/341. Removing from TSC agenda.
FWIW, I would like to add a vote in favor of this work, including providing an alpine-based image without npm.
My needs are:
I would really like to see an official image, since it's not obvious to someone like myself which things are necessary vs what can safely be deleted when pairing down a larger image, or which specific combination of flags need to be set to build it from source without npm, while still allowing native modules to work.
If one of the main obstacles is still the naming convention for the release, it would be nice if there could be a simple vote with github reactions by the maintainers so we could be unblocked. The suggestion of -nopm
on the PR seemed pretty good to me.
Thanks.
I've made some tests. Using multi-stage docker build and node static build I was able to reduce node alpine image size by two times. And upx-packed is four times less size.
REPOSITORY TAG IMAGE ID CREATED SIZE
node alpine d97a436daee9 8 days ago 79.3MB
mhart/alpine-node slim b8c1832fbf86 8 days ago 44.5MB
m03geek/alpine-node latest 4ed96bad5c6f 10 minutes ago 38.7MB
m03geek/alpine-node upx-latest c3e52e2954ac 22 seconds ago 18.6MB
You can find dockerfile in my repo https://github.com/SkeLLLa/alpine-node, feel free to use it if needed.
FWIW, I'm maintaining scratch Node images at https://github.com/astefanutti/scratch-node. The compressed size is around 14MB for Node 12.
@astefanutti that's very nice. I've created static built based on your idea with scratch. And with upx it became even smaller: ~12MB. You may apply upx packer in your repo as well. Also I've created autobuild repo, so if anyone interested: https://hub.docker.com/r/m03geek/alpine-node. Those are not well tested, but they should work.
If anyone here is interested in porting that into official repo - feel free to take, test, enhance the code (repo link is in docker repo description).
Agree it would be useful!
fwiw, I experimented a bit with this over here using GitHub Actions to build a statically compiled node
: https://github.com/chorrell/docker-node-minimal
Building the node:14-alpine
image without npm or yarn reduces the image size from 116MB to 86MB, most of which is the 71MB node
binary.
Any news on this? Issue was created over 3 years ago :-S
Almost one year in since last bump and still no info about minimal node base images suited for production workloads?
We currently struggle because Microsoft Defender for Cloud flags all our Production builds because of an outdated dependency in npm (-> ip@2.0.0).
I created the debian core image in #2058
Now that Docker supports multi-stage builds it'd be nice to have an official base image with just the Node.js binary. A build image could extend from the current images and a production image could extend from the standalone version (copying the built application with all installed dependencies from the build container).