* Re: [PATCH v1 1/2] scripts: add tool to run containerized builds
2025-12-10 13:58 ` [PATCH v1 1/2] scripts: add tool to run " Guillaume Tucker
@ 2025-12-13 4:16 ` Guillaume Tucker
2025-12-15 9:24 ` Onur Özkan
` (2 subsequent siblings)
3 siblings, 0 replies; 10+ messages in thread
From: Guillaume Tucker @ 2025-12-13 4:16 UTC (permalink / raw)
To: Nathan Chancellor, Miguel Ojeda
Cc: linux-kernel, rust-for-linux, linux-kbuild, automated-testing,
workflows, llvm, Arnd Bergmann, Onur Özkan
[+Onur - sorry I didn't Cc you when sending this series]
On 10/12/2025 2:58 pm, Guillaume Tucker wrote:
> +def run_docker(args):
> + """Run a command in a Docker container"""
> + uid = args.uid or os.getuid()
> + gid = args.gid or args.uid or os.getgid()
> + cmd = [
> + 'docker', 'run',
> + '--interactive',
> + '--volume', f'{os.getcwd()}:/src',
> + '--workdir', '/src',
> + '--user', f'{uid}:{gid}'
> + ]
> + if args.env_file:
> + cmd += ['--env-file', args.env_file]
> + cmd.append(args.image)
> + cmd += args.cmd
> + return subprocess.call(cmd)
Just realised that it also needs a TTY to handle Ctrl-C signals
correctly, otherwise the Python process would stop but the container
would keep running in a detached process (same for podman):
diff --git a/scripts/container b/scripts/container
index 74644ac33685..e05425c06d28 100755
--- a/scripts/container
+++ b/scripts/container
@@ -30,6 +30,7 @@ def run_docker(args):
cmd = [
'docker', 'run',
'--interactive',
+ '--tty',
'--volume', f'{os.getcwd()}:/src',
'--workdir', '/src',
'--user', f'{uid}:{gid}'
I'll send a v2 next week, but I'll wait a bit for any feedback first.
Thanks,
Guillaume
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v1 1/2] scripts: add tool to run containerized builds
2025-12-10 13:58 ` [PATCH v1 1/2] scripts: add tool to run " Guillaume Tucker
2025-12-13 4:16 ` Guillaume Tucker
@ 2025-12-15 9:24 ` Onur Özkan
2025-12-15 10:15 ` Guillaume Tucker
2025-12-17 9:56 ` [Automated-testing] " David Gow
2025-12-19 19:47 ` Nathan Chancellor
3 siblings, 1 reply; 10+ messages in thread
From: Onur Özkan @ 2025-12-15 9:24 UTC (permalink / raw)
To: Guillaume Tucker
Cc: Nathan Chancellor, Miguel Ojeda, linux-kernel, rust-for-linux,
linux-kbuild, automated-testing, workflows, llvm, Arnd Bergmann
Hi Guillaume,
Excellent work! Just one note from my side so far:
On Wed, 10 Dec 2025 14:58:28 +0100
Guillaume Tucker <gtucker@gtucker.io> wrote:
> Add a 'scripts/container' tool written in Python to run any command in
> the source tree from within a container. This can typically be used
> to call 'make' with a compiler toolchain image to run reproducible
> builds but any arbitrary command can be run too. Only Docker and
> Podman are supported for this initial version.
>
> Cc: Nathan Chancellor <nathan@kernel.org>
> Cc: Miguel Ojeda <ojeda@kernel.org>
> Link:
> https://lore.kernel.org/all/affb7aff-dc9b-4263-bbd4-a7965c19ac4e@gtucker.io/
> Signed-off-by: Guillaume Tucker <gtucker@gtucker.io> ---
> scripts/container | 112
> ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112
> insertions(+) create mode 100755 scripts/container
>
> diff --git a/scripts/container b/scripts/container
> new file mode 100755
> index 000000000000..74644ac33685
> --- /dev/null
> +++ b/scripts/container
> @@ -0,0 +1,112 @@
> +#!/bin/env python3
By default, this will not work on NixOS because /bin/env is
not a valid path.
It will fail like this:
$ cat something
#!/bin/env python3
$ ./something
zsh: ./something: bad interpreter: /bin/env: no such file or
directory
Is there a reason for not using /usr/bin/env?
> +# SPDX-License-Identifier: GPL-2.0-only
> +# Copyright (C) 2025 Guillaume Tucker
> +
> +"""Containerized builds"""
> +
> +import argparse
> +import logging
> +import os
> +import subprocess
> +import sys
> +
> +
> +def get_logger(verbose):
> + """Set up a logger with the appropriate level"""
> + logger = logging.getLogger('container')
> + handler = logging.StreamHandler()
> + handler.setFormatter(logging.Formatter(
> + fmt='[container {levelname}] {message}', style='{'
> + ))
> + logger.addHandler(handler)
> + logger.setLevel(logging.DEBUG if verbose is True else
> logging.INFO)
> + return logger
> +
> +
> +def run_docker(args):
> + """Run a command in a Docker container"""
> + uid = args.uid or os.getuid()
> + gid = args.gid or args.uid or os.getgid()
> + cmd = [
> + 'docker', 'run',
> + '--interactive',
> + '--volume', f'{os.getcwd()}:/src',
> + '--workdir', '/src',
> + '--user', f'{uid}:{gid}'
> + ]
> + if args.env_file:
> + cmd += ['--env-file', args.env_file]
> + cmd.append(args.image)
> + cmd += args.cmd
> + return subprocess.call(cmd)
> +
> +
> +def run_podman(args):
> + """Run a command in a Podman container"""
> + uid = args.uid or 1000
> + gid = args.gid or args.uid or 1000
> + cmd = [
> + 'podman', 'run',
> + '--interactive',
> + '--volume', f'{os.getcwd()}:/src',
> + '--workdir', '/src',
> + '--userns', f'keep-id:uid={uid},gid={gid}',
> + ]
> + if args.env_file:
> + cmd += ['--env-file', args.env_file]
> + cmd.append(args.image)
> + cmd += args.cmd
> + return subprocess.call(cmd)
> +
> +
> +def main(args):
> + """Main entry point for the container tool"""
> + logger = get_logger(args.verbose)
> + logger.debug("runtime=%s, image=%s", args.runtime, args.image)
> + runtimes = {
> + 'docker': run_docker,
> + 'podman': run_podman,
> + }
> + handler = runtimes.get(args.runtime)
> + if not handler:
> + logger.error("Unknown container runtime: %s", args.runtime)
> + return 1
> + try:
> + return handler(args)
> + except KeyboardInterrupt:
> + logger.error("aborted")
> + return 1
> +
> +
> +if __name__ == '__main__':
> + parser = argparse.ArgumentParser("Containerized builds")
> + parser.add_argument(
> + '-e', '--env-file',
> + help="Path to an environment file to load in the container."
> + )
> + parser.add_argument(
> + '-g', '--gid',
> + help="Group ID to use inside the container."
> + )
> + parser.add_argument(
> + '-i', '--image', default='gcc',
> + help="Container image, default is gcc."
> + )
> + parser.add_argument(
> + '-r', '--runtime', choices=['docker', 'podman'],
> default='docker',
> + help="Container runtime, default is docker."
> + )
> + parser.add_argument(
> + '-u', '--uid',
> + help="User ID to use inside the container. If the -g option
> is not"
> + "specified, the user ID will also be used for the group ID."
> + )
> + parser.add_argument(
> + '-v', '--verbose', action='store_true',
> + help="Enable verbose output."
> + )
> + parser.add_argument(
> + 'cmd', nargs='+',
> + help="Command to run in the container"
> + )
> + sys.exit(main(parser.parse_args(sys.argv[1:])))
-Onur
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v1 1/2] scripts: add tool to run containerized builds
2025-12-15 9:24 ` Onur Özkan
@ 2025-12-15 10:15 ` Guillaume Tucker
0 siblings, 0 replies; 10+ messages in thread
From: Guillaume Tucker @ 2025-12-15 10:15 UTC (permalink / raw)
To: Onur Özkan
Cc: Nathan Chancellor, Miguel Ojeda, linux-kernel, rust-for-linux,
linux-kbuild, automated-testing, workflows, llvm, Arnd Bergmann
Hi Onur,
On 15/12/2025 10:24 am, Onur Özkan wrote:
> Hi Guillaume,
>
> Excellent work! Just one note from my side so far:
Thanks for the review!
> On Wed, 10 Dec 2025 14:58:28 +0100
> Guillaume Tucker<gtucker@gtucker.io> wrote:
>
>> Add a 'scripts/container' tool written in Python to run any command in
>> the source tree from within a container. This can typically be used
>> to call 'make' with a compiler toolchain image to run reproducible
>> builds but any arbitrary command can be run too. Only Docker and
>> Podman are supported for this initial version.
>>
>> Cc: Nathan Chancellor<nathan@kernel.org>
>> Cc: Miguel Ojeda<ojeda@kernel.org>
>> Link:
>> https://lore.kernel.org/all/affb7aff-dc9b-4263-bbd4-
>> a7965c19ac4e@gtucker.io/
>> Signed-off-by: Guillaume Tucker<gtucker@gtucker.io> ---
>> scripts/container | 112
>> ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 112
>> insertions(+) create mode 100755 scripts/container
>>
>> diff --git a/scripts/container b/scripts/container
>> new file mode 100755
>> index 000000000000..74644ac33685
>> --- /dev/null
>> +++ b/scripts/container
>> @@ -0,0 +1,112 @@
>> +#!/bin/env python3
> By default, this will not work on NixOS because /bin/env is
> not a valid path.
>
> It will fail like this:
>
> $ cat something
> #!/bin/env python3
>
> $ ./something
> zsh: ./something: bad interpreter: /bin/env: no such file or
> directory
>
> Is there a reason for not using /usr/bin/env?
Ah sorry, my bad. I initially started writing this as a shell script
using /bin/sh and typed it wrong when changing to Python. So I'll
fix it in v2, thanks for flagging this (pylint didn't...).
Another change I want to make is to drop the default image as 'gcc'
doesn't really help. If the user hasn't set a custom tag, it will
pull some generic image from docker.io which won't have all the tools
needed to build a kernel. So making the -i option required or
turning it into a positional argument would be better than some
implicit behaviour. I'll start a separate thread with Konstantin and
Arnd about hosting kernel.org toolchain container images as having
that should make the tool much more useful and we might set valid
default values e.g. kernel.org/gcc.
Cheers,
Guillaume
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Automated-testing] [PATCH v1 1/2] scripts: add tool to run containerized builds
2025-12-10 13:58 ` [PATCH v1 1/2] scripts: add tool to run " Guillaume Tucker
2025-12-13 4:16 ` Guillaume Tucker
2025-12-15 9:24 ` Onur Özkan
@ 2025-12-17 9:56 ` David Gow
2025-12-17 13:51 ` Guillaume Tucker
2025-12-19 19:47 ` Nathan Chancellor
3 siblings, 1 reply; 10+ messages in thread
From: David Gow @ 2025-12-17 9:56 UTC (permalink / raw)
To: gtucker
Cc: Nathan Chancellor, Miguel Ojeda, linux-kernel, rust-for-linux,
linux-kbuild, automated-testing, workflows, llvm, Arnd Bergmann
[-- Attachment #1: Type: text/plain, Size: 1028 bytes --]
On Wed, 10 Dec 2025 at 21:58, Guillaume Tucker via
lists.yoctoproject.org <gtucker=gtucker.io@lists.yoctoproject.org>
wrote:
>
> Add a 'scripts/container' tool written in Python to run any command in
> the source tree from within a container. This can typically be used
> to call 'make' with a compiler toolchain image to run reproducible
> builds but any arbitrary command can be run too. Only Docker and
> Podman are supported for this initial version.
>
> Cc: Nathan Chancellor <nathan@kernel.org>
> Cc: Miguel Ojeda <ojeda@kernel.org>
> Link: https://lore.kernel.org/all/affb7aff-dc9b-4263-bbd4-a7965c19ac4e@gtucker.io/
> Signed-off-by: Guillaume Tucker <gtucker@gtucker.io>
> ---
I gave this a go, and am liking it so far. My only real complaints are
that the defaults don't totally match my prejudices. :-)
Having a good default container, and perhaps falling back
automatically to podman if docker isn't running (or just defaulting to
podman) would make this very convenient for one-line
tests/reproducers.
-- David
[-- Attachment #2: S/MIME Cryptographic Signature --]
[-- Type: application/pkcs7-signature, Size: 5281 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [Automated-testing] [PATCH v1 1/2] scripts: add tool to run containerized builds
2025-12-17 9:56 ` [Automated-testing] " David Gow
@ 2025-12-17 13:51 ` Guillaume Tucker
0 siblings, 0 replies; 10+ messages in thread
From: Guillaume Tucker @ 2025-12-17 13:51 UTC (permalink / raw)
To: David Gow
Cc: Nathan Chancellor, Miguel Ojeda, linux-kernel, rust-for-linux,
linux-kbuild, automated-testing, workflows, llvm, Arnd Bergmann
Hello David,
On 17/12/2025 10:56 am, David Gow wrote:
> On Wed, 10 Dec 2025 at 21:58, Guillaume Tucker via
> lists.yoctoproject.org <gtucker=gtucker.io@lists.yoctoproject.org>
> wrote:
>>
>> Add a 'scripts/container' tool written in Python to run any command in
>> the source tree from within a container. This can typically be used
>> to call 'make' with a compiler toolchain image to run reproducible
>> builds but any arbitrary command can be run too. Only Docker and
>> Podman are supported for this initial version.
>>
>> Cc: Nathan Chancellor <nathan@kernel.org>
>> Cc: Miguel Ojeda <ojeda@kernel.org>
>> Link: https://lore.kernel.org/all/affb7aff-dc9b-4263-bbd4-a7965c19ac4e@gtucker.io/
>> Signed-off-by: Guillaume Tucker <gtucker@gtucker.io>
>> ---
>
> I gave this a go, and am liking it so far. My only real complaints are
> that the defaults don't totally match my prejudices. :-)
>
> Having a good default container, and perhaps falling back
> automatically to podman if docker isn't running (or just defaulting to
> podman) would make this very convenient for one-line
> tests/reproducers.
Many thanks for your feedback, I'm glad that worked for you.
Yes, the default 'gcc' image doesn't actually work in practice. I've
proposed something else in another email to drop the default for now
but aim to provide "first-party" container images using kernel.org
toolchains which may give us some useful default later on.
Then good point about the default container runtime, I'll update the
logic to automatically look for Docker and Podman - basically iterate
through the supported runtimes - in the v2.
Cheers,
Guillaume
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v1 1/2] scripts: add tool to run containerized builds
2025-12-10 13:58 ` [PATCH v1 1/2] scripts: add tool to run " Guillaume Tucker
` (2 preceding siblings ...)
2025-12-17 9:56 ` [Automated-testing] " David Gow
@ 2025-12-19 19:47 ` Nathan Chancellor
2025-12-19 21:15 ` Nathan Chancellor
3 siblings, 1 reply; 10+ messages in thread
From: Nathan Chancellor @ 2025-12-19 19:47 UTC (permalink / raw)
To: Guillaume Tucker
Cc: Miguel Ojeda, linux-kernel, rust-for-linux, linux-kbuild,
automated-testing, workflows, llvm, Arnd Bergmann
Hi Guillaume,
On Wed, Dec 10, 2025 at 02:58:28PM +0100, Guillaume Tucker wrote:
> Add a 'scripts/container' tool written in Python to run any command in
> the source tree from within a container. This can typically be used
> to call 'make' with a compiler toolchain image to run reproducible
> builds but any arbitrary command can be run too. Only Docker and
> Podman are supported for this initial version.
>
> Cc: Nathan Chancellor <nathan@kernel.org>
> Cc: Miguel Ojeda <ojeda@kernel.org>
> Link: https://lore.kernel.org/all/affb7aff-dc9b-4263-bbd4-a7965c19ac4e@gtucker.io/
> Signed-off-by: Guillaume Tucker <gtucker@gtucker.io>
Overall, I like the concept here. It is simple and should be relatively
easy for people to drive. I think having some short quick examples (or a
link to the Documentation file that inclues them) would be good in case
people stumble across the script first.
One initial comment (or perhaps feature request) would be handling O= /
KBUILD_OUTPUT for building out of tree. It may be a little complicated
for mounting the build directory into the container but it might make it
easier for folks who build out of tree to use.
> ---
> scripts/container | 112 ++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 112 insertions(+)
> create mode 100755 scripts/container
>
> diff --git a/scripts/container b/scripts/container
> new file mode 100755
> index 000000000000..74644ac33685
> --- /dev/null
> +++ b/scripts/container
> @@ -0,0 +1,112 @@
> +#!/bin/env python3
> +# SPDX-License-Identifier: GPL-2.0-only
> +# Copyright (C) 2025 Guillaume Tucker
> +
> +"""Containerized builds"""
> +
> +import argparse
> +import logging
> +import os
> +import subprocess
> +import sys
> +
> +
> +def get_logger(verbose):
> + """Set up a logger with the appropriate level"""
> + logger = logging.getLogger('container')
> + handler = logging.StreamHandler()
> + handler.setFormatter(logging.Formatter(
> + fmt='[container {levelname}] {message}', style='{'
> + ))
> + logger.addHandler(handler)
> + logger.setLevel(logging.DEBUG if verbose is True else logging.INFO)
> + return logger
> +
> +
> +def run_docker(args):
> + """Run a command in a Docker container"""
> + uid = args.uid or os.getuid()
> + gid = args.gid or args.uid or os.getgid()
> + cmd = [
> + 'docker', 'run',
> + '--interactive',
> + '--volume', f'{os.getcwd()}:/src',
Is there a minimum python version required for this? If not, I would
prefer using pathlib here:
from pathlib import Path
then
Path.cwd()
> + '--workdir', '/src',
> + '--user', f'{uid}:{gid}'
> + ]
> + if args.env_file:
> + cmd += ['--env-file', args.env_file]
> + cmd.append(args.image)
> + cmd += args.cmd
> + return subprocess.call(cmd)
> +
> +
> +def run_podman(args):
> + """Run a command in a Podman container"""
> + uid = args.uid or 1000
> + gid = args.gid or args.uid or 1000
Why 1000 instead of using getuid() and getgid() as above?
> + cmd = [
> + 'podman', 'run',
> + '--interactive',
> + '--volume', f'{os.getcwd()}:/src',
> + '--workdir', '/src',
> + '--userns', f'keep-id:uid={uid},gid={gid}',
> + ]
> + if args.env_file:
> + cmd += ['--env-file', args.env_file]
> + cmd.append(args.image)
> + cmd += args.cmd
> + return subprocess.call(cmd)
Most of these two functions are the same. Maybe they could be abstracted
into a simple class so that most of the logic could be shared between
the two implementations? That also might simplify main() a bit and make
fulfilling David's request a little simpler as well.
> +def main(args):
> + """Main entry point for the container tool"""
> + logger = get_logger(args.verbose)
> + logger.debug("runtime=%s, image=%s", args.runtime, args.image)
> + runtimes = {
> + 'docker': run_docker,
> + 'podman': run_podman,
> + }
> + handler = runtimes.get(args.runtime)
> + if not handler:
> + logger.error("Unknown container runtime: %s", args.runtime)
> + return 1
> + try:
> + return handler(args)
> + except KeyboardInterrupt:
> + logger.error("aborted")
> + return 1
> +
> +
> +if __name__ == '__main__':
> + parser = argparse.ArgumentParser("Containerized builds")
> + parser.add_argument(
> + '-e', '--env-file',
> + help="Path to an environment file to load in the container."
> + )
Is there documentation for how an environment file should be formatter?
> + parser.add_argument(
> + '-g', '--gid',
> + help="Group ID to use inside the container."
> + )
> + parser.add_argument(
> + '-i', '--image', default='gcc',
> + help="Container image, default is gcc."
> + )
> + parser.add_argument(
> + '-r', '--runtime', choices=['docker', 'podman'], default='docker',
> + help="Container runtime, default is docker."
> + )
> + parser.add_argument(
> + '-u', '--uid',
> + help="User ID to use inside the container. If the -g option is not"
> + "specified, the user ID will also be used for the group ID."
> + )
> + parser.add_argument(
> + '-v', '--verbose', action='store_true',
> + help="Enable verbose output."
> + )
> + parser.add_argument(
> + 'cmd', nargs='+',
> + help="Command to run in the container"
> + )
> + sys.exit(main(parser.parse_args(sys.argv[1:])))
> --
> 2.47.3
>
^ permalink raw reply [flat|nested] 10+ messages in thread* Re: [PATCH v1 1/2] scripts: add tool to run containerized builds
2025-12-19 19:47 ` Nathan Chancellor
@ 2025-12-19 21:15 ` Nathan Chancellor
0 siblings, 0 replies; 10+ messages in thread
From: Nathan Chancellor @ 2025-12-19 21:15 UTC (permalink / raw)
To: Guillaume Tucker
Cc: Miguel Ojeda, linux-kernel, rust-for-linux, linux-kbuild,
automated-testing, workflows, llvm, Arnd Bergmann
On Fri, Dec 19, 2025 at 12:47:48PM -0700, Nathan Chancellor wrote:
> Most of these two functions are the same. Maybe they could be abstracted
> into a simple class so that most of the logic could be shared between
> the two implementations? That also might simplify main() a bit and make
> fulfilling David's request a little simpler as well.
Sigh, this is what I get for working through my inbox bottom up since I
see that you did this in v2 :) looks good, I will give a couple more
comments there.
^ permalink raw reply [flat|nested] 10+ messages in thread