Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support running from a container #28

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Containerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
FROM quay.io/fedora/fedora:40 as build
RUN dnf install --setopt=install_weak_deps=0 -y \
golang libvirt-devel git-core && \
dnf clean all
COPY . /src
WORKDIR /src
RUN make

FROM quay.io/fedora/fedora:40
RUN dnf install --setopt=install_weak_deps=0 -y \
podman gvisor-tap-vsock qemu-img qemu-kvm-core openssh-clients \
libvirt-client libvirt-daemon-driver-qemu libvirt-daemon-driver-storage-disk && \
dnf clean all
COPY --from=build /src/bin/podman-bootc /usr/bin/
COPY --from=build /src/entrypoint /usr/bin/
RUN useradd podman-bootc -d /cache
# nuke polkit tty agent to silence virsh warnings
RUN rm /usr/bin/pkttyagent
ENTRYPOINT ["/usr/bin/entrypoint"]
34 changes: 33 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,39 @@ Even after you close the SSH connection, the machine continues to run.
- `podman-bootc ssh`: Connect to a VM
- `podman-bootc rm`: Remove a VM

### Architecture
## Running as a container (Linux)

There is also a container image available at `quay.io/podman/podman-bootc` that
makes it more convenient to run podman-bootc on Linux. It can run under rootless
podman. The only requirement is that `/dev/kvm` must be passed through.

In this model, the underlying `podman machine` infrastructure is automatically
brought up on startup and brought down on exit. This allows booting a bootc
container in a single command:

```shell
podman run --rm -ti --device /dev/kvm quay.io/podman/podman-bootc run <image>
```

You can also run the image without passing any command. In that case, you will
be given a shell in which the environment is set up and ready for `podman-bootc`
invocations.

### Caching

You likely will want to enable caching to avoid having to redownload/rederive
artifacts every time. To do this, mount a volume at `/cache`. For example:

```shell
# from a volume
podman volume create podman-bootc
podman run --rm -v podman-bootc:/cache --device /dev/kvm quay.io/podman/podman-bootc run <image>

# from a mountpoint
podman run --rm -v ~/.cache/podman-bootc:/cache:z --device /dev/kvm quay.io/podman/podman-bootc
```

## Architecture

At the current time the `run` command uses a
[bootc install](https://containers.github.io/bootc/bootc-install.html)
Expand Down
74 changes: 74 additions & 0 deletions entrypoint
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/bin/bash
set -euo pipefail

if [ "$(id -u)" = 0 ]; then
# this is normally created by the authentication stack
rundir=/run/user/"$(id -u podman-bootc)"
# shellcheck disable=SC2174
mkdir -m 700 -p "${rundir}"
chown -R podman-bootc:podman-bootc "${rundir}"

rc=0
mountpoint -q /cache || rc=$?
if [ $rc = 0 ]; then
chown -R podman-bootc:podman-bootc /cache
elif [ $rc = 32 ]; then
echo "Note: /cache is not a mountpoint" >&2
echo "Consider mounting a volume on /cache to cache artifacts" >&2
else
echo "Warning: failed checking if /cache is a mountpoint" >&2
fi

# re-exec ourselves as the podman-bootc user
# control flow continues below
exec sudo -u podman-bootc "$0" "$@"
fi

# When hard killing VMs (e.g. by hard killing the container), disk overlays
# can remain; libvirt will choke if they already exist when trying to bring
# up new VMs from the same image. Those files should probably not be under
# XDG_CACHE_HOME in the first place.
if [ -d /cache/.cache/podman-bootc ]; then
find /cache/.cache/podman-bootc -name '*.TRANSIENT-*' -type f -exec rm {} \;
fi

if [ $# -gt 0 ] && [ "$1" != run ]; then
echo "Only the 'run' command is supported in this mode" >&2
echo "To get a shell, do not pass a command" >&2
exit 1
fi

stop() {
podman machine stop bootstrap
touch /cache/.clean-bootstrap-stop
}

trap 'stop' EXIT

# create or recreate or start the bootstrap VM
init_args=(--rootful --timezone UTC --now bootstrap)
if podman machine ls -q | grep -q bootstrap; then
if [ ! -f /cache/.clean-bootstrap-stop ]; then
# to be safe, we recreate the bootstrap node if it wasn't shut down cleanly
podman machine rm bootstrap -f
podman machine init "${init_args[@]}"
else
rm /cache/.clean-bootstrap-stop
podman machine start bootstrap
fi
else
podman machine init "${init_args[@]}"
fi

if [ $# = 0 ]; then
echo "You can now run podman-bootc commands; e.g.:" >&2
echo >&2
echo -e "\tpodman-bootc run --rm quay.io/centos-bootc/centos-bootc:stream9" >&2
echo >&2
bash
elif [ "$1" = run ]; then
podman-bootc "$@"
else
echo "unreachable" >&2
exit 1
fi