xref: /linux/Documentation/dev-tools/container.rst (revision df989b01b5f97dae8f9869cfacbda1308f2182c1)
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