-
-
Notifications
You must be signed in to change notification settings - Fork 466
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
Support BuildKit #601
Comments
This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Open a new issue if needed. |
Realize this is old, but seems current situation is that the HTTP API does not support buildkit, even in 2022 :( |
https://docs.docker.com/build/buildkit/
This issue should be re-opened. Users are failing to build images using BuildKit features: testcontainers/testcontainers-node#571 |
Didn't have the time yet to look at Docker CLI source code to check how is CLI using it. |
This is no longer an issue. const docker = require("dockerode");
docker.buildImage({...}, { version: "2" }) The support for the If I get a chance, I'll update the DefinitelyTyped package |
@mikeseese Have you tested that? I think there's quite a lot more to this than just sending a different version in the request unfortunately. The protocol to actually run the build is completely different, and as far as I know there's no kind of compatibility layer or similar - we'll need to fully implement the new protocol. Under the hood, non-BuildKit builds just send a single HTTP request with all files and the build options, and then stream the raw build output back. BuildKit builds meanwhile just start a session with initial options, then uses gRPC over HTTP/2 to do two-way communication throughout the build. Files aren't sent up front: instead the server requests each file it needs from the client on demand, and similarly injects secrets and proxies remote SSH authentication from the client over the connection. It's not just a flag to enable. For example, try building this minimal Buildkit Dockerfile: # syntax=docker/dockerfile:1
FROM bash
RUN echo 'hello' > /tmp/hello Running this: let Dockerode = require('dockerode')
let d = new Dockerode()
d.buildImage({ context: process.cwd(), src: ['Dockerfile'] }, { version: '2' }, (e, res) => res.pipe(process.stdout)) Prints: {"id":"moby.buildkit.trace","aux":"Cm8KR3NoYTI1Njo1NTNiMmZmZTZjOTM2ZDRlYjczNGY0ZjRkZTRlZWU4N2M0YWRiN2Y0NjlkYjk0YTQzZGM3NTkzNzhhYWVkNGU3GiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQ="}
{"id":"moby.buildkit.trace","aux":"Cn0KR3NoYTI1Njo1NTNiMmZmZTZjOTM2ZDRlYjczNGY0ZjRkZTRlZWU4N2M0YWRiN2Y0NjlkYjk0YTQzZGM3NTkzNzhhYWVkNGU3GiRbaW50ZXJuYWxdIGxvYWQgcmVtb3RlIGJ1aWxkIGNvbnRleHQqDAjl5aCzBhDp2aulAQ=="}
{"id":"moby.buildkit.trace","aux":"CosBCkdzaGEyNTY6NTUzYjJmZmU2YzkzNmQ0ZWI3MzRmNGY0ZGU0ZWVlODdjNGFkYjdmNDY5ZGI5NGE0M2RjNzU5Mzc4YWFlZDRlNxokW2ludGVybmFsXSBsb2FkIHJlbW90ZSBidWlsZCBjb250ZXh0KgwI5eWgswYQ6dmrpQEyDAjl5aCzBhCBjeDFAQ=="}
{"id":"moby.buildkit.trace","aux":"CosBCkdzaGEyNTY6NTUzYjJmZmU2YzkzNmQ0ZWI3MzRmNGY0ZGU0ZWVlODdjNGFkYjdmNDY5ZGI5NGE0M2RjNzU5Mzc4YWFlZDRlNxokW2ludGVybmFsXSBsb2FkIHJlbW90ZSBidWlsZCBjb250ZXh0KgwI5eWgswYQzZP1xQEyDAjl5aCzBhDs1PjFAQ=="}
{"id":"moby.buildkit.trace","aux":"CqMBCkdzaGEyNTY6YWM2MjQ0YzMyMGNjNTI5NTRjMDAyYTM0Njg1YzUwNjlkM2RhNGMyNTYzZjUyNGQwNTY1ZWM0OTUxNTk3NDJmZRJHc2hhMjU2OjU1M2IyZmZlNmM5MzZkNGViNzM0ZjRmNGRlNGVlZTg3YzRhZGI3ZjQ2OWRiOTRhNDNkYzc1OTM3OGFhZWQ0ZTcaD2NvcHkgL2NvbnRleHQgLw=="}
{"id":"moby.buildkit.trace","aux":"CrEBCkdzaGEyNTY6YWM2MjQ0YzMyMGNjNTI5NTRjMDAyYTM0Njg1YzUwNjlkM2RhNGMyNTYzZjUyNGQwNTY1ZWM0OTUxNTk3NDJmZRJHc2hhMjU2OjU1M2IyZmZlNmM5MzZkNGViNzM0ZjRmNGRlNGVlZTg3YzRhZGI3ZjQ2OWRiOTRhNDNkYzc1OTM3OGFhZWQ0ZTcaD2NvcHkgL2NvbnRleHQgLyoMCOXloLMGELvFjsoB"}
{"id":"moby.buildkit.trace","aux":"Cr8BCkdzaGEyNTY6YWM2MjQ0YzMyMGNjNTI5NTRjMDAyYTM0Njg1YzUwNjlkM2RhNGMyNTYzZjUyNGQwNTY1ZWM0OTUxNTk3NDJmZRJHc2hhMjU2OjU1M2IyZmZlNmM5MzZkNGViNzM0ZjRmNGRlNGVlZTg3YzRhZGI3ZjQ2OWRiOTRhNDNkYzc1OTM3OGFhZWQ0ZTcaD2NvcHkgL2NvbnRleHQgLyoMCOXloLMGELvFjsoBMgwI5eWgswYQzPKy6gE="}
{"id":"moby.buildkit.trace","aux":"Co8BCkdzaGEyNTY6YWMwNzJkNTIxOTAxMjIyZWVlZjU1MGY1MjI4Mjg3N2YxOTZlMTZiMDI0Nzg0NGJlOWNlYjFjY2MxZWFjMzkxZBo2cmVzb2x2ZSBpbWFnZSBjb25maWcgZm9yIGRvY2tlci5pby9kb2NrZXIvZG9ja2VyZmlsZToxKgwI5eWgswYQ07bR7gE="}
{"id":"moby.buildkit.trace","aux":"CrEBCkdzaGEyNTY6YWMwNzJkNTIxOTAxMjIyZWVlZjU1MGY1MjI4Mjg3N2YxOTZlMTZiMDI0Nzg0NGJlOWNlYjFjY2MxZWFjMzkxZBo2cmVzb2x2ZSBpbWFnZSBjb25maWcgZm9yIGRvY2tlci5pby9kb2NrZXIvZG9ja2VyZmlsZToxKgwI5eWgswYQ07bR7gEyDAjl5aCzBhD1ytPGAzoSbm8gYWN0aXZlIHNlc3Npb25z"}
{"errorDetail":{"message":"no active sessions"},"error":"no active sessions"} Sending the new version does switch to the buildkit protocol, but Dockerode doesn't know how to speak that protocol, so never successfully does anything. Even though this case isn't using any buildkit features, the build fails, and no image is created. |
@apocas I was able to create a reproduction repo that will successfully build an image with Removing the version flag will fail saying the chmod feature requires BuildKit but keeping the flag does indeed give me an image has |
The no active sessions does mean that there isn't complete support from dockerode, but this specific scenario might allow you to build fine after doing a |
Is it possible to use a remote builder for the build? |
You mean using a remote Docker engine, or using a remote Buildkitd daemon directly? The former will work (just as with any Dockerode command - local or remote is the same) but the latter almost certainly won't (https://github.com/moby/buildkit#expose-buildkit-as-a-tcp-service suggests the daemon's direct API only speaks its own gRPC API, while Dockerode is currently just uses plain HTTP with the Docker Engine API). Or do you mean something else? If you have a concrete example command/environment that'd be useful. |
@mikeseese Nice example! Yes, I can confirm that minimal case works, which is interesting. It seems that in that case you have managed to avoid everything that might require an active session, neat. To list them explicitly, the limitations I can see that do require a session (and so are currently not supported by Dockerode, or any implementation that just changes the
Also, the build output consists of JSON with base64'd content in the In cases where you can avoid the above features though and you only need the final image id (not the streamed build output) then just upgrading the version as above should work OK, so that might indeed be a workaround for some setups. I think going further though, it looks quite achievable to fully support the core Buildkit featureset, so that most normal builds do work without many constraints and give us the main benefits of Buildkit, and it'd be good to somehow aim for that. AFAICT the main steps required are:
I'm definitely interested in this, and I've got some outlines of the initial session negotiation logic working already, but I'm unlikely to have time to fully implement everything myself for the next couple of months at least. If anybody is keen to look at that in the meantime though then I'd be very happy to provide some pointers, just let me know. |
@pimterry in my minimal exploration of this I found that the gprc-js package was missing a feature that exists in the Go API to bind a GPRC server to an existing socket https://github.com/grpc/grpc-node/blob/master/packages/grpc-js/src/server.ts#L806 However this might be changing with v1.11 of gprc-js according to this grpc/grpc-node#2675 so that might be the final piece needed to implement buildkit support into dockerode |
I was just able to create a POC for this. Happy for any feedback and improvements: #766 |
Would be nice to provide an easy way to enable BuildKit for faster and more efficient builds.
It's as easy as setting
DOCKER_BUILDKIT=1
before using the Docker CLI, not sure what is required from the perspective of the Docker API usage.The text was updated successfully, but these errors were encountered: