container.rst 8.3 KB

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