1#!/usr/bin/env python3 2# 3# Build the required docker image to run package unit tests 4# 5# Script Variables: 6# DOCKER_IMG_NAME: <optional, the name of the docker image to generate> 7# default is openbmc/ubuntu-unit-test 8# DISTRO: <optional, the distro to build a docker image against> 9# default is ubuntu:eoan 10# BRANCH: <optional, branch to build from each of the openbmc/ 11# repositories> 12# default is master, which will be used if input branch not 13# provided or not found 14# UBUNTU_MIRROR: <optional, the URL of a mirror of Ubuntu to override the 15# default ones in /etc/apt/sources.list> 16# default is empty, and no mirror is used. 17# http_proxy The HTTP address of the proxy server to connect to. 18# Default: "", proxy is not setup if this is not set 19 20import os 21import sys 22from sh import docker, git, nproc, uname 23 24# Read a bunch of environment variables. 25docker_image_name = os.environ.get("DOCKER_IMAGE_NAME", "openbmc/ubuntu-unit-test") 26distro = os.environ.get("DISTRO", "ubuntu:focal") 27branch = os.environ.get("BRANCH", "master") 28ubuntu_mirror = os.environ.get("UBUNTU_MIRROR") 29http_proxy = os.environ.get("http_proxy") 30 31# Set up some common variables. 32proc_count = nproc().strip() 33username = os.environ.get("USER") 34homedir = os.environ.get("HOME") 35gid = os.getgid() 36uid = os.getuid() 37 38# Determine the architecture for Docker. 39arch = uname("-m").strip() 40if arch == "ppc64le": 41 docker_base = "ppc64le/" 42elif arch == "x86_64": 43 docker_base = "" 44else: 45 print(f"Unsupported system architecture({arch}) found for docker image") 46 sys.exit(1) 47 48# Packages to include in image. 49packages = { 50 "boost": {"rev": "1.74.0"}, 51 "cereal": {"rev": "v1.3.0"}, 52 "catch2": {"rev": "v2.12.2"}, 53 "CLI11": {"rev": "v1.9.0"}, 54 "fmt": {"rev": "6.2.1"}, 55 # Snapshot from 2020-01-03 56 "function2": {"rev": "3a0746bf5f601dfed05330aefcb6854354fce07d"}, 57 # Snapshot from 2020-02-13 58 "googletest": {"rev": "23b2a3b1cf803999fb38175f6e9e038a4495c8a5"}, 59 # Release 2020-08-06 60 "json": {"rev": "v3.9.1"}, 61 # Snapshot from 2019-05-24 62 "lcov": {"rev": "75fbae1cfc5027f818a0bb865bf6f96fab3202da"}, 63 # dev-5.0 2019-05-03 64 "linux-headers": {"rev": "8bf6567e77f7aa68975b7c9c6d044bba690bf327"}, 65 # Snapshot from 2019-09-03 66 "libvncserver": {"rev": "1354f7f1bb6962dab209eddb9d6aac1f03408110"}, 67 "span-lite": {"rev": "v0.7.0"}, 68 # version from meta-openembedded/meta-oe/recipes-support/libtinyxml2/libtinyxml2_5.0.1.bb 69 "tinyxml2": {"rev": "37bc3aca429f0164adf68c23444540b4a24b5778"}, 70 # version from /meta-openembedded/meta-oe/recipes-devtools/boost-url/boost-url_git.bb 71 "boost-url": {"rev": "a56ae0df6d3078319755fbaa67822b4fa7fd352b"}, 72 # version from meta-openembedded/meta-oe/recipes-devtools/valijson/valijson_git.bb 73 "valijson": {"rev": "c2f22fddf599d04dc33fcd7ed257c698a05345d9"}, 74 # version from meta-openembedded/meta-oe/recipes-devtools/nlohmann-fifo/nlohmann-fifo_git.bb 75 "fifo_map": {"rev": "0dfbf5dacbb15a32c43f912a7e66a54aae39d0f9"}, 76 "open-power/pdbg": {}, 77 "openbmc/gpioplus": {}, 78 "openbmc/phosphor-dbus-interfaces": {}, 79 "openbmc/phosphor-logging": {}, 80 "openbmc/phosphor-objmgr": {}, 81 "openbmc/pldm": {}, 82 "openbmc/sdbusplus": {}, 83 "openbmc/sdeventplus": {}, 84 "openbmc/stdplus": {}, 85} 86 87def pkg_rev(pkg): 88 return packages[pkg]["rev"] 89 90def pkg_stagename(pkg): 91 if not pkg.startswith("openbmc/"): 92 pkg = "openbmc/" + pkg 93 return pkg.replace("/", "-") 94 95# Look up the HEAD for missing a static rev. 96pkg_lookups = {} 97for pkg in packages.keys(): 98 if "rev" in packages[pkg]: 99 continue 100 pkg_lookups[pkg] = git( 101 "ls-remote", "--heads", f"https://github.com/{pkg}", _bg=True 102 ) 103for pkg, result in pkg_lookups.items(): 104 for line in result.stdout.decode().split("\n"): 105 if f"refs/heads/{branch}" in line: 106 packages[pkg]["rev"] = line.strip().split()[0] 107 elif "refs/heads/master" in line and p not in packages: 108 packages[pkg]["rev"] = line.strip().split()[0] 109 110# Create the contents of the '/tmp/depcache'. 111# This needs to be sorted for consistency. 112depcache = "" 113for pkg in sorted(packages.keys()): 114 depcache += "%s:%s," % (pkg, pkg_rev(pkg)) 115 116# Define common flags used for builds 117prefix = "/usr/local" 118configure_flags = " ".join( 119 [ 120 f"--prefix={prefix}", 121 ] 122) 123cmake_flags = " ".join( 124 [ 125 "-DCMAKE_BUILD_TYPE=RelWithDebInfo", 126 "-DBUILD_SHARED_LIBS=ON", 127 f"-DCMAKE_INSTALL_PREFIX:PATH={prefix}", 128 ] 129) 130meson_flags = " ".join( 131 [ 132 "--wrap-mode=nodownload", 133 f"-Dprefix={prefix}", 134 ] 135) 136 137# Build the commands needed to compose our final image 138# We must sort the packages, otherwise we might produce an unstable 139# docker file and rebuild the image unnecessarily 140copy_cmds = "" 141for pkg in sorted(packages.keys()): 142 copy_cmds += f"COPY --from={pkg_stagename(pkg)} {prefix} {prefix}\n" 143 # Workaround for upstream docker bug and multiple COPY cmds 144 # https://github.com/moby/moby/issues/37965 145 copy_cmds += "RUN true\n" 146 147# Special flags if setting up a deb mirror. 148mirror = "" 149if "ubuntu" in distro and ubuntu_mirror: 150 mirror = f""" 151RUN echo "deb {ubuntu_mirror} $(. /etc/os-release && echo $VERSION_CODENAME) main restricted universe multiverse" > /etc/apt/sources.list && \\ 152 echo "deb {ubuntu_mirror} $(. /etc/os-release && echo $VERSION_CODENAME)-updates main restricted universe multiverse" >> /etc/apt/sources.list && \\ 153 echo "deb {ubuntu_mirror} $(. /etc/os-release && echo $VERSION_CODENAME)-security main restricted universe multiverse" >> /etc/apt/sources.list && \\ 154 echo "deb {ubuntu_mirror} $(. /etc/os-release && echo $VERSION_CODENAME)-proposed main restricted universe multiverse" >> /etc/apt/sources.list && \\ 155 echo "deb {ubuntu_mirror} $(. /etc/os-release && echo $VERSION_CODENAME)-backports main restricted universe multiverse" >> /etc/apt/sources.list 156""" 157 158# Special flags for proxying. 159proxy_cmd = "" 160proxy_args = [] 161if http_proxy: 162 proxy_cmd = f""" 163RUN echo "[http]" >> {homedir}/.gitconfig && \ 164 echo "proxy = {http_proxy}" >> {homedir}/.gitconfig 165""" 166 proxy_args.extend( 167 [ 168 "--build-arg", 169 f"http_proxy={http_proxy}", 170 "--build-arg", 171 "https_proxy={https_proxy}", 172 ] 173 ) 174 175# Create docker image that can run package unit tests 176dockerfile = f""" 177FROM {docker_base}{distro} as openbmc-base 178 179{mirror} 180 181ENV DEBIAN_FRONTEND noninteractive 182 183ENV PYTHONPATH "/usr/local/lib/python3.8/site-packages/" 184 185# We need the keys to be imported for dbgsym repos 186# New releases have a package, older ones fall back to manual fetching 187# https://wiki.ubuntu.com/Debug%20Symbol%20Packages 188RUN apt-get update && ( apt-get install ubuntu-dbgsym-keyring || ( apt-get install -yy dirmngr && \ 189 apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F2EDC64DC5AEE1F6B9C621F0C8CAB6595FDFF622 ) ) 190 191# Parse the current repo list into a debug repo list 192RUN sed -n '/^deb /s,^deb [^ ]* ,deb http://ddebs.ubuntu.com ,p' /etc/apt/sources.list >/etc/apt/sources.list.d/debug.list 193 194# Remove non-existent debug repos 195RUN sed -i '/-\(backports\|security\) /d' /etc/apt/sources.list.d/debug.list 196 197RUN cat /etc/apt/sources.list.d/debug.list 198 199RUN apt-get update && apt-get dist-upgrade -yy && apt-get install -yy \ 200 gcc-10 \ 201 g++-10 \ 202 libc6-dbg \ 203 libc6-dev \ 204 libtool \ 205 bison \ 206 libdbus-1-dev \ 207 flex \ 208 cmake \ 209 python3 \ 210 python3-dev\ 211 python3-yaml \ 212 python3-mako \ 213 python3-pip \ 214 python3-setuptools \ 215 python3-git \ 216 python3-socks \ 217 pkg-config \ 218 autoconf \ 219 autoconf-archive \ 220 libsystemd-dev \ 221 systemd \ 222 libssl-dev \ 223 libevdev-dev \ 224 libevdev2-dbgsym \ 225 libjpeg-dev \ 226 libpng-dev \ 227 ninja-build \ 228 sudo \ 229 curl \ 230 git \ 231 dbus \ 232 iputils-ping \ 233 clang-10 \ 234 clang-format-10 \ 235 clang-tidy-10 \ 236 clang-tools-10 \ 237 shellcheck \ 238 npm \ 239 iproute2 \ 240 libnl-3-dev \ 241 libnl-genl-3-dev \ 242 libconfig++-dev \ 243 libsnmp-dev \ 244 valgrind \ 245 valgrind-dbg \ 246 libpam0g-dev \ 247 xxd \ 248 libi2c-dev \ 249 wget \ 250 libldap2-dev \ 251 libprotobuf-dev \ 252 libperlio-gzip-perl \ 253 libjson-perl \ 254 protobuf-compiler \ 255 libgpiod-dev \ 256 device-tree-compiler \ 257 cppcheck \ 258 libpciaccess-dev \ 259 libmimetic-dev \ 260 libxml2-utils \ 261 libxml-simple-perl 262 263RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-10 1000 \ 264 --slave /usr/bin/g++ g++ /usr/bin/g++-10 \ 265 --slave /usr/bin/gcov gcov /usr/bin/gcov-10 \ 266 --slave /usr/bin/gcov-dump gcov-dump /usr/bin/gcov-dump-10 \ 267 --slave /usr/bin/gcov-tool gcov-tool /usr/bin/gcov-tool-10 268 269 270RUN update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 1000 \ 271 --slave /usr/bin/clang++ clang++ /usr/bin/clang++-10 \ 272 --slave /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-10 \ 273 --slave /usr/bin/clang-format clang-format /usr/bin/clang-format-10 \ 274 --slave /usr/bin/run-clang-tidy.py run-clang-tidy.py /usr/bin/run-clang-tidy-10.py 275 276RUN pip3 install inflection 277RUN pip3 install pycodestyle 278RUN pip3 install jsonschema 279RUN pip3 install meson==0.54.3 280RUN pip3 install protobuf 281 282FROM openbmc-base as {pkg_stagename('lcov')} 283RUN curl -L https://github.com/linux-test-project/lcov/archive/{pkg_rev('lcov')}.tar.gz | tar -xz && \ 284cd lcov-* && \ 285make -j{proc_count} && \ 286make install 287 288FROM openbmc-base as {pkg_stagename('function2')} 289RUN mkdir {prefix}/include/function2 && \ 290curl -L -o {prefix}/include/function2/function2.hpp https://raw.githubusercontent.com/Naios/function2/{pkg_rev('function2')}/include/function2/function2.hpp 291 292FROM openbmc-base as {pkg_stagename('googletest')} 293RUN curl -L https://github.com/google/googletest/archive/{pkg_rev('googletest')}.tar.gz | tar -xz && \ 294cd googletest-* && \ 295mkdir build && \ 296cd build && \ 297CXXFLAGS=-std=c++17 cmake {cmake_flags} -DTHREADS_PREFER_PTHREAD_FLAG=ON .. && \ 298make -j{proc_count} && \ 299make install 300 301FROM openbmc-base as {pkg_stagename('catch2')} 302RUN curl -L https://github.com/catchorg/Catch2/archive/{pkg_rev('catch2')}.tar.gz | tar -xz && \ 303cd Catch2-* && \ 304mkdir build && \ 305cd build && \ 306cmake {cmake_flags} -DBUILD_TESTING=OFF -DCATCH_INSTALL_DOCS=OFF .. && \ 307make -j{proc_count} && \ 308make install 309 310FROM openbmc-base as {pkg_stagename('cereal')} 311RUN curl -L https://github.com/USCiLab/cereal/archive/{pkg_rev('cereal')}.tar.gz | tar -xz && \ 312cp -a cereal-*/include/cereal/ {prefix}/include/ 313 314FROM openbmc-base as {pkg_stagename('CLI11')} 315RUN curl -L https://github.com/CLIUtils/CLI11/archive/{pkg_rev('CLI11')}.tar.gz | tar -xz && \ 316cd CLI11-* && \ 317mkdir build && \ 318cd build && \ 319cmake {cmake_flags} -DCLI11_BUILD_DOCS=OFF -DBUILD_TESTING=OFF -DCLI11_BUILD_EXAMPLES=OFF .. && \ 320make -j{proc_count} && \ 321make install 322 323FROM openbmc-base as {pkg_stagename('fmt')} 324RUN curl -L https://github.com/fmtlib/fmt/archive/{pkg_rev('fmt')}.tar.gz | tar -xz && \ 325cd fmt-* && \ 326mkdir build && \ 327cd build && \ 328cmake {cmake_flags} -DFMT_DOC=OFF -DFMT_TEST=OFF .. && \ 329make -j{proc_count} && \ 330make install 331 332FROM openbmc-base as {pkg_stagename('json')} 333RUN mkdir {prefix}/include/nlohmann/ && \ 334curl -L -o {prefix}/include/nlohmann/json.hpp https://github.com/nlohmann/json/releases/download/{pkg_rev('json')}/json.hpp && \ 335ln -s nlohmann/json.hpp {prefix}/include/json.hpp 336 337FROM openbmc-base as {pkg_stagename('fifo_map')} 338RUN curl -L https://github.com/nlohmann/fifo_map/archive/{pkg_rev('fifo_map')}.tar.gz | tar -xz && \ 339cd fifo_map-*/src && cp fifo_map.hpp {prefix}/include/ 340 341FROM openbmc-base as {pkg_stagename('span-lite')} 342RUN curl -L https://github.com/martinmoene/span-lite/archive/{pkg_rev('span-lite')}.tar.gz | tar -xz && \ 343cd span-lite-* && \ 344mkdir build && \ 345cd build && \ 346cmake {cmake_flags} -DSPAN_LITE_OPT_BUILD_TESTS=OFF .. && \ 347make -j{proc_count} && \ 348make install 349 350FROM openbmc-base as {pkg_stagename('linux-headers')} 351RUN curl -L https://github.com/openbmc/linux/archive/{pkg_rev('linux-headers')}.tar.gz | tar -xz && \ 352cd linux-* && \ 353make -j{proc_count} defconfig && \ 354make INSTALL_HDR_PATH=/usr/local headers_install 355 356FROM openbmc-base as {pkg_stagename('boost')} 357RUN curl -L https://dl.bintray.com/boostorg/release/{pkg_rev('boost')}/source/boost_$(echo "{pkg_rev('boost')}" | tr '.' '_').tar.bz2 | tar -xj && \ 358cd boost_*/ && \ 359./bootstrap.sh --prefix={prefix} --with-libraries=context,coroutine && \ 360./b2 && ./b2 install --prefix={prefix} 361 362FROM openbmc-base as {pkg_stagename('tinyxml2')} 363RUN curl -L https://github.com/leethomason/tinyxml2/archive/{pkg_rev('tinyxml2')}.tar.gz | tar -xz && \ 364cd tinyxml2-* && \ 365mkdir build && \ 366cd build && \ 367cmake {cmake_flags} .. && \ 368make -j{proc_count} && \ 369make install 370 371FROM openbmc-base as {pkg_stagename('boost-url')} 372RUN curl -L https://github.com/CPPAlliance/url/archive/{pkg_rev('boost-url')}.tar.gz | tar -xz && \ 373cd url-* && \ 374mkdir buildir && \ 375cd buildir && \ 376cmake {cmake_flags} -DBOOST_URL_STANDALONE=ON -DBOOST_URL_BUILD_TESTS=OFF -DBOOST_URL_BUILD_EXAMPLES=OFF .. && \ 377make -j{proc_count} && \ 378make install 379 380FROM openbmc-base as {pkg_stagename('valijson')} 381RUN curl -L https://github.com/tristanpenman/valijson/archive/{pkg_rev('valijson')}.tar.gz | tar -xz && \ 382cd valijson-* && \ 383mkdir build && \ 384cd build && \ 385cmake {cmake_flags} -DINSTALL_HEADERS=1 -DBUILD_TESTS=0 .. && \ 386make -j{proc_count} && \ 387make install 388 389FROM openbmc-base as {pkg_stagename('libvncserver')} 390RUN curl -L https://github.com/LibVNC/libvncserver/archive/{pkg_rev('libvncserver')}.tar.gz | tar -xz && \ 391cd libvncserver-* && \ 392mkdir build && \ 393cd build && \ 394cmake {cmake_flags} .. && \ 395make -j{proc_count} && \ 396make install 397 398FROM openbmc-base as {pkg_stagename('openbmc/stdplus')} 399COPY --from={pkg_stagename('fmt')} {prefix} {prefix} 400COPY --from={pkg_stagename('span-lite')} {prefix} {prefix} 401RUN curl -L https://github.com/openbmc/stdplus/archive/{pkg_rev('openbmc/stdplus')}.tar.gz | tar -xz && \ 402cd stdplus-* && \ 403meson build {meson_flags} -Dtests=disabled -Dexamples=false && \ 404ninja -C build && \ 405ninja -C build install 406 407FROM openbmc-base as {pkg_stagename('openbmc/sdbusplus')} 408RUN curl -L https://github.com/openbmc/sdbusplus/archive/{pkg_rev('openbmc/sdbusplus')}.tar.gz | tar -xz && \ 409cd sdbusplus-* && \ 410cd tools && ./setup.py install --root=/ --prefix={prefix} && \ 411cd .. && meson build {meson_flags} -Dtests=disabled -Dexamples=disabled && \ 412ninja -C build && \ 413ninja -C build install 414 415FROM openbmc-base as {pkg_stagename('openbmc/sdeventplus')} 416COPY --from={pkg_stagename('function2')} {prefix} {prefix} 417COPY --from={pkg_stagename('openbmc/stdplus')} {prefix} {prefix} 418RUN curl -L https://github.com/openbmc/sdeventplus/archive/{pkg_rev('openbmc/sdeventplus')}.tar.gz | tar -xz && \ 419cd sdeventplus-* && \ 420meson build {meson_flags} -Dtests=disabled -Dexamples=false && \ 421ninja -C build && \ 422ninja -C build install 423 424FROM openbmc-base as {pkg_stagename('openbmc/gpioplus')} 425COPY --from={pkg_stagename('openbmc/stdplus')} {prefix} {prefix} 426RUN curl -L https://github.com/openbmc/gpioplus/archive/{pkg_rev('openbmc/gpioplus')}.tar.gz | tar -xz && \ 427cd gpioplus-* && \ 428meson build {meson_flags} -Dtests=disabled -Dexamples=false && \ 429ninja -C build && \ 430ninja -C build install 431 432FROM openbmc-base as {pkg_stagename('openbmc/phosphor-dbus-interfaces')} 433COPY --from={pkg_stagename('openbmc/sdbusplus')} {prefix} {prefix} 434RUN curl -L https://github.com/openbmc/phosphor-dbus-interfaces/archive/{pkg_rev('openbmc/phosphor-dbus-interfaces')}.tar.gz | tar -xz && \ 435cd phosphor-dbus-interfaces-* && \ 436meson build {meson_flags} -Ddata_org_open_power=true -Ddata_com_ibm=true && \ 437ninja -C build && \ 438ninja -C build install 439 440FROM openbmc-base as {pkg_stagename('openbmc/phosphor-logging')} 441COPY --from={pkg_stagename('cereal')} {prefix} {prefix} 442COPY --from={pkg_stagename('openbmc/sdbusplus')} {prefix} {prefix} 443COPY --from={pkg_stagename('openbmc/sdeventplus')} {prefix} {prefix} 444COPY --from={pkg_stagename('openbmc/phosphor-dbus-interfaces')} {prefix} {prefix} 445COPY --from={pkg_stagename('fifo_map')} {prefix} {prefix} 446RUN curl -L https://github.com/openbmc/phosphor-logging/archive/{pkg_rev('openbmc/phosphor-logging')}.tar.gz | tar -xz && \ 447cd phosphor-logging-* && \ 448./bootstrap.sh && \ 449./configure {configure_flags} --enable-metadata-processing YAML_DIR={prefix}/share/phosphor-dbus-yaml/yaml && \ 450make -j{proc_count} && \ 451make install 452 453FROM openbmc-base as {pkg_stagename('openbmc/phosphor-objmgr')} 454COPY --from={pkg_stagename('boost')} {prefix} {prefix} 455COPY --from={pkg_stagename('openbmc/sdbusplus')} {prefix} {prefix} 456COPY --from={pkg_stagename('tinyxml2')} {prefix} {prefix} 457COPY --from={pkg_stagename('openbmc/phosphor-logging')} {prefix} {prefix} 458RUN curl -L https://github.com/openbmc/phosphor-objmgr/archive/{pkg_rev('openbmc/phosphor-objmgr')}.tar.gz | tar -xz && \ 459cd phosphor-objmgr-* && \ 460./bootstrap.sh && \ 461./configure {configure_flags} && \ 462make -j{proc_count} && \ 463make install 464 465FROM openbmc-base as {pkg_stagename('open-power/pdbg')} 466RUN curl -L https://github.com/open-power/pdbg/archive/{pkg_rev('open-power/pdbg')}.tar.gz | tar -xz && \ 467cd pdbg-* && \ 468./bootstrap.sh && \ 469./configure {configure_flags} && \ 470make -j{proc_count} && \ 471make install 472 473FROM openbmc-base as {pkg_stagename('openbmc/pldm')} 474COPY --from={pkg_stagename('openbmc/sdbusplus')} {prefix} {prefix} 475COPY --from={pkg_stagename('openbmc/sdeventplus')} {prefix} {prefix} 476COPY --from={pkg_stagename('boost')} {prefix} {prefix} 477COPY --from={pkg_stagename('openbmc/phosphor-dbus-interfaces')} {prefix} {prefix} 478COPY --from={pkg_stagename('openbmc/phosphor-logging')} {prefix} {prefix} 479COPY --from={pkg_stagename('json')} {prefix} {prefix} 480COPY --from={pkg_stagename('CLI11')} {prefix} {prefix} 481RUN curl -L https://github.com/openbmc/pldm/archive/{pkg_rev('openbmc/pldm')}.tar.gz | tar -xz && \ 482cd pldm-* && \ 483meson build {meson_flags} -Dlibpldm-only=enabled -Doem-ibm=enabled -Dtests=disabled && \ 484ninja -C build && \ 485ninja -C build install 486 487# Build the final output image 488FROM openbmc-base 489{copy_cmds} 490 491# Some of our infrastructure still relies on the presence of this file 492# even though it is no longer needed to rebuild the docker environment 493# NOTE: The file is sorted to ensure the ordering is stable. 494RUN echo '{depcache}' > /tmp/depcache 495 496# Final configuration for the workspace 497RUN grep -q {gid} /etc/group || groupadd -g {gid} {username} 498RUN mkdir -p "{os.path.dirname(homedir)}" 499RUN grep -q {uid} /etc/passwd || useradd -d {homedir} -m -u {uid} -g {gid} {username} 500RUN sed -i '1iDefaults umask=000' /etc/sudoers 501RUN echo "{username} ALL=(ALL) NOPASSWD: ALL" >>/etc/sudoers 502 503{proxy_cmd} 504 505RUN /bin/bash 506""" 507 508# Do the docker build. 509for line in docker.build( 510 proxy_args, 511 "--network=host", 512 "-t", 513 docker_image_name, 514 "-", 515 _in=dockerfile, 516 _iter=True, 517): 518 print(line, end="", flush=True) 519