Open tracker1 opened 9 years ago
:+1:
@tracker1 https://github.com/oren/alpine-node - only 22 MB
Perhaps run this binary against the test suite to make sure it passes?
@jbergstroem automated tests of our docker images is def on my roadmap. Just haven't had time. I'll open an issue for it though.
Just saying that the alpine stuff is pretty much bleeding edge (that alpine-node seems to pull the latest available from alpine). If this ends up being our recommended solution, it'd be great to back that statement up. Btw, I'm also really like the suggested approach of minimising the container size as long as we're very comfortable with the toolchain that leads us there.
@oren thanks, had considered doing the same... added issue suggesting the addition of pre-requisites for gyp...
@jbergstroem cool, I'd thought about just seeing which version was in apm
and how well up to date the alpine image would be myself, hadn't taken the time. Agreed on minimizing the size... even though it's not too bad, ubuntu and debian images are a bit bigger and if we can start off small, it is a great thing.
yup. tiny images are nice. Here is nginx in 6 MB - https://github.com/oren/alpine-nginx
100% agree with the direction this is going. I'll be glad to tackle this, but it might be a few weeks before I'm at a point where I can explore this area (my backlog is pretty long right now). If @oren or @tracker1 (or others?) wants to kick off exploring this in the form of a PR to a new branch (maybe alpine
?) we can start iterating on the idea. Thoughts?
( //CC: @pesho @Starefossen @hmalphettes @jlmitch5)
I also like this, and would welcome a PR adding it as a tag in this repo (possible tags: alpine, micro, busybox, or something else?)
IMO "alpine" would be the most self-descriptive tag :smile:
would welcome a PR adding it as a tag in this repo
A few points, before anyone starts working on such a PR:
If it's not possible to satisfy the above, I think the Alpine image should remain separate.
The source of the iojs package build is here: https://github.com/alpinelinux/aports/blob/master/testing/iojs/APKBUILD
The image 'alpine:edge' does not contain gnupg indeed; Note that gnupg is available as a supported package.
If we go down this route dont we need to provide the rest of the images: "iojs:alpine-slim", "iojs:alpine", "iojs:alpine-onbuild" ?
Starting from @oren's Dockerfile I have been testing Alpine to run some modules with native dependencies. @oren's image is a fine alternative to iojs:slim.
We would need a second fatter alpine image with the build tools to support this situation:
RUN apk update && \
apk add --update iojs make g++ git gnupg python bash && rm -rf /var/cache/apk/*
That image weighs 203 MB to be compared with the 700 MB of the debian based iojs image.
What about having 2 images: 22 MB image for situations where native modules are not needed, and 700 MB for the other case.
@oren at the moment there are 3 images based off debian jessie
@oren could you specify the content of the 2 images you have in mind?
Good thing to have in mind: alpine runs on musl (at least when I last checked). Has anyone run the iojs test suite on such a docker image yet?
Both _mjones from #alpine-linux and myself run the test suite.
environment alpine edge on kvm full virtualisation. results 7 tests fail, 828 tests pass. It looks like the failures are deliberate behaviour of musl libc (the failed tests are one due to busybox 'ps' not having the p option, and the rest TLS/SSL). He will investigate it later. Details here: http://paste.ubuntu.com/10710805/
environment
ubuntu + docker. Steps to reprouce my setup: https://github.com/oren/test-iojs-docker-alpine
results
I was not able to run the tests.
When I run ./configure --prefix=/usr --shared-openssl --shared-zlib
I get: http://paste.ubuntu.com/10710714
And When I run make
I get: http://paste.ubuntu.com/10710640/
@hmalphettes you are correct about the number of images needed. It should match whatever we currently have.
@hmalphettes given the binary capable version is about the same size as the current slim, I'd say that's pretty nice.
@tracker1 agreed: it is very nice.
I second @pesho's comment on verifying binaries in order for this to become an official io.js image under the :alpine
tag.
:+1: on verification, and I would still like to see #46 be a prerequisite to shipping this if it gets that far.
Update: I am able to run the tests and get 4 errors. To reproduce it follow https://github.com/oren/test-iojs-docker-alpine
make -C out BUILDTYPE=Release V=1
make[1]: Entering directory '/tmp/iojs-v1.6.3/out'
make[1]: Nothing to be done for 'all'.
make[1]: Leaving directory '/tmp/iojs-v1.6.3/out'
ln -fs out/Release/iojs iojs
/usr/bin/python tools/test.py --mode=release message parallel sequential -J
Path: parallel/test-cluster-http-pipe
events.js:141
throw er; // Unhandled 'error' event
^
Error: read EACCES
at exports._errnoException (util.js:749:11)
at Pipe.onread (net.js:538:26)
assert.js:88
throw new assert.AssertionError({
^
AssertionError: false == true
at process.<anonymous> (/tmp/iojs-v1.6.3/test/parallel/test-cluster-http-pipe.js:22:5)
at emitOne (events.js:82:20)
at process.emit (events.js:166:7)
at process.exit (node.js:659:17)
at Worker.<anonymous> (/tmp/iojs-v1.6.3/test/parallel/test-cluster-http-pipe.js:19:13)
at emitTwo (events.js:87:13)
at Worker.emit (events.js:169:7)
at ChildProcess.<anonymous> (cluster.js:351:14)
at ChildProcess.g (events.js:257:16)
at emitTwo (events.js:87:13)
Command: out/Release/iojs /tmp/iojs-v1.6.3/test/parallel/test-cluster-http-pipe.js
Path: parallel/test-http-client-pipe-end
events.js:141
throw er; // Unhandled 'error' event
^
Error: read EACCES
at exports._errnoException (util.js:749:11)
at Pipe.onread (net.js:538:26)
Command: out/Release/iojs /tmp/iojs-v1.6.3/test/parallel/test-http-client-pipe-end.js
Path: parallel/test-http-client-response-domain
assert.js:88
throw new assert.AssertionError({
^
AssertionError: 'should be caught by domain' == 'read EACCES'
at Domain.<anonymous> (/tmp/iojs-v1.6.3/test/parallel/test-http-client-response-domain.js:29:12)
at emitOne (events.js:77:13)
at Domain.emit (events.js:166:7)
at ClientRequest.emit (events.js:139:14)
at Socket.socketErrorListener (_http_client.js:254:9)
at emitOne (events.js:77:13)
at Socket.emit (events.js:166:7)
at net.js:438:14
at process._tickDomainCallback (node.js:366:13)
Command: out/Release/iojs /tmp/iojs-v1.6.3/test/parallel/test-http-client-response-domain.js
Path: parallel/test-http-unix-socket
Error: read EACCES
at exports._errnoException (util.js:749:11)
at Pipe.onread (net.js:538:26)
assert.js:88
throw new assert.AssertionError({
^
AssertionError: false == true
at process.<anonymous> (/tmp/iojs-v1.6.3/test/parallel/test-http-unix-socket.js:63:10)
at emitOne (events.js:82:20)
at process.emit (events.js:166:7)
at process.exit (node.js:659:17)
at ClientRequest.<anonymous> (/tmp/iojs-v1.6.3/test/parallel/test-http-unix-socket.js:55:13)
at emitOne (events.js:77:13)
at ClientRequest.emit (events.js:166:7)
at Socket.socketErrorListener (_http_client.js:254:9)
at emitOne (events.js:77:13)
at Socket.emit (events.js:166:7)
Command: out/Release/iojs /tmp/iojs-v1.6.3/test/parallel/test-http-unix-socket.js
Path: parallel/test-module-loading-error
util.debug: Use console.error instead
DEBUG: load test-module-loading-error.js
assert.js:88
throw new assert.AssertionError({
^
AssertionError: -1 != -1
at Object.<anonymous> (/tmp/iojs-v1.6.3/test/parallel/test-module-loading-error.js:22:10)
at Module._compile (module.js:410:26)
at Object.Module._extensions..js (module.js:428:10)
at Module.load (module.js:335:32)
at Function.Module._load (module.js:290:12)
at Function.Module.runMain (module.js:451:10)
at startup (node.js:123:18)
at node.js:867:3
Command: out/Release/iojs /tmp/iojs-v1.6.3/test/parallel/test-module-loading-error.js
Makefile:76: recipe for target 'test' failed
Looks like the first 3 are permission errrors (maybe)? The last one is a bit strange. I'm not used to running the iojs-test suite though.
Unfortunately there are some challenges with running the io.js test suite 😕 Maybe someone at iojs/build may be able to help?
FWIW, I've been using io.js on my Alpine Docker image for a while now (only 24.6 MB!) – there are only two failing tests on my stack, due to assumptions in the tests themselves.
One test (test-module-loading-error.js) is loading an already-built native linux module, which I assume is built with glibc because it fails with "Exec format error" – native modules work fine on Alpine if they're compiled using musl (which npm/node-gyp will do during an npm install) – so I think the test scope here is too narrow. The test shouldn't just check for linux, but also for glibc – and perhaps have another option for musl-based linux distros.
The other test (test-setproctitle.js) is failing because it's trying to run ps
with a -p
flag, which isn't supported on the Alpine version of ps
– so I'd argue that the test should be changed with that in mind.
So apart from those minor test issues, it runs fine. You can check it out here:
:+1:
Sorry for jumping in mid-stream here and not fully groking the entirety of this thread but I think @jbergstroem's point about testing needs to be expanded on: when @iojs/docker is considering releasing images based on specific platforms like this it would be great if we could take a more coordinated approach to the issue of platform support. If you go ahead and push an Alpine Linux based image while this distro is not part of our CI suite for io.js you're creating a gap in our understanding of what it means for it to be supported.
I'd suggest that if you're set on doing this then @iojs/docker and @iojs/build find some way to integrate testing into regular CI such that we can be clearer about it being a supported platform, both in the current state of io.js and as it evolves over time. I don't know enough (anything?) about this distro so can't suggest a way forward but would love to help explore this. Perhaps something like build-containers for this if it's a container-focused distro?
@rvagg I can commit to having a CI figured out for the iojs docker images by end of June.
In this presentation redbeard makes the case that we should build our iojs/nodejs containers from scratch instead of relying on a general purpose distro: https://www.youtube.com/watch?v=gMpldbcMHuI
Yes, or we can take this approach by @rmg.
@hmalphettes Highly interesting talk, thanks for the link :-)!
Basically, I agree with you, but… I think the solution can not be that every developer who wants to run Node.js using Docker has to build her or his own container. We need a really small and reliable official base image. Of course, this can be built using the techniques shown in the video, but it should be done once, not over and over again, shouldn't it?
@Starefossen good point: build-container and runtime-container. For my daily work I use the full iojs for builds and then copy the application and its node_modules into iojs-slim for the runtime. Those techniques add-up: the smaller the runtime container iojs provides and the smaller my application's runtime container will be.
@goloroden yes agreed. What I understood from the talk is that nodejs/iojs team here provides a "built from scratch" set of images. Downstream users of those images add their application: just like what we do today.
I thought it was interesting to bring in the fact that we can choose buildroot or something else as an alternative to alpine linux if it helps. For example we can choose gcc with buildroot if alpinelinux's musl libc is problematic.
@Starefossen and friends: if we want to build iojs on the top of alpinelinux would this type of Dockerfile from @mhart be acceptable: https://github.com/mhart/alpine-node/blob/master/Dockerfile? With @mhart's kind permission we can adopt it and derive the full, slim and onbuild versions.
Short of that we need to get involved with alpinelinux to maintain the iojs package.
@hmalphettes @mhart is actually involved in this thread ;-)
https://github.com/nodejs/docker-iojs/issues/44#issuecomment-95969892
The blocker is testing which is being talked about in these threads:
Once we get testing figured out, we can take it to the @nodejs/build team to get signed off on it being a supported platform as rvagg said in: https://github.com/nodejs/docker-iojs/issues/44#issuecomment-96114656
Yeah, so FWIW we've been running the Uniqlo US Mobile site on alpine-iojs in production for at least 6 months now with no problems (on 2.5.0 atm, haven't moved to 3.0.0 yet)
I'm more than happy for ppl to use the image and/or the Dockerfile for whatever they'd like (and the license in the project should cover that).
I try to keep it up to date as soon as new node/io.js releases come out, but given its current lack of automated testing, etc, it's probably not a good candidate to be officially sanctioned in any way. At least, as it stands right now.
@Starefossen thanks for the mention :-)
writes a long comment, reads thread, deletes comment because everything had already been said
:+1:
Thanks for the image Something is not right with compiled modules, for example (runtime, npm install seems ok except few warnings): Error: Error loading shared library /usr/src/app/node_modules/twelve/node_modules/bson/build/Release/bson.node: Exec format error]
@mkrn did you mean to post that as a new issue? Or is it related to this discussion about using alpine linux as a base image?
Nevermind please @rmg I think node_modules were copying from my machine until i've added them to .dockerignore
Thanks for the image!
@mhart installing procps
adds support for ps -p
as suggested by @oren here: https://github.com/oren/test-iojs-docker-alpine/commit/72f6f35a3e69483584de2651a251ae0d88d7e099
There are 3 failing tests for v5.0.0:
test-module-loading-error.js
fails as reported above already. The error message is Exec format error
which makes sense for an invalid node life. Note that if we compile it with --fully-static
then we get the error message: Dynamic loading not supported
test-net-better-error-messages-port-hostname.js
returns an EAI_AGAIN
instead of the expected ENOTFOUND
. I am not enough of an expert to declare how critical that is./node-v5.0.0/test/parallel/test-stdout-close-unref.js:8
process.stdin._handle.close();
^
TypeError: Cannot read property 'close' of undefined
@hmalphettes Were you able to solve Dynamic loading not supported
? I am using a node package running process.dlopen()
that is throwing this error on an Alpine container.
@polarathene that probably means you're using a statically compiled node.js binary? Which Alpine container (and tag) are you using?
@mhart I'm using FROM smebberson/alpine-nodejs
from this repo. They have a base alpine image and several examples extending it, once I get this working without errors I'll be using the docker images that include consul from the repo.
You're correct about them using a static compiled node.js binary I think, here is the Dockerfile for the image I'm using. How would I go about fixing this, and is there any drawbacks involved? If it's just compile time perhaps I could send a PR for a variant or replacement of the current Dockerfile.
Yep, they're definitely statically compiling: https://github.com/smebberson/docker-alpine/blob/master/alpine-nodejs/Dockerfile#L9
You could use another image that doesn't statically compile. I have a bunch of them over here: https://github.com/mhart/alpine-node
So you could use mhart/alpine-node:6
or mhart/alpine-node:5
or mhart/alpine-node:4
or whatever you'd like.
Or if you want to continue using the image you're currently using, you could just remove the --fully-static
flag and build it yourself.
I've created an issue on their repo letting them know about it, until then I'll give your images a go :)
Thanks for the help, I looked into advantages/disadvantages of using dynamic linking instead of a static linking here, any idea if performance/memory is affected much with Node when built with dynamic linking?
https://registry.hub.docker.com/_/alpine/
Though I'm not sure how much will actually be saved once Python2.7, build tools and libssl dependencies are installed, it might be worth considering.