tests/docker: add basic user mapping support

Currently all docker builds are done by exporting a tarball to the
docker container and running the build as the containers root user.
Other use cases are possible however and it is possible to map a part
of users file-system to the container. This is useful for example for
doing cross-builds of arbitrary source trees. For this to work
smoothly the container needs to have a user created that maps cleanly
to the host system.

This adds a -u option to the docker script so that:

  DEB_ARCH=armhf DEB_TYPE=stable ./tests/docker/docker.py build \
    -u --include-executable=arm-linux-user/qemu-arm \
    debian:armhf ./tests/docker/dockerfiles/debian-bootstrap.docker

Will build a container that can then be run like:

  docker run --rm -it -v /home/alex/lsrc/qemu/risu.git/:/src \
    --user=alex:alex -w /src/ debian:armhf \
    sh -c "make clean && ./configure -s && make"

All docker containers built will add the current user unless
explicitly disabled by specifying NOUSER when invoking the Makefile:

  make docker-image-debian-armhf-cross NOUSER=1

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Fam Zheng <famz@redhat.com>
Tested-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-Id: <20170220105139.21581-2-alex.bennee@linaro.org>
Signed-off-by: Fam Zheng <famz@redhat.com>
This commit is contained in:
Alex Bennée 2017-02-20 10:51:36 +00:00 committed by Fam Zheng
parent 10f25e4844
commit 414a8ce57e
2 changed files with 16 additions and 2 deletions

View file

@ -50,6 +50,7 @@ docker-image-%: $(DOCKER_FILES_DIR)/%.docker
$(call quiet-command,\ $(call quiet-command,\
$(SRC_PATH)/tests/docker/docker.py build qemu:$* $< \ $(SRC_PATH)/tests/docker/docker.py build qemu:$* $< \
$(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \ $(if $V,,--quiet) $(if $(NOCACHE),--no-cache) \
$(if $(NOUSER),,--add-current-user) \
$(if $(EXECUTABLE),--include-executable=$(EXECUTABLE)),\ $(if $(EXECUTABLE),--include-executable=$(EXECUTABLE)),\
"BUILD","$*") "BUILD","$*")
@ -99,6 +100,7 @@ docker:
@echo ' (default is 1)' @echo ' (default is 1)'
@echo ' DEBUG=1 Stop and drop to shell in the created container' @echo ' DEBUG=1 Stop and drop to shell in the created container'
@echo ' before running the command.' @echo ' before running the command.'
@echo ' NOUSER Define to disable adding current user to containers passwd.'
@echo ' NOCACHE=1 Ignore cache when build images.' @echo ' NOCACHE=1 Ignore cache when build images.'
@echo ' EXECUTABLE=<path> Include executable in image.' @echo ' EXECUTABLE=<path> Include executable in image.'

View file

@ -25,6 +25,7 @@ import signal
from tarfile import TarFile, TarInfo from tarfile import TarFile, TarInfo
from StringIO import StringIO from StringIO import StringIO
from shutil import copy, rmtree from shutil import copy, rmtree
from pwd import getpwuid
DEVNULL = open(os.devnull, 'wb') DEVNULL = open(os.devnull, 'wb')
@ -149,13 +150,21 @@ class Docker(object):
labels = json.loads(resp)[0]["Config"].get("Labels", {}) labels = json.loads(resp)[0]["Config"].get("Labels", {})
return labels.get("com.qemu.dockerfile-checksum", "") return labels.get("com.qemu.dockerfile-checksum", "")
def build_image(self, tag, docker_dir, dockerfile, quiet=True, argv=None): def build_image(self, tag, docker_dir, dockerfile,
quiet=True, user=False, argv=None):
if argv == None: if argv == None:
argv = [] argv = []
tmp_df = tempfile.NamedTemporaryFile(dir=docker_dir, suffix=".docker") tmp_df = tempfile.NamedTemporaryFile(dir=docker_dir, suffix=".docker")
tmp_df.write(dockerfile) tmp_df.write(dockerfile)
if user:
uid = os.getuid()
uname = getpwuid(uid).pw_name
tmp_df.write("\n")
tmp_df.write("RUN id %s 2>/dev/null || useradd -u %d -U %s" %
(uname, uid, uname))
tmp_df.write("\n") tmp_df.write("\n")
tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" % tmp_df.write("LABEL com.qemu.dockerfile-checksum=%s" %
_text_checksum(dockerfile)) _text_checksum(dockerfile))
@ -225,6 +234,9 @@ class BuildCommand(SubCommand):
help="""Specify a binary that will be copied to the help="""Specify a binary that will be copied to the
container together with all its dependent container together with all its dependent
libraries""") libraries""")
parser.add_argument("--add-current-user", "-u", dest="user",
action="store_true",
help="Add the current user to image's passwd")
parser.add_argument("tag", parser.add_argument("tag",
help="Image Tag") help="Image Tag")
parser.add_argument("dockerfile", parser.add_argument("dockerfile",
@ -261,7 +273,7 @@ class BuildCommand(SubCommand):
docker_dir) docker_dir)
dkr.build_image(tag, docker_dir, dockerfile, dkr.build_image(tag, docker_dir, dockerfile,
quiet=args.quiet, argv=argv) quiet=args.quiet, user=args.user, argv=argv)
rmtree(docker_dir) rmtree(docker_dir)