mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-09 03:57:24 +00:00
dev_container: Fix podman and enable unprivileged containers
To enable podman, the Dockerfile has been split into a root run Dockerfile and one that adds a non-root user. The following combinations have been tested: ./tools/dev_container -v --clean --podman --unprivileged ./tools/dev_container -v --clean --podman ./tools/dev_container -v --clean --unprivileged And warnings have been added to ensure users are aware that the only fully supported variant is running a privileged docker container: ./tools/dev_container -v --clean The unprivileged containers will allow us to validate if unit tests require privileged system access. BUG=None TEST=See above Change-Id: I185b1d9c3829674986305b0e72a39b1a4ba11b98 Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/3971029 Reviewed-by: Zihan Chen <zihanchen@google.com> Commit-Queue: Dennis Kempin <denniskempin@google.com> Reviewed-by: Dennis Kempin <denniskempin@google.com>
This commit is contained in:
parent
d57ff28353
commit
6a2b1fda85
5 changed files with 104 additions and 44 deletions
|
@ -40,21 +40,36 @@ CACHE_DIR = os.environ.get("CROSVM_CONTAINER_CACHE", None)
|
|||
DOCKER_ARGS = [
|
||||
# Share cache dir
|
||||
f"--volume {CACHE_DIR}:/cache:rw" if CACHE_DIR else None,
|
||||
# Share devices and syslog
|
||||
# Use tmpfs in the container for faster performance.
|
||||
"--mount type=tmpfs,destination=/tmp",
|
||||
# KVM is required to run a VM for testing.
|
||||
"--device /dev/kvm",
|
||||
f"--env OUTSIDE_UID={os.getuid()}",
|
||||
f"--env OUTSIDE_GID={os.getgid()}",
|
||||
f"gcr.io/crosvm-infra/crosvm_dev_user:{IMAGE_VERSION}",
|
||||
]
|
||||
|
||||
PODMAN_ARGS = [
|
||||
# Share cache dir
|
||||
f"--volume {CACHE_DIR}:/cache:rw" if CACHE_DIR else None,
|
||||
# Use tmpfs in the container for faster performance.
|
||||
"--mount type=tmpfs,destination=/tmp",
|
||||
# KVM is required to run a VM for testing.
|
||||
"--device /dev/kvm",
|
||||
f"gcr.io/crosvm-infra/crosvm_dev:{IMAGE_VERSION}",
|
||||
]
|
||||
|
||||
PRIVILEGED_ARGS = [
|
||||
# Share devices and syslog
|
||||
"--volume /dev/log:/dev/log",
|
||||
"--device /dev/net/tun",
|
||||
"--device /dev/vhost-net",
|
||||
"--device /dev/vhost-vsock",
|
||||
# Use tmpfs in the container for faster performance.
|
||||
"--mount type=tmpfs,destination=/tmp",
|
||||
# For plugin process jail
|
||||
"--mount type=tmpfs,destination=/var/empty",
|
||||
f"--env OUTSIDE_UID={os.getuid()}",
|
||||
f"--env OUTSIDE_GID={os.getgid()}",
|
||||
f"gcr.io/crosvm-infra/crosvm_dev:{IMAGE_VERSION}",
|
||||
]
|
||||
|
||||
|
||||
PODMAN_IS_DEFAULT = shutil.which("docker") == None
|
||||
|
||||
|
||||
|
@ -111,7 +126,9 @@ def ensure_container_is_alive(docker: cmd, docker_args: List[Optional[str]]):
|
|||
|
||||
if not container_is_running(docker):
|
||||
# Run neverending sleep to keep container alive while we 'docker exec' commands.
|
||||
docker(f"run --detach --name {CONTAINER_NAME}", *docker_args, "sleep infinity").stdout()
|
||||
docker(f"run --detach --name {CONTAINER_NAME}", *docker_args, "sleep infinity").fg(
|
||||
quiet=True
|
||||
)
|
||||
cid = container_id(docker)
|
||||
print(f"Started dev-container ({cid}).")
|
||||
else:
|
||||
|
@ -130,22 +147,32 @@ def main(
|
|||
podman: bool = PODMAN_IS_DEFAULT,
|
||||
self_test: bool = False,
|
||||
pull: bool = False,
|
||||
unprivileged: bool = False,
|
||||
):
|
||||
chdir(CROSVM_ROOT)
|
||||
|
||||
docker = cmd("podman" if podman else "docker")
|
||||
docker_args = [
|
||||
# Podman will not share devices when `--privileged` is specified
|
||||
"--privileged" if not podman else None,
|
||||
*workspace_mount_args(),
|
||||
*DOCKER_ARGS,
|
||||
]
|
||||
|
||||
if podman:
|
||||
print("WARNING: Running dev_container with podman is not fully supported.")
|
||||
print("Some crosvm tests require privileges podman cannot provide and may fail.")
|
||||
if unprivileged:
|
||||
print("WARNING: Running dev_container with --unprivileged is a work in progress.")
|
||||
print("Not all tests are expected to pass.")
|
||||
print()
|
||||
|
||||
docker_args = [
|
||||
*workspace_mount_args(),
|
||||
*(PRIVILEGED_ARGS if not unprivileged else []),
|
||||
]
|
||||
if podman:
|
||||
print("WARNING: Running dev_container with podman is experimental.")
|
||||
print("It is strongly recommended to use docker.")
|
||||
print()
|
||||
docker = cmd("podman")
|
||||
docker_args += [*PODMAN_ARGS]
|
||||
else:
|
||||
docker = cmd("docker")
|
||||
docker_args += [
|
||||
"--privileged" if not unprivileged else None,
|
||||
*DOCKER_ARGS,
|
||||
]
|
||||
|
||||
if self_test:
|
||||
TestDevContainer.docker = docker
|
||||
suite = unittest.defaultTestLoader.loadTestsFromTestCase(TestDevContainer)
|
||||
|
@ -162,6 +189,7 @@ def main(
|
|||
|
||||
if pull:
|
||||
docker("pull", f"gcr.io/crosvm-infra/crosvm_dev:{IMAGE_VERSION}").fg()
|
||||
docker("pull", f"gcr.io/crosvm-infra/crosvm_dev_user:{IMAGE_VERSION}").fg()
|
||||
return
|
||||
|
||||
# If a command is provided run non-interactive unless explicitly asked for.
|
||||
|
@ -182,10 +210,14 @@ def main(
|
|||
else:
|
||||
# cmd is executed directly
|
||||
cid = ensure_container_is_alive(docker, docker_args)
|
||||
if not command:
|
||||
command = ("/tools/entrypoint.sh",)
|
||||
if podman:
|
||||
if not command:
|
||||
command = ("/bin/bash",)
|
||||
else:
|
||||
command = ("/tools/entrypoint.sh",) + tuple(command)
|
||||
if not command:
|
||||
command = ("/tools/entrypoint.sh",)
|
||||
else:
|
||||
command = ("/tools/entrypoint.sh",) + tuple(command)
|
||||
quoted_cmd = list(map(quoted, command))
|
||||
docker("exec", *tty_args, cid, *quoted_cmd).fg()
|
||||
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
# Copyright 2021 The ChromiumOS Authors
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# Development container for crosvm.
|
||||
#
|
||||
# Provides all dependencies specified in install-deps with some additonal
|
||||
# logic to cache cargo data in CI runs.
|
||||
#
|
||||
# Note, if you are using docker, you will probably be using "Dockerfile.user".
|
||||
|
||||
FROM docker.io/debian:testing-20220822-slim
|
||||
|
||||
ENV RUSTUP_HOME=/usr/local/rustup \
|
||||
|
@ -36,21 +44,6 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
|
|||
&& ./install-armhf-deps \
|
||||
&& ./install-docs-deps
|
||||
|
||||
# Add a new password-less sudoer user crosvmdev
|
||||
RUN useradd -ms /bin/bash crosvmdev \
|
||||
&& usermod -aG sudo crosvmdev \
|
||||
&& echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
|
||||
# Pass rust envs from rust toolchain image when sudo into new user
|
||||
&& echo 'Defaults env_keep += "RUSTUP_HOME CARGO_HOME RUST_VERSION CARGO_TARGET_DIR"' >> /etc/sudoers \
|
||||
# Allow dependencies and build files to be used and overwritten by user
|
||||
&& chown -R crosvmdev:crosvmdev /scratch /cache
|
||||
|
||||
# Following operations will be run as crosvmdev to ensure correct permission.
|
||||
USER crosvmdev
|
||||
|
||||
# Prepare path to rust toolchain for crosvmdev
|
||||
RUN echo 'export PATH=/cache/cargo_home/bin:/usr/local/cargo/bin:$PATH' >> /home/crosvmdev/.profile
|
||||
|
||||
# Prepare wine64
|
||||
RUN sudo ln -sf /usr/bin/wine64-stable /usr/bin/wine64 \
|
||||
&& wine64 wineboot
|
||||
|
@ -68,9 +61,3 @@ ENV CARGO_HOME=/cache/cargo_home
|
|||
|
||||
VOLUME /workspace
|
||||
WORKDIR /workspace
|
||||
|
||||
# Switch back to root to avoid usermod crosvmdev as crosvmdev
|
||||
USER root
|
||||
COPY tools/impl/dev_container/entrypoint.sh tools/impl/dev_container/setup-user.sh /tools/
|
||||
RUN chmod 755 /tools/entrypoint.sh /tools/setup-user.sh
|
||||
ENTRYPOINT ["/tools/entrypoint.sh"]
|
||||
|
|
33
tools/impl/dev_container/Dockerfile.user
Normal file
33
tools/impl/dev_container/Dockerfile.user
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Copyright 2022 The ChromiumOS Authors
|
||||
# Use of this source code is governed by a BSD-style license that can be
|
||||
# found in the LICENSE file.
|
||||
|
||||
# Extends the "./Dockerfile" created image by adding a non-root user and ensuring
|
||||
# that user can access the necessary files and devices for development.
|
||||
#
|
||||
# This will allow the user to use the same UID/GID inside the container that they have
|
||||
# on the outside, preventing container created files from being owned by root.
|
||||
|
||||
ARG VERSION
|
||||
FROM gcr.io/crosvm-infra/crosvm_dev:${VERSION}
|
||||
|
||||
# Add a new password-less sudoer user crosvmdev
|
||||
RUN useradd -ms /bin/bash crosvmdev \
|
||||
&& usermod -aG sudo crosvmdev \
|
||||
&& echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \
|
||||
# Pass rust envs from rust toolchain image when sudo into new user
|
||||
&& echo 'Defaults env_keep += "RUSTUP_HOME CARGO_HOME RUST_VERSION CARGO_TARGET_DIR"' >> /etc/sudoers \
|
||||
# Allow dependencies and build files to be used and overwritten by user
|
||||
&& chown -R crosvmdev:crosvmdev /scratch /cache
|
||||
|
||||
# Following operations will be run as crosvmdev to ensure correct permission.
|
||||
USER crosvmdev
|
||||
|
||||
# Prepare path to rust toolchain for crosvmdev
|
||||
RUN echo 'export PATH=/cache/cargo_home/bin:/usr/local/cargo/bin:$PATH' >> /home/crosvmdev/.profile
|
||||
|
||||
# Switch back to root to avoid usermod crosvmdev as crosvmdev
|
||||
USER root
|
||||
COPY tools/impl/dev_container/entrypoint.sh tools/impl/dev_container/setup-user.sh /tools/
|
||||
RUN chmod 755 /tools/entrypoint.sh /tools/setup-user.sh
|
||||
ENTRYPOINT ["/tools/entrypoint.sh"]
|
|
@ -23,10 +23,11 @@ BUILD_CONTEXT=$(shell realpath ../../../)
|
|||
|
||||
DOCKER ?= docker
|
||||
|
||||
all: crosvm_dev
|
||||
all: crosvm_dev crosvm_dev_user
|
||||
|
||||
upload: all
|
||||
$(DOCKER) push $(TAG_BASE)/crosvm_dev:$(VERSION)
|
||||
$(DOCKER) push $(TAG_BASE)/crosvm_dev_user:$(VERSION)
|
||||
|
||||
crosvm_dev:
|
||||
$(DOCKER) build \
|
||||
|
@ -34,4 +35,11 @@ crosvm_dev:
|
|||
-f Dockerfile \
|
||||
$(BUILD_CONTEXT)
|
||||
|
||||
crosvm_dev_user:
|
||||
$(DOCKER) build \
|
||||
-t $(TAG_BASE)/$@:$(VERSION) \
|
||||
-f Dockerfile.user \
|
||||
--build-arg=VERSION=$(VERSION) \
|
||||
$(BUILD_CONTEXT)
|
||||
|
||||
.PHONY: all crosvm_dev upload
|
||||
|
|
|
@ -1 +1 @@
|
|||
r0026
|
||||
r0027
|
||||
|
|
Loading…
Reference in a new issue