-
Notifications
You must be signed in to change notification settings - Fork 2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Try to download pre-built alpine binary before building #1026
Try to download pre-built alpine binary before building #1026
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is awesome! Would be so good to not have to build for alpine (albeit we'll probably be building node 10 for a while)
The only thing missing is the different architecture. The output in Alpine is different than on Debian. |
@tianon do you have those? |
081b462
to
9c213fd
Compare
Nevermind, I just won't error on the other archs |
49723d6
to
61db88d
Compare
10/alpine/Dockerfile
Outdated
make \ | ||
python \ | ||
RUN ARCH= && alpineArch="$(arch)" \ | ||
&& case "${alpineArch##*-}" in \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this needed? x64 is the only option so this can be simplified be removing the alpine specific case statement
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need to detect the arch anywys because the other arch will still need to build from source
Dockerfile-alpine.template
Outdated
make \ | ||
python \ | ||
RUN ARCH= && alpineArch="$(arch)" \ | ||
&& case "${alpineArch##*-}" in \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same as previous comment:
Is this needed? x64 is the only option so this can be simplified be removing the alpine specific case statement
6/alpine/Dockerfile
Outdated
@@ -2,20 +2,19 @@ FROM alpine:3.9 | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this hits EOL on the 30th, maybe better to skip instead of pushing a new version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can wait after the 30th an rebase this after version 6 has been removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
10/alpine/Dockerfile
Outdated
@@ -34,6 +33,23 @@ RUN addgroup -g 1000 node \ | |||
gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \ | |||
gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \ | |||
done \ | |||
&& ( \ | |||
curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-$ARCH-musl.tar.xz" \ | |||
&& curl -fsSLO --compressed "https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/SHASUMS256.txt" \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Downloading the shasums file at the same time as the tar doesn't really increase the authenticity of the artifact. If someone is able to compromise the unofficial-builds
server (or the connection to it), then they can easily change both files to match.
We usually recommend downloading the sha file separately (like during update.sh
) so that it can be embedded in the Dockerfile. See https://github.com/docker-library/official-images/tree/3b512a89a9719efa190d5938ea3ca4ca5291d68c#image-build
There is also a bug in that a failed sha256sum
(or tar
, rm
, or ln
) could leave the tar, shasum, or extracted files intact in the image while still then building from source. For RUN
lines that need more complex logic, you might want to move to using set -eu
with semicolons rather than &&
(docker-library/mongo#313 (comment)).
Overall, these new builds will be nice to have!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, it should really only try building from source if neither file exists, since a sha or other failure indicates a different problem and the image should appropriately fail to build.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these comments have been addressed yet. 😉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, but this approach is in line with the other image so maybe it warrants a separate discussion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not following -- which "other image" are you referring to?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also need to address when these lines fail:
There is also a bug in that a failed
sha256sum
(ortar
,rm
, orln
) could leave the tar, shasum, or extracted files intact in the image while still then building from source. ForRUN
lines that need more complex logic, you might want to move to usingset -eu
with semicolons rather than&&
(docker-library/mongo#313 (comment)).If the tar downloads (and fails to shasum or something), it should consider that as the only possible route for the given version, rather than falling back to building, so that the build failure can be noticed and the unofficial artifacts fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done!!! Only thing left is to modify the update script to embed the shasum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The current implementation still suffers here -- as written, it will always attempt to download an unofficial-builds tarball whether one is expected to exist or not, and even if we're on an architecture where we expect to have such a tarball, if it does not exist, we'll happily throw a harmless error in the logs nobody will check followed by downloading the source and building instead. Not a bad strategy from a "resilient builds" perspective, but it doesn't help catch issues with the unofficial-builds project.
Here's an alternative approach (created from 10/alpine/Dockerfile
to illustrate so I'd have something concrete I could test/verify):
FROM alpine:3.9
ENV NODE_VERSION 10.16.1
RUN set -eux; \
addgroup -g 1000 node; \
adduser -u 1000 -G node -s /bin/sh -D node; \
apk add --no-cache \
libstdc++ \
; \
apk add --no-cache --virtual .build-deps \
curl \
; \
apkArch="$(apk --print-arch)"; \
url=; checksum=; \
case "$apkArch" in \
x86_64) \
url="https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64-musl.tar.xz"; \
checksum='c5b5adc27dfe1c9bded56b30158f9a10c617c93dde1f74febc19866dc5ff487c'; \
;; \
esac; \
if [ -n "$url" ] && [ -n "$checksum" ]; then \
curl -fsSL -o node.txz --compressed "$url"; \
echo "$checksum *node.txz" | sha256sum -c -; \
tar -xJf node.txz -C /usr/local --strip-components=1 --no-same-owner; \
rm node.txz; \
else \
apk add --no-cache --virtual .build-deps-full \
binutils-gold \
g++ \
gcc \
gnupg \
libgcc \
linux-headers \
make \
python \
; \
# gpg keys listed at https://github.com/nodejs/node#release-keys
for key in \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
77984A986EBC2AA786BC0F66B01FBB92821C587A \
8FCCA13FEF1D0C2E91008E09770F7A9A5AE15600 \
4ED778F539E3634C779C87C6D7062848A1AB005C \
A48C2BEE680E841632CD4E44F07496B3EB3C1762 \
B9E2F5981AA6E0CD28160D9FF13993A75599653C \
; do \
gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done; \
curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.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.tar.xz\$" SHASUMS256.txt | sha256sum -c -; \
tar -xf "node-v$NODE_VERSION.tar.xz"; \
cd "node-v$NODE_VERSION"; \
./configure; \
make -j$(getconf _NPROCESSORS_ONLN) V=; \
make install; \
apk del --no-network .build-deps-full; \
cd ..; \
rm -Rf "node-v$NODE_VERSION"; \
rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \
fi; \
apk del --no-network .build-deps; \
# basic sanity/smoke test
node --version
ENV YARN_VERSION 1.17.3
RUN apk add --no-cache --virtual .build-deps-yarn curl gnupg tar \
&& for key in \
6A010C5166006599AA17F08146C2130DFD2497F5 \
; do \
gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
done \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz" \
&& curl -fsSLO --compressed "https://yarnpkg.com/downloads/$YARN_VERSION/yarn-v$YARN_VERSION.tar.gz.asc" \
&& gpg --batch --verify yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& mkdir -p /opt \
&& tar -xzf yarn-v$YARN_VERSION.tar.gz -C /opt/ \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarn /usr/local/bin/yarn \
&& ln -s /opt/yarn-v$YARN_VERSION/bin/yarnpkg /usr/local/bin/yarnpkg \
&& rm yarn-v$YARN_VERSION.tar.gz.asc yarn-v$YARN_VERSION.tar.gz \
&& apk del .build-deps-yarn
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
CMD [ "node" ]
And the diff
, which should make the changes I've made more obvious:
$ GIT_PAGER=cat git diff --ignore-all-space
diff --git a/10/alpine/Dockerfile b/10/alpine/Dockerfile
index c165a6c..b653f4e 100644
--- a/10/alpine/Dockerfile
+++ b/10/alpine/Dockerfile
@@ -2,13 +2,31 @@ FROM alpine:3.9
ENV NODE_VERSION 10.16.1
-RUN addgroup -g 1000 node \
- && adduser -u 1000 -G node -s /bin/sh -D node \
- && apk add --no-cache \
+RUN set -eux; \
+ addgroup -g 1000 node; \
+ adduser -u 1000 -G node -s /bin/sh -D node; \
+ apk add --no-cache \
libstdc++ \
- && apk add --no-cache --virtual .build-deps \
- binutils-gold \
+ ; \
+ apk add --no-cache --virtual .build-deps \
curl \
+ ; \
+ apkArch="$(apk --print-arch)"; \
+ url=; checksum=; \
+ case "$apkArch" in \
+ x86_64) \
+ url="https://unofficial-builds.nodejs.org/download/release/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64-musl.tar.xz"; \
+ checksum='c5b5adc27dfe1c9bded56b30158f9a10c617c93dde1f74febc19866dc5ff487c'; \
+ ;; \
+ esac; \
+ if [ -n "$url" ] && [ -n "$checksum" ]; then \
+ curl -fsSL -o node.txz --compressed "$url"; \
+ echo "$checksum *node.txz" | sha256sum -c -; \
+ tar -xJf node.txz -C /usr/local --strip-components=1 --no-same-owner; \
+ rm node.txz; \
+ else \
+ apk add --no-cache --virtual .build-deps-full \
+ binutils-gold \
g++ \
gcc \
gnupg \
@@ -16,8 +34,9 @@ RUN addgroup -g 1000 node \
linux-headers \
make \
python \
+ ; \
# gpg keys listed at https://github.com/nodejs/node#release-keys
- && for key in \
+ for key in \
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
FD3A5288F042B6850C66B31F09FE44734EB7990E \
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
@@ -33,20 +52,24 @@ RUN addgroup -g 1000 node \
gpg --batch --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys "$key" || \
gpg --batch --keyserver hkp://ipv4.pool.sks-keyservers.net --recv-keys "$key" || \
gpg --batch --keyserver hkp://pgp.mit.edu:80 --recv-keys "$key" ; \
- done \
- && curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.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.tar.xz\$" SHASUMS256.txt | sha256sum -c - \
- && tar -xf "node-v$NODE_VERSION.tar.xz" \
- && cd "node-v$NODE_VERSION" \
- && ./configure \
- && make -j$(getconf _NPROCESSORS_ONLN) V= \
- && make install \
- && apk del .build-deps \
- && cd .. \
- && rm -Rf "node-v$NODE_VERSION" \
- && rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt
+ done; \
+ curl -fsSLO --compressed "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION.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.tar.xz\$" SHASUMS256.txt | sha256sum -c -; \
+ tar -xf "node-v$NODE_VERSION.tar.xz"; \
+ cd "node-v$NODE_VERSION"; \
+ ./configure; \
+ make -j$(getconf _NPROCESSORS_ONLN) V=; \
+ make install; \
+ apk del --no-network .build-deps-full; \
+ cd ..; \
+ rm -Rf "node-v$NODE_VERSION"; \
+ rm "node-v$NODE_VERSION.tar.xz" SHASUMS256.txt.asc SHASUMS256.txt; \
+ fi; \
+ apk del --no-network .build-deps; \
+# basic sanity/smoke test
+ node --version
ENV YARN_VERSION 1.17.3
If you like this approach, I'd be happy to put together a proper PR.
Well, the way unofficial-builds is currently set up is that it's just going to churn out builds for any new release of any release line because it's just watching for changes, which may not be a great idea because it's applying Node 12 build standards across the board and maybe there should be some differentiation. But the result is that you'll get unofficial-builds linux-x64-musl binaries for Node 8 and 10 too. They're using Alpine 3.9, so musl 1.1.20, if you're shipping older Alpine containers then it might be a problem. |
there's also nothing precluding doing anything different with unofficial-builds, it's essentially a blank slate looking for contributors to make it do what they need |
Ah, didn't know that! Pretty sweet. Maybe we could try to ship both our current "build in container" in addition to those others and ask people to try them out?
We are just on 3.9 (we don't have the capacity to build for multiple), so that shouldn't be an issue. |
What does this mean? Are you shipping both x86 and x64 versions of the Alpine container or some other architecture? Is there much of a call for x86 Docker containers? I've just added x64-musl to unofficial-builds because my assumption was that this is all people are using with Alpine. If that's not the case and there's popular use of other architectures then maybe we should expand the offering there? It's a fairly straightforward matter of adding a new recipe to the chain. Also regarding availability timing on unofficial-builds, this all depends on how long it takes to compile everything. New releases are detected within 5 minutes and then start building. So if I look at the timestamp on index.json at https://nodejs.org/download/release/ which reflects the 12.0.0 release and compare it to the index.json at https://unofficial-builds.nodejs.org/download/release/ which reflects the availability of builds there; the former is This all assumes that the builds go without a hitch. Currently they are all dependent on each other so one failure will fail them all. That's not ideal and needs to change (contributions welcome!). We still have Alpine in the Node CI cluster but no x86 and no ARMv6 so it's more likely that one of the others will fail to build at some point in the future than musl. |
@rvagg we unfortunately can't get tag specific metrics from docker but we have had issues/questions about the alpine variant on other archs than x64. Here is the architecture matrix for version 11 we use: https://github.com/nodejs/docker-node/blob/master/11/architectures |
That's a lotta architectures. per-arch metrics would be fascinating. I bet there'd be no squeals if you trimmed that list a bit; it's a shame you can't know for sure. |
@rvagg I think it might be a reasonable compromise to use the unofficial build infrastructure to deliver the most common arch (x64 only or x64 and i386) and have the other builds occuring on the docker build infrastructure. It would allow us to deliver new release to the majority way faster while not affecting the other archs. |
I did some experimenting with trying to get musl x86 binaries on the 64-bit host but I can't see a way to do it without some serious hoop jumping. There's no combination of musl + gcc multilib support that I can find anywhere so it either requires a custom gcc compile or a 32-bit host. Without metrics that show that these are even used I might drop the idea for now (although others are welcome to take up the challenge!). |
@rvagg just having the x64 one is a huge help for us. We can always look at i386 later if need be. |
I agree. Just having x64 solves the immediate problem of the slow travis builds. That will speed up our part of the release process significantly. |
61db88d
to
b812021
Compare
Is there any blockers left for this? |
22d1745
to
c6b44fb
Compare
Ok! removed the |
@PeterDaveHello I think we are good to go!! |
c6b44fb
to
52fad23
Compare
@PeterDaveHello all done! |
the last minor issue: #1026 (comment) |
52fad23
to
9b38bc4
Compare
@PeterDaveHello in theory though, the whole |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, that's right, but just want to keep the diff minimized in such huge change, never mind. I was going to merge this one but noticed it appears another commit and seems an accident that you want to remove it first?
9b38bc4
to
93c5e09
Compare
@PeterDaveHello done! |
Created PR to the official-images repo (docker-library/official-images#6871) |
dang, you just ticked over the 6 month mark for this PR congrats anyway! |
This change appears to have rolled back the version of musl. Up until this change, we were pulling in musl-1.1.20-r5. As of two days ago node:10-alpine and node:12.13-alpine (those are all I've checked) are pulling musl-1.1.20-r4, which has the vulnerability CVE-2019-14697. (CVSS v2 score of 7.5 and CVSS v3 score of 9.8 - https://nvd.nist.gov/vuln/detail/CVE-2019-14697) This is not too surprising, as the original pull request is from before musl-1.1.20-r5 was released. But boy does it speed up the build! :) Unfortunately, it also breaks the build if you block builds that contain high or critical vulnerabilities. See also #1143 |
@misterpaul is there a line specifically you think did this? We are installing node on top of the base image and are not modifying the base image much. |
We should link this PR to #1025 |
No description provided.