1

I'm working on converting my existing CentOS 7 Docker image build process to use Buildah and I'm running into an issue with mknod.

Currently I use the following Dockerfile to build a new image. So basically building an image with an image in order to avoid dependencies on the build host. I run it like this:

docker build -f Dockerfile.builder -t centosbuilder:latest . && \
docker run --rm centosbuilder:latest | docker import - mycentos:latest

And here's the Dockerfile:

FROM centos:7

ENV ROOTFS /image_build_root
ENV TMPDIR /tmp/image_build

WORKDIR ${TMPDIR}
RUN mkdir -p ${ROOTFS}
RUN mkdir -m 755 ${ROOTFS}/dev && \
    mknod -m 600 ${ROOTFS}/dev/console c 5 1 && \
    mknod -m 600 ${ROOTFS}/dev/initctl p && \
    mknod -m 666 ${ROOTFS}/dev/full c 1 7 && \
    mknod -m 666 ${ROOTFS}/dev/null c 1 3 && \
    mknod -m 666 ${ROOTFS}/dev/ptmx c 5 2 && \
    mknod -m 666 ${ROOTFS}/dev/random c 1 8 && \
    mknod -m 666 ${ROOTFS}/dev/tty c 5 0 && \
    mknod -m 666 ${ROOTFS}/dev/tty0 c 4 0 && \
    mknod -m 666 ${ROOTFS}/dev/urandom c 1 9 && \
    mknod -m 666 ${ROOTFS}/dev/zero c 1 5
RUN yum --installroot=${ROOTFS} --releasever=7 --setopt=tsflags=nodocs --setopt=group_package_types=mandatory -y groupinstall Core
RUN yum --installroot=${ROOTFS} -y clean all
RUN echo "NETWORKING=yes" > ${ROOTFS}/etc/sysconfig/network && \
    echo "HOSTNAME=localhost.localdomain" > ${ROOTFS}/etc/sysconfig/network
RUN rm -rf ${ROOTFS}/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive} && \
    #  docs and man pages
    rm -rf ${ROOTFS}/usr/share/{man,doc,info,gnome/help} && \
    #  cracklib
    rm -rf ${ROOTFS}/usr/share/cracklib && \
    #  i18n
    rm -rf ${ROOTFS}/usr/share/i18n && \
    #  yum cache
    rm -rf ${ROOTFS}/var/cache/yum && \
    mkdir -p --mode=0755 ${ROOTFS}/var/cache/yum && \
    #  sln
    rm -rf ${ROOTFS}/sbin/sln && \
    #  ldconfig
    rm -rf ${ROOTFS}/etc/ld.so.cache ${ROOTFS}/var/cache/ldconfig && \
    mkdir -p --mode=0755 ${ROOTFS}/var/cache/ldconfig
CMD /usr/bin/tar -cf - -C ${ROOTFS} .

Using Buildah, I run into my first error on this line:

$ buildah run "${BUILDER}" mknod -m 600 "${ROOTFS}/dev/console" c 5 1
/usr/bin/mknod: '/image_build_root/dev/console': Operation not permitted
ERRO exit status 1

I've tried running my build script (see below) as root to no avail. I assumed maybe the CAP_MKNOD capability wasn't being set, but I get the same error even if I manually enable it.

Build script:

#!/bin/bash -x

set -e

ROOTFS=/image_build_root
TMPDIR=/tmp/image_build

BUILDER="$(buildah from docker.io/library/centos:7)"
buildah config --workingdir "${TMPDIR}" "${BUILDER}"
buildah run "${BUILDER}" mkdir -p "${ROOTFS}"
buildah run "${BUILDER}" mkdir -m 755 "${ROOTFS}/dev"
buildah run --cap-add=CAP_MKNOD "${BUILDER}" mknod -m 600 "${ROOTFS}/dev/console" c 5 1
buildah run "${BUILDER}" mknod -m 600 "${ROOTFS}/dev/initctl" p
buildah run "${BUILDER}" mknod -m 666 "${ROOTFS}/dev/full" c 1 7
buildah run "${BUILDER}" mknod -m 666 "${ROOTFS}/dev/null" c 1 3
buildah run "${BUILDER}" mknod -m 666 "${ROOTFS}/dev/ptmx" c 5 2
buildah run "${BUILDER}" mknod -m 666 "${ROOTFS}/dev/random" c 1 8
buildah run "${BUILDER}" mknod -m 666 "${ROOTFS}/dev/tty" c 5 0
buildah run "${BUILDER}" mknod -m 666 "${ROOTFS}/dev/tty0" c 4 0
buildah run "${BUILDER}" mknod -m 666 "${ROOTFS}/dev/urandom" c 1 9
buildah run "${BUILDER}" mknod -m 666 "${ROOTFS}/dev/zero" c 1 5
buildah run "${BUILDER}" yum \
    --installroot="${ROOTFS}" \
    --releasever=7 \
    --setopt=tsflags=nodocs \
    --setopt=group_package_types=mandatory \
    -y \
    groupinstall Core
buildah run "${BUILDER}" yum --installroot="${ROOTFS}" -y clean all
buildah run "${BUILDER}" echo "NETWORKING=yes" > "${ROOTFS}/etc/sysconfig/network"
buildah run "${BUILDER}" echo "HOSTNAME=localhost.localdomain" > "${ROOTFS}/etc/sysconfig/network"
buildah run "${BUILDER}" rm -rf \
    "${ROOTFS}/usr/{{lib,share}/locale,{lib,lib64}/gconv,bin/localedef,sbin/build-locale-archive}" \
    "${ROOTFS}/usr/share/{man,doc,info,gnome/help}" \
    "${ROOTFS}/usr/share/cracklib" \
    "${ROOTFS}/usr/share/i18n" \
    "${ROOTFS}/var/cache/yum" \
    "${ROOTFS}/sbin/sln" \
    "${ROOTFS}/etc/ld.so.cache" \
    "${ROOTFS}/var/cache/ldconfig"
buildah run "${BUILDER}" mkdir -p --mode=0755 "${ROOTFS}/var/cache/yum"
buildah run "${BUILDER}" mkdir -p --mode=0755 "${ROOTFS}/var/cache/ldconfig"
buildah config --cmd /usr/bin/tar -cf - -C "${ROOTFS}" . "${BUILDER}"
buildah commit "${BUILDER}" centos7builder
BMitch
  • 5,966
  • 1
  • 25
  • 32
Mark C
  • 187
  • 5
  • `mknod` is a priviledged operation and requires **root** priviledges. Run the build process in a [fakeroot shell](https://unix.stackexchange.com/questions/9714/what-is-the-need-for-fakeroot-command-in-linux). – Piotr P. Karwasz Mar 25 '20 at 21:21
  • I still get the same error when I run `fakeroot` then `./build-image.sh`. I get the same error when running as root as well. – Mark C Mar 26 '20 at 14:21
  • What type of filesystem is `/image_build_root` on? Maybe it is mounted with the `nodev` option (cf. the output of `mount`)? – Piotr P. Karwasz Mar 27 '20 at 07:52

1 Answers1

1

An unprivileged user (rootless) has not enough privileges for using mknod, the kernel blocks that. It doesn't matter how many capabilities are left in the user namespace, it won't still be able to use it.

Please refer the following issue.

It is not possible to use mknod and buildah bud/run --isolation="rootless". You need to ignore mknod or use another isolation. It is not possible to mix them. This is awful and nothing can be done.

puchu
  • 126
  • 2