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