-
Notifications
You must be signed in to change notification settings - Fork 601
debug: Add buildx debug command
#2006
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
Conversation
80bb8e0 to
274c1ce
Compare
|
It seems that we need to fix https://github.com/docker/docs as well to pass the CI?
|
Ah right that's because we have a stub file upstream for |
commands/root.go
Outdated
| ) | ||
| if isExperimental() { | ||
| cmd.AddCommand(debugcmd.RootCmd(dockerCli, func(dops debugcmd.DebugOptions) *cobra.Command { | ||
| return buildCmd(dockerCli, opts, dops) |
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 are just debugging the build cmd so sounds good to have buildx debug defaulting to build atm but could be any root cmd in the future such as bake with buildx debug bake so we might consider passing cmd instead and have a "debug" interface for each command supporting debug. WDYT?
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.
Thanks for the suggestion! It sounds good to me. I've fixed the patch to pass *cobra.Command with the debugger interface to debugcmd.RootCmd. PTAL 🙏
934e927 to
55691f3
Compare
commands/debug/shell.go
Outdated
|
|
||
| cmd := &cobra.Command{ | ||
| Use: "debug-shell", | ||
| Use: "shell", |
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.
IMO, we could just have shell be the top-level command, so docker buildx debug drops you directly into the shell.
Then we don't need a separate command for it, and it kind of acts as debug is your portal to all debugging stuff. The top-level debug command needs to do something anyways, and to me this makes the most sense.
Also, if we drop shell, it means that we could potentially have every command after debug can be run without the debug - debug build corresponds to build, debug bake corresponds to bake, etc.
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.
Thanks for the suggestion! Fixed the patch to launch the debugger directly by buildx debug command.
|
Aha, thanks @ktock 🎉 This looks like a perfect start, just one real comment, otherwise looks good! |
commands/debug/root.go
Outdated
|
|
||
| // DebugConfig is a user-specified configuration for the debugger. | ||
| type DebugConfig struct { | ||
|
|
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.
nit: empty line (also below)
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.
Off-topic: is there any way we can get this linted / auto-formatted? I know that gofumpt has a rule for this, but there's some other rules in there that are a bit more controversial IMO. @crazy-max any ideas?
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 looked at gofumpt and wsl linters and don't see any rules for this case 🤔
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 they have rules like this for functions at least in "No empty lines around function bodies" but not for generic blocks
|
@ktock Following @dvdksn comment in docker/docs#17947 (comment), I have disabled the |
|
Thanks! |
| if isExperimental() { | ||
| flags.StringVar(&invokeFlag, "invoke", "", "Invoke a command after the build") | ||
| flags.SetAnnotation("invoke", "experimentalCLI", nil) | ||
| // TODO: move this to debug command if needed |
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.
root, detach and server-config flags don't look necessary anymore for build command right? Looks to be already available in debug root cmd.
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.
Maybe? Technically a non debugged build can still run on the remote controller, so maybe best to leave it here for now.
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.
Thanks @ktock!
This gets closer to what I was imagining 🎉
I wonder, (and maybe this is something to look into with the "extra" args after a -- component) if we should always drop into a shell when using a debug subcommand? To me, that would feel like a logical default.
PTAL @tonistiigi
e18f57d to
da87cb4
Compare
tonistiigi
left a comment
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.
- When I run
buildx debug(no arguments) and thenexec shI get
Process "i7xkjhw104urtoth9pboe0ug6" started. Press Ctrl-a-c to switch to that process.
(buildx) Switched IO
Switched IO
But there is no process, nor build context.
- I'm not sure if this is specifically in this PR but enabling debugger breaks stacktraces. Without the opt-in I get.
Dockerfile:60
--------------------
59 | ARG TARGETPLATFORM
60 | >>> RUN2 --mount=type=bind,target=. \
61 | >>> --mount=type=cache,target=/root/.cache \
62 | >>> --mount=type=cache,target=/go/pkg/mod \
63 | >>> --mount=type=bind,from=buildx-version,source=/buildx-version,target=/buildx-version <<EOT
64 | set -e
--------------------
ERROR: failed to solve: dockerfile parse error on line 60: unknown instruction: RUN2 (did you mean RUN?)
but with this only
ERROR: dockerfile parse error on line 60: unknown instruction: RUN2 (did you mean RUN?)
This is without any extra flags, just with BUILDX_EXPERIMANTAL=1 docker buildx debug build .
-
docker buildx debug --on=error build .with Dockerfile error I don't see any error printed at all, nor stacktrace. Only after I close the monitor I see the error printed. -
I think
--onshould default toerrorondebug build. Atm. I don't see any differences betweenbuildx buildandbuildx debug build. -
Issuing
rollbackcommand always seems to returncontext cancelederror.
Interactive container was restarted with process "4qa81kfpppzkoawwhh052bbn4". Press Ctrl-a-c to switch to the new container
(buildx) Switched IO
ERROR: failed to exec process: context canceled
ERROR: failed to exec process: context canceled
-
Follow-up.
--on=erroron a container error gets me in the container but there is no context of what happened, what was the last command etc. I think the help command or monitor messages should give context about what is the current interactive context (build result for specific target, error result from command) so there is context of what gets run onexec/reload/rollback. -
Follow-up. We need
lscommand that would list the files in the current dir. If I get error likerunc run failed: unable to start container process: exec: "sh": executable file not found in $PATHthen I have no idea what I'm missing. This could also be exec of debug image what has the current mounts mounted somewhere.
Signed-off-by: Kohei Tokunaga <[email protected]>
Signed-off-by: Kohei Tokunaga <[email protected]>
Signed-off-by: Kohei Tokunaga <[email protected]>
Signed-off-by: Kohei Tokunaga <[email protected]>
Signed-off-by: Kohei Tokunaga <[email protected]>
Signed-off-by: Kohei Tokunaga <[email protected]>
Signed-off-by: Kohei Tokunaga <[email protected]>
|
@tonistiigi Thanks for the comments!
In the future, we should create a new session for these cases with user-configured "default" image.
Fixed (8da8ee2)
Fixed(0dd89f6)
Fixed (5a0e4c1).
This is because The following-ups will be separated PRs.
|
tonistiigi
left a comment
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.
Thanks. I think we can merge this now in the current state, but some more follow-ups:
- Let's say I have two different types of errors. One is wrong Dockerfile command and another is process error.
Dockerfile:60
--------------------
59 | ARG TARGETPLATFORM
60 | >>> RUN2 --mount=type=bind,target=. \
61 | >>> --mount=type=cache,target=/root/.cache \
62 | >>> --mount=type=cache,target=/go/pkg/mod \
63 | >>> --mount=type=bind,from=buildx-version,source=/buildx-version,target=/buildx-version <<EOT
64 | set -e
--------------------
ERROR: dockerfile parse error on line 60: unknown instruction: RUN2 (did you mean RUN?)
[+] Building 0.0s (0/0) docker:desktop-linux
Launching interactive container. Press Ctrl-a-c to switch to monitor console
Interactive container was restarted with process "o5e8x1ty9nn2j93m62b8zmhdn". Press Ctrl-a-c to switch to the new container
Switched IO
------
Dockerfile:60
--------------------
59 | ARG TARGETPLATFORM
60 | >>> RUN --mount=type=bind,target=. \
61 | >>> --mount=type=cache,target=/root/.cache \
62 | >>> --mount=type=cache,target=/go/pkg/mod \
63 | >>> --mount=type=bind,from=buildx-version,source=/buildx-version,target=/buildx-version <<EOT
64 | >>> set -e
65 | >>> xx-go2 --wrap
66 | >>> DESTDIR=/usr/bin VERSION=$(cat /buildx-version/version) REVISION=$(cat /buildx-version/revision) GO_EXTRA_LDFLAGS="-s -w" ./hack/build
67 | >>> xx-verify --static /usr/bin/docker-buildx
68 | >>> EOT
69 |
--------------------
ERROR: process "/bin/sh -c set -e\n xx-go2 --wrap\n DESTDIR=/usr/bin VERSION=$(cat /buildx-version/version) REVISION=$(cat /buildx-version/revision) GO_EXTRA_LDFLAGS=\"-s -w\" ./hack/build\n xx-verify --static /usr/bin/docker-buildx\n" did not complete successfully: exit code: 127
[+] Building 0.0s (0/0) docker:desktop-linux
Launching interactive container. Press Ctrl-a-c to switch to monitor console
Interactive container was restarted with process "l3x31fm3i08owokoxwtazeuuw". Press Ctrl-a-c to switch to the new container
/ #
As expected only the second one is debuggable (only second one opens shell as well). But from the output they print same messages about interactive containers and switching IO. It should be more clear that these are different types of errors, why first one does not create execution context and what runs in the shell of second one.
- There is an error in Dockerfile command (eg. change
RUNtoRUN2). I get an error. Now I runreload. It builds up to the Dockerfile error again but this time I don't see any error. It just shows:
(buildx) reload
[+] Building 0.6s (4/4) FINISHED docker:desktop-linux
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 4.74kB 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 45B 0.0s
=> resolve image config for docker.io/docker/dockerfile:1 0.5s
=> CACHED docker-image://docker.io/docker/dockerfile:1@sha256:ac85f380a63b13dfcefa89046420e1781752bab202122f8f50032edf31be0021 0.0s
Interactive container was restarted with process "p1zsu784bbr3orf8t1g5by9j7". Press Ctrl-a-c to switch to the new container
Switched IO
Switched IO
(buildx)
- I run
debug build .and get an error. I fix the error and issuereload. Now my build succeeds. I run some more interactive processes and eventually close the debugger. Now I get an error.
(buildx)
[+] Building 0.0s (0/0) docker:desktop-linux
Dockerfile:60
--------------------
59 | ARG TARGETPLATFORM
60 | >>> RUN2 --mount=type=bind,target=. \
61 | >>> --mount=type=cache,target=/root/.cache \
62 | >>> --mount=type=cache,target=/go/pkg/mod \
63 | >>> --mount=type=bind,from=buildx-version,source=/buildx-version,target=/buildx-version <<EOT
64 | set -e
--------------------
ERROR: dockerfile parse error on line 60: unknown instruction: RUN2 (did you mean RUN?)
What I think is the error from the very first build invocation.
- (We can discuss this more in the issue before any actual work). When I reach an error I don't think there is a way to switch to the clean state before the failed command to try running it again. My options are to reload to rebuild from source or rollback that resets my local changes but I still seem to have the state that the command that failed generated before it errored.
|
Thanks for the feedback. The following will be fixed by #2086
I think the following is already done by
I've recorded Other following-up issues to #1104 (comment) |
This commit refactors the debugger flags by adding
buildx debugcommand that can be used for launching the monitor.This implements the following features proposed by @jedevc and @crazy-max (#1104 (comment))
Examples
This launches a monitor after the build.
/bin/shwill be invoked in the result image.This launches a monitor after the build only when the build fails.
/bin/shwill be invoked in the result image.The following immediately launches the monitor.
Notes
buildx debugand this commit introducesbuildx debugfor launching the monitor directly, this commit removedbuildx build --invoke=debug-shellflag. Please let me know if we shouldn't remove this.I've implementedImplementedbuildx debug shellfor launching monitor but notbuildx debug. Please let me know if we should have both of them.buildx debugbased on the comment debug: Addbuildx debugcommand #2006 (comment) .buildx deubg, the following proposal isn't included in this PR.