buildg: Interactive Debugger for Dockerfile

Kohei Tokunaga
nttlabs
Published in
3 min readMay 19, 2022

Debugging Dockerfile is hard. This is even more true of large and highly multi-staged Dockerfile. Though you can inspect the intermediate state of the build by modifying and re-running the Dockerfile, this is time-consuming and your favourite tools might be unavailable on the base image. This makes debugging a 5 min problem take hours.

To solve this issue, we’re working on an interactive debugger for Dockerfile: buildg.

What’s buildg?

buildg is a tool to debug Dockerfile in an interactive and easy-to-use UI/UX.

The UI/UX of buildg is partially inspired by well-known debuggers like gdb and delve but buildg takes Dockerfile instead of C or Go programs.

buildg provides the following features as of now:

  • Source-level inspection
  • Breakpoints and step execution
  • Interactive shell on a step with bringing your own debugging tools
  • Rootless execution

How does buildg work?

buildg is implemented based on BuildKit.

BuildKit is the core of docker build since 18.09. It has features for efficiently building images, including concurrent multi-stage builds.

Because buildg is based on BuildKit, you can use recent Dockerfile syntaxes like bind mounts and here-documents on buildg as well.

buildg is based on BuildKit and takes Dockerfile as the input

Note that buildg is in an early stage and depends on unmerged patches for BuildKit. We’re working on upstreaming them.

Getting started

Release binaries are available from https://github.com/ktock/buildg/releases. runc is needed on your system.

To run buildg as a root user:

$ sudo buildg debug /path/to/context

To run buildg as a non-root user:

$ buildg.sh debug /path/to/context

If you’re using nerdctl, a Docker-compatible CLI for contaiNERD, buildg is available as a subcommand since nerdctl v0.20.

$ nerdctl builder debug /path/to/context

For further information about installing buildg, please refer to the document.

Example of debugging Dockerfile with buildg

This section shows some of the features of buildg through an example. We use buildg v0.1 here. Let’s consider the following Dockerfile which creates a JSON file at the root directory of the image.

FROM busybox
RUN echo foo > /foo
RUN echo bar > /bar
RUN echo "{ \"$(cat /foo)\" : \"$(cat /bar)\" }" > /baz

You can start debugging this Dockerfile using buildg debug command specifying the path to the build context where this Dockerfile is stored. The flag --image specifies the image used for debugging each instruction (discussed later).

$ buildg.sh debug --image ubuntu:22.04 /tmp/ctx

This starts building the Dockerfile and launches an interactive session which accepts the debug commands. The output tells us this build pauses at line 1. (buildg) is the prompt of the debug session.

Filename: "Dockerfile"
=> 1| FROM busybox
2| RUN echo foo > /foo
3| RUN echo bar > /bar
4| RUN echo "{ \"$(cat /foo)\" : \"$(cat /bar)\" }" > /baz
(buildg)

You can set a breakpoint using break command and resume the build using continue command. Then the output shows this build now pauses at line 4 which is a RUN instruction creating a JSON file /baz.

(buildg) break 4
(buildg) continue
...
Breakpoint[0]: reached line: Dockerfile:4
Filename: "Dockerfile"
1| FROM busybox
2| RUN echo foo > /foo
3| RUN echo bar > /bar
*=> 4| RUN echo "{ \"$(cat /foo)\" : \"$(cat /bar)\" }" > /baz

Let’s inspect this RUN instruction deeper by launching a shell using exec command. Though this instruction is based on busybox, the flag --image allows you to debug it using the image specified to buildg debug (ubuntu:22.04 in this example) instead. So you can use your favourite system and tools. Here, we install and use jq command for inspecting /baz formatted as JSON.

(buildg) exec --image sh
# apt-get update -y && apt-get install -y jq

The instruction’s rootfs is mounted at /debugroot by default. So baz is accessible at /debugroot/baz.

# cat /debugroot/baz | jq .foo
"bar"

You can go back to the debug session by quitting the shell using Ctrl-D. Then you can resume the build using continue command.

# [Ctrl-D]
(buildg) continue

This section briefly introduced some of the features of buildg. For complete command reference, please refer to the documentation.

NTT is hiring!

We NTT is looking for engineers who work in Open Source communities like containerd, Docker/Moby and Kubernetes. Visit https://www.rd.ntt/e/sic/recruit/ to see how to join us.

--

--