1.. SPDX-License-Identifier: GPL-2.0-only 2.. Copyright (C) 2025 Guillaume Tucker 3 4==================== 5Containerized Builds 6==================== 7 8The ``container`` tool can be used to run any command in the kernel source tree 9from within a container. Doing so facilitates reproducing builds across 10various platforms, for example when a test bot has reported an issue which 11requires a specific version of a compiler or an external test suite. While 12this can already be done by users who are familiar with containers, having a 13dedicated tool in the kernel tree lowers the barrier to entry by solving common 14problems once and for all (e.g. user id management). It also makes it easier 15to share an exact command line leading to a particular result. The main use 16case is likely to be kernel builds but virtually anything can be run: KUnit, 17checkpatch etc. provided a suitable image is available. 18 19 20Options 21======= 22 23Command line syntax:: 24 25 scripts/container -i IMAGE [OPTION]... CMD... 26 27Available options: 28 29``-e, --env-file ENV_FILE`` 30 31 Path to an environment file to load in the container. 32 33``-g, --gid GID`` 34 35 Group id to use inside the container. 36 37``-i, --image IMAGE`` 38 39 Container image name (required). 40 41``-r, --runtime RUNTIME`` 42 43 Container runtime name. Supported runtimes: ``docker``, ``podman``. 44 45 If not specified, the first one found on the system will be used 46 i.e. Podman if present, otherwise Docker. 47 48``-s, --shell`` 49 50 Run the container in an interactive shell. 51 52``-u, --uid UID`` 53 54 User id to use inside the container. 55 56 If the ``-g`` option is not specified, the user id will also be used for 57 the group id. 58 59``-v, --verbose`` 60 61 Enable verbose output. 62 63``-h, --help`` 64 65 Show the help message and exit. 66 67 68Usage 69===== 70 71It's entirely up to the user to choose which image to use and the ``CMD`` 72arguments are passed directly as an arbitrary command line to run in the 73container. The tool will take care of mounting the source tree as the current 74working directory and adjust the user and group id as needed. 75 76The container image which would typically include a compiler toolchain is 77provided by the user and selected via the ``-i`` option. The container runtime 78can be selected with the ``-r`` option, which can be either ``docker`` or 79``podman``. If none is specified, the first one found on the system will be 80used while giving priority to Podman. Support for other runtimes may be added 81later depending on their popularity among users. 82 83By default, commands are run non-interactively. The user can abort a running 84container with SIGINT (Ctrl-C). To run commands interactively with a TTY, the 85``--shell`` or ``-s`` option can be used. Signals will then be received by the 86shell directly rather than the parent ``container`` process. To exit an 87interactive shell, use Ctrl-D or ``exit``. 88 89.. note:: 90 91 The only host requirement aside from a container runtime is Python 3.10 or 92 later. 93 94.. note:: 95 96 Out-of-tree builds are not fully supported yet. The ``O=`` option can 97 however already be used with a relative path inside the source tree to keep 98 separate build outputs. A workaround to build outside the tree is to use 99 ``mount --bind``, see the examples section further down. 100 101 102Environment Variables 103===================== 104 105Environment variables are not propagated to the container so they have to be 106either defined in the image itself or via the ``-e`` option using an 107environment file. In some cases it makes more sense to have them defined in 108the Containerfile used to create the image. For example, a Clang-only compiler 109toolchain image may have ``LLVM=1`` defined. 110 111The local environment file is more useful for user-specific variables added 112during development. It is passed as-is to the container runtime so its format 113may vary. Typically, it will look like the output of ``env``. For example:: 114 115 INSTALL_MOD_STRIP=1 116 SOME_RANDOM_TEXT=One upon a time 117 118Please also note that ``make`` options can still be passed on the command line, 119so while this can't be done since the first argument needs to be the 120executable:: 121 122 scripts/container -i docker.io/tuxmake/korg-clang LLVM=1 make # won't work 123 124this will work:: 125 126 scripts/container -i docker.io/tuxmake/korg-clang make LLVM=1 127 128 129User IDs 130======== 131 132This is an area where the behaviour will vary slightly depending on the 133container runtime. The goal is to run commands as the user invoking the tool. 134With Podman, a namespace is created to map the current user id to a different 135one in the container (1000 by default). With Docker, while this is also 136possible with recent versions it requires a special feature to be enabled in 137the daemon so it's not used here for simplicity. Instead, the container is run 138with the current user id directly. In both cases, this will provide the same 139file permissions for the kernel source tree mounted as a volume. The only 140difference is that when using Docker without a namespace, the user id may not 141be the same as the default one set in the image. 142 143Say, we're using an image which sets up a default user with id 1000 and the 144current user calling the ``container`` tool has id 1234. The kernel source 145tree was checked out by this same user so the files belong to user 1234. With 146Podman, the container will be running as user id 1000 with a mapping to id 1234 147so that the files from the mounted volume appear to belong to id 1000 inside 148the container. With Docker and no namespace, the container will be running 149with user id 1234 which can access the files in the volume but not in the user 1501000 home directory. This shouldn't be an issue when running commands only in 151the kernel tree but it is worth highlighting here as it might matter for 152special corner cases. 153 154.. note:: 155 156 Podman's `Docker compatibility 157 <https://podman-desktop.io/docs/migrating-from-docker/managing-docker-compatibility>`__ 158 mode to run ``docker`` commands on top of a Podman backend is more complex 159 and not fully supported yet. As such, Podman will take priority if both 160 runtimes are available on the system. 161 162 163Examples 164======== 165 166The TuxMake project provides a variety of prebuilt container images available 167on `Docker Hub <https://hub.docker.com/u/tuxmake>`__. Here's the shortest 168example to build a kernel using a TuxMake Clang image:: 169 170 scripts/container -i docker.io/tuxmake/korg-clang -- make LLVM=1 defconfig 171 scripts/container -i docker.io/tuxmake/korg-clang -- make LLVM=1 -j$(nproc) 172 173.. note:: 174 175 When running a command with options within the container, it should be 176 separated with a double dash ``--`` to not confuse them with the 177 ``container`` tool options. Plain commands with no options don't strictly 178 require the double dashes e.g.:: 179 180 scripts/container -i docker.io/tuxmake/korg-clang make mrproper 181 182To run ``checkpatch.pl`` in a ``patches`` directory with a generic Perl image:: 183 184 scripts/container -i perl:slim-trixie scripts/checkpatch.pl patches/* 185 186As an alternative to the TuxMake images, the examples below refer to 187``kernel.org`` images which are based on the `kernel.org compiler toolchains 188<https://mirrors.edge.kernel.org/pub/tools/>`__. These aren't (yet) officially 189available in any public registry but users can build their own locally instead 190using this `experimental repository 191<https://gitlab.com/gtucker/korg-containers>`__ by running ``make 192PREFIX=kernel.org/``. 193 194To build just ``bzImage`` using Clang:: 195 196 scripts/container -i kernel.org/clang -- make bzImage -j$(nproc) 197 198Same with GCC 15 as a particular version tag:: 199 200 scripts/container -i kernel.org/gcc:15 -- make bzImage -j$(nproc) 201 202For an out-of-tree build, a trick is to bind-mount the destination directory to 203a relative path inside the source tree:: 204 205 mkdir -p $HOME/tmp/my-kernel-build 206 mkdir -p build 207 sudo mount --bind $HOME/tmp/my-kernel-build build 208 scripts/container -i kernel.org/gcc -- make mrproper 209 scripts/container -i kernel.org/gcc -- make O=build defconfig 210 scripts/container -i kernel.org/gcc -- make O=build -j$(nproc) 211 212To run KUnit in an interactive shell and get the full output:: 213 214 scripts/container -s -i kernel.org/gcc:kunit -- \ 215 tools/testing/kunit/kunit.py \ 216 run \ 217 --arch=x86_64 \ 218 --cross_compile=x86_64-linux- 219 220To just start an interactive shell:: 221 222 scripts/container -si kernel.org/gcc bash 223 224To build the HTML documentation, which requires the ``kdocs`` image built with 225``make PREFIX=kernel.org/ extra`` as it's not a compiler toolchain:: 226 227 scripts/container -i kernel.org/kdocs make htmldocs 228